Найти в Дзене
WebTutorials

Различные способы получения градиентных теней CSS. Часть 2

Оглавление

Читайте начало статьи по ссылке.

градиентная тень контейнера с прозрачным фоном и border-radius
градиентная тень контейнера с прозрачным фоном и border-radius

Добавление радиуса границы

Если вы попытаетесь добавить border-radius к элементу при использовании непрозрачного решения, с которого мы начали, это будет довольно тривиальная задача. Все, что вам нужно сделать, это наследовать то же значение от основного элемента, и все готово.

-2

Даже если у вас нет радиуса границы, рекомендуется определить border-radius: inherit. Это учитывает любой потенциальный радиус границы, который вы, возможно, захотите добавить позже, или радиус границы, полученный откуда-то еще.

Другое дело, когда имеешь дело с прозрачным решением. К сожалению, это означает поиск другого решения, потому что clip-path не может справиться с кривизной. Это означает, что мы не сможем вырезать область внутри основного элемента.

Мы введем в микс свойство mask.

Эта часть была очень утомительной, и я изо всех сил пытался найти общее решение, которое не полагалось бы на магические числа. В итоге я получил очень сложное решение, в котором используется только один псевдоэлемент, но код представлял собой груду спагетти, охватывающую лишь несколько частных случаев. Не думаю, что стоит исследовать этот путь.

Я решил вставить лишний элемент ради более простого кода. Вот разметка:

-3

Я использую пользовательский элемент <sh>, чтобы избежать любого потенциального конфликта с внешним CSS. Я мог бы использовать div, но так как это общий элемент, он может быть легко затронут другим правилом CSS, пришедшим откуда-то еще, что может сломать наш код.

Первым шагом является позиционирование элемента <sh> и намеренное создание переполнения:

-4

Код может показаться немного странным, но мы доберемся до его логики по ходу дела. Затем мы создаем градиентную тень, используя псевдоэлемент <sh>.

-5

Как видите, псевдоэлемент использует тот же код, что и все предыдущие примеры. Единственное отличие состоит в том, что 3D-преобразование определено для элемента <sh> вместо псевдоэлемента. На данный момент у нас есть градиентная тень без функции прозрачности.

Обратите внимание, что область элемента <sh> выделена черным контуром. Почему я это делаю? Потому что таким образом я могу применить к нему маску, чтобы скрыть часть внутри зеленой области и оставить переполненную часть там, где нам нужно видеть тень.

Я знаю, что это немного сложно, но, в отличие от clip-path, свойство mask не учитывает область вне элемента для отображения и скрытия элементов. Поэтому я был вынужден ввести дополнительный элемент — моделировать «внешнюю» область.

Также обратите внимание, что я использую комбинацию border и inset для определения этой области. Это позволяет мне сохранить поле заполнения этого дополнительного элемента таким же, как у основного элемента, так что псевдоэлементу не потребуются дополнительные вычисления.

Еще одна полезная вещь, которую мы получаем от использования дополнительного элемента, заключается в том, что элемент фиксируется, а перемещается только псевдоэлемент (используя translate). Это позволит мне легко определить маску, что является последним шагом этого трюка.

-6

Смотрите пример по ссылке.

Готово! У нас есть градиентная тень, и она поддерживает радиус границы! Вы, наверное, ожидали сложного значения маски с кучей градиентов, но нет! Нам нужны только два простых градиента и составная маска, чтобы завершить волшебство.

Давайте изолируем элемент <sh>, чтобы понять, что там происходит:

-7

Вот что мы получаем:

-8

Обратите внимание, как внутренний радиус совпадает с border-radius основного элемента. Я определил большую границу (150 пикселей) и border-radius, равный большой границе плюс радиус основного элемента. Снаружи у меня радиус равен 150px + R. Внутри у меня 150px + R - 150px = R.

Мы должны скрыть внутреннюю (синюю) часть и убедиться, что граница (красная) все еще видна. Для этого я определил два маскирующих слоя: один покрывает только область содержимого, а другой покрывает область рамки (значение по умолчанию). Затем я исключил одно из другого, чтобы выявить границу.

-9

Полный пример можно посмотреть по ссылке.

Я использовал ту же технику для создания границы, которая поддерживает gradients и border-radius.

Есть ли недостатки у этого метода?

Да, это определенно не идеально. Первая проблема, с которой вы можете столкнуться, связана с использованием границы основного элемента. Это может привести к небольшому смещению радиусов, если вы его не учтете. У нас есть эта проблема в нашем примере, но, возможно, вы ее едва заметите.

Исправить это относительно просто: добавьте ширину границы для inset элемента <sh>.

-10

Другим недостатком является большое значение, которое мы используем для границы (150px в примере). Это значение должно быть достаточно большим, чтобы содержать тень, но не слишком большим, чтобы избежать проблем с переполнением и полосой прокрутки. К счастью, онлайн-генератор рассчитает оптимальное значение с учетом всех параметров.

Последний недостаток, о котором я знаю, это когда вы работаете со сложным радиусом границы. Например, если вы хотите, чтобы к каждому углу применялся разный радиус, вы должны определить переменную для каждой стороны. Я полагаю, это не совсем недостаток, но ваш код может немного усложниться в обслуживании.

Онлайн-генератор учитывает только однородный радиус для простоты, но теперь вы знаете, как изменить код, если хотите учитывать сложную конфигурацию радиуса.

-11

Подведение итогов

Мы дошли до конца! Магия градиентных теней больше не является загадкой. Я попытался охватить все возможности и возможные проблемы, с которыми вы можете столкнуться. Если я что-то упустил или вы обнаружите какие-либо проблемы, не стесняйтесь сообщить об этом в разделе комментариев, и я проверю это.

Опять же, многое из этого, вероятно, излишне, учитывая, что решение де-факто покроет большинство ваших вариантов использования. Тем не менее, полезно знать «почему» и «как» этот трюк и как преодолеть его ограничения. Кроме того, мы получили хорошее упражнение, играя с отсечением и маскированием CSS.

И, конечно же, у вас есть онлайн-генератор, к которому вы можете обратиться в любое время, когда захотите избежать хлопот.

Перевод статьи "Different Ways to Get CSS Gradient Shadows".