Создание ярких умных теней
Вы когда-нибудь хотели узнать, как создать эффект тени, который наследует некоторые цвета от элемента переднего плана? Прочтите или посмотрите ниже, чтобы узнать, как!
На днях я прогуливался по Home Depot (он же Toys «R» Us для больших детей!), и у них был огромный стенд, чтобы продемонстрировать все умные лампочки, которые они продавали. Один из элементов дисплея предназначался для серии лампочек за телевизором, которые будут проецировать на заднем плане приближение цветов, отображаемых на экране на переднем плане. Это было примерно так:
Обратите внимание на то, что происходит за телевизором. Цвета, показанные на переднем плане на экране, проецируются в виде цветной тени позади самого телевизора. По мере изменения цветов на экране меняются и цвета, проецируемые на фон. Действительно здорово, правда?
Естественно, увидев это, я первой подумал, можно ли создать красочную тень, достаточно умную, чтобы имитировать цвета переднего плана, с помощью веб-технологий. Оказывается, вполне можно использовать только CSS. В этой статье мы рассмотрим, как создать этот эффект.
Вперед!
Сделать это реальным
Как вы увидите в следующих разделах, создание этой красочной тени с помощью CSS поначалу может показаться сложной задачей. Когда мы начнем разбираться в этом и разбиваем этот крупный кусок задачи на более мелкие части, вы увидите, что все это вполне легко усваивается. В следующих нескольких разделах мы собираемся создать следующий пример:
Вы должны увидеть изображение суши с красочной тенью позади него. Чтобы подчеркнуть, что мы все это делаем вживую, тень анимирована с пульсирующим эффектом. Разобрав рабочий пример, давайте погрузимся в реализацию и посмотрим, как HTML и CSS оживляют все это.
Отображение нашего изображения
В HTML-коде для отображения нашего изображения суши нет ничего особенного:
<div class="parent">
<div class="colorfulShadow sushi"></div>
</div>
У нас есть родительский элемент div
, и он содержит дочерний элемент div
, который отвечает за отображение суши. Мы отображаем суши, задавая его как фоновое изображение, и это обрабатывается следующим правилом стиля .sushi:
.sushi {
margin: 100px;
width: 150px;
height: 150px;
background-image: url("https://www.kirupa.com/icon/1f363.svg");
background-repeat: no-repeat;
background-size: contain;
}
В этом правиле стиля мы указываем размер нашего div равным 150 на 150 пикселей, и мы устанавливаем для него background-image
и связанные свойства. Если подвести итоги того, где мы сейчас находимся, HTML и CSS, которые мы видели, дадут нам что-то, что выглядит следующим образом:
Пришло время теней
Теперь, когда у нас появилось наше изображение, все, что осталось, - это еще более интересная часть нас, определяющая тень. Мы собираемся определить тень, указав дочерний псевдоэлемент (используя after), который будет делать три вещи:
- Распологаться прямо за нашим изображением
- Наследовать то же фоновое изображение, что и у родительского элемента
- Полагаться на фильтры, чтобы применить красочный эффект тени
Эти три вещи выполняются по следующим двум правилам стиля:
.colorfulShadow {
position: relative;
}
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
Уделите несколько минут, чтобы пройтись по тому, что здесь происходит. Обратите особое внимание на каждое свойство и его стоимость. Некоторые примечательные выноски здесь - это background
и filter
. Свойство background
имеет значение inherit, что означает, что его значение будет фоном родителя:
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
В свойстве filter
определены два фильтра: drop-shadow и blur
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
}
Наш фильтр отбрасывания теней настроен на отображение черной тени с непрозрачностью 50%, а наш фильтр размытия размывает наш псевдоэлемент на 20 пикселей. Комбинация этих двух фильтров - это то, что в конечном итоге создает красочную тень, которая теперь появится за нашим изображением суши, когда будут применены эти два правила стиля:
На данный момент мы в значительной степени довольны. Для полноты картины, если вам нужна анимация, в которой цветная тень увеличивается и уменьшается, следующие дополнения к нашему существующему CSS помогут вам в этом:
.colorfulShadow {
position: relative;
}
.colorfulShadow::after {
content: "";
width: 100%;
height: 100%;
position: absolute;
background: inherit;
background-position: center center;
filter: drop-shadow(0px 0px 10px rgba(0, 0, 0, 0.50)) blur(20px);
z-index: -1;
/* animation time! */
animation: oscillate 1s cubic-bezier(.17, .67, .45, 1.32) infinite alternate;
}
@keyframes oscillate {
from {
transform: scale(1, 1);
}
to {
transform: scale(1.3, 1.3);
}
}
Если вам нужна некоторая интерактивность без постоянно повторяющейся анимации, вы также можете использовать переход CSS, чтобы изменить поведение тени при некоторых действиях, таких как наведение курсора. Сложная часть состоит в том, чтобы просто обрабатывать псевдоэлемент так же, как и любой другой элемент, который вы бы явно определяли в HTML или динамически создавали с помощью JavaScript. Единственная разница в том, что этот элемент полностью создан с использованием только CSS!
Заключение
Псевдоэлементы позволяют нам использовать CSS для выполнения некоторых задач по созданию элементов, которые исторически относились к домену HTML и JavaScript. Для нашей красочной и умной тени мы полагались на родительский элемент, чтобы установить фоновое изображение. Это позволило нам легко определить дочерний псевдоэлемент, который унаследовал детали фонового изображения родительского объекта, но также позволил нам установить для него набор свойств для эффекта размытия и отбрасывания тени. Хотя все это хорошо, и мы свели к минимуму много копий и вставок, этот подход не очень гибкий.
Что, если я хочу применить такую тень к элементу, который не просто пуст с фоновым изображением? Что, если у меня есть элемент HTML, например кнопка или поле со списком, к которому я хочу применить этот эффект тени? Одно из решений - полагаться на JavaScript для дублирования соответствующих элементов в DOM, размещения их под элементами переднего плана, применения фильтров и прекращения работы. Хотя это работает, я всегда немного вздрагиваю при дублировании элементов DOM, учитывая, насколько тяжелым является этот процесс. Жаль, что в JavaScript нет эквивалента renderTargetBitmap, где любой визуальный элемент, который вы предоставляете, легко превращается в растровое изображение, с которым вы можете делать все, что захотите! 🥶