По моему скромному мнению, лучшие веб-сайты и веб-приложения имеют осязаемое «настоящее» качество. Для достижения этого качества необходимо много факторов, но тени являются критическим компонентом.

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

В этом уроке мы научимся преобразовывать типичные тени в красивые, реалистичные:

Целевая аудитория.Это руководство предназначено для разработчиков, знакомых с основами CSS. Предполагается некоторое знание цветов box-shadow, hsl() и переменных CSS.

Зачем вообще использовать тени?

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

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

Вот пример. Перетащите ползунок «Показать», чтобы увидеть, что я имею в виду:

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

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

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

Однако для достижения этих целей нам необходимо целостно взглянуть на тени в нашем приложении.

Создание согласованной среды

Долгое время я не очень правильно использовала тени 😬.

Когда я хотел, чтобы у элемента была тень, я добавлял свойство box-shadow и возился с числами, пока мне не нравился результат.

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

В естественном мире тени отбрасываются от источника света. Направление теней зависит от положения источника света:

В общем, мы должны определиться с единым источником света для всех элементов на странице. Обычно этот источник света находится выше и немного левее:

Если бы в CSS была настоящая система освещения, мы бы указали положение одного или нескольких источников света. К сожалению, в CSS такого нет.

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

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

То же соотношение?

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

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

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

Далее поговорим о высоте. Как мы можем создать иллюзию того, что элемент поднимается к пользователю?

Нам нужно будет настроить все 4 переменные в тандеме, чтобы создать целостный опыт.

Поэкспериментируйте с этой демонстрацией и обратите внимание, как меняются значения:

Первые два числа — горизонтальное и вертикальное смещение — масштабируются вместе в тандеме. Вертикальное смещение всегда в 2 раза больше горизонтального.

Когда карта поднимается выше, происходят еще две вещи:

  • Радиус размытия увеличивается.
  • Тень становится менее непрозрачной.

(Я также увеличиваю размер карты для еще большего реализма. На практике проще пропустить этот шаг.)

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

Если вы находитесь в хорошо освещенной комнате, прижмите руку к столу (или любой другой поверхности поблизости) и медленно поднимите ее. Обратите внимание, как меняется тень: она удаляется от вашей руки (большее смещение), становится более размытой (больший радиус размытия) и начинает исчезать (меньшая непрозрачность). Если вы не можете двигать руками, вместо этого вы можете использовать опорные объекты в комнате. Сравните различные тени вокруг вас.

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

Итак, резюмируя:

  1. Каждый элемент на странице должен быть освещен одним и тем же глобальным источником света.
  2. Свойство box-shadow представляет положение источника света с использованием смещения по горизонтали и вертикали. Для обеспечения согласованности каждая тень должна использовать одинаковое соотношение между этими двумя числами.
  3. По мере приближения элемента к пользователю смещение должно увеличиваться, радиус размытия должен увеличиваться, а непрозрачность тени должна уменьшаться.
  4. Вы можете пропустить некоторые из этих расчетов, воспользовавшись нашей интуицией.

Трюки

Расслоение

Современные инструменты 3D-иллюстрации, такие как Blender, могут создавать реалистичные тени и освещение с помощью метода, известного как трассировка лучей.

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

У веб-пользователей нет такого терпения, поэтому алгоритм box-shadow гораздо примитивнее. Он создает прямоугольник в форме нашего элемента и применяет к нему базовый алгоритм размытия.

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

Вместо того, чтобы использовать одну box-shadow, мы наложим несколько штук друг на друга с немного разными смещениями и радиусами:

Накладывая несколько теней, мы создаем немного тонкости, присутствующей в реальных тенях.

Эта техника подробно описана в замечательном посте в блоге Тобиаса Ахлина «Гладкие и четкие тени с многослойной коробчатой ​​тенью». Позже в этом сообщении блога я поделюсь некоторыми инструментами для получения этих значений программным путем!

Компромисс производительности

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

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

Как всегда, обязательно проведите собственное тестирование! По моему опыту, многослойные тени не сильно влияют на производительность, но я также никогда не пытался использовать десятки или сотни одновременно.

Кроме того, вероятно, не стоит пытаться анимировать многослойную тень.

Подходящие по цвету тени

До сих пор все наши тени использовали полупрозрачный черный цвет, например hsl(0deg 0% 0% / 0.4). Это на самом деле не идеально.

Когда мы накладываем черный цвет на фоновый цвет, он не просто становится темнее; это также немного обесцвечивает его.

Сравните эти две коробки:

В поле слева используется прозрачный черный цвет. Коробка справа соответствует оттенку и насыщенности цвета, но снижает яркость. Мы получаем гораздо более яркую коробку!

Аналогичный эффект возникает, когда мы используем более темный цвет для наших теней:

На мой взгляд, ни одна из этих теней не совсем правильная. Тот, что слева, слишком ненасыщенный, а тот, что справа, недостаточно обесцвеченный; это больше похоже на свечение, чем на тень!

Чтобы найти цвет Златовласки, могут потребоваться некоторые эксперименты:

Подбирая оттенок и снижая насыщенность/яркость, мы можем создать настоящую тень, в которой нет этого «размытого» оттенка серого.

Соотношение между насыщенностью и светлотой

Если вы знакомы с цветовым форматом hsl, то знаете, что насыщенность и яркость контролируются независимо.

Не странно ли тогда, что снижение яркости также влияет на насыщенность?

Чтобы ответить на этот вопрос, нам нужно спуститься в кроличью нору. Если вы заинтересованы, нажмите «Показать больше», чтобы погрузиться!

В качестве примера, вот два блока с одинаковым процентом насыщения (100%), но с очень разной воспринимаемой насыщенностью:

Это происходит потому, что в цветах при высоких/низких значениях яркости просто не так много «пигмента». Насыщенность не может так сильно влиять на общий цвет.

Это наиболее очевидно в крайних случаях:

hsl(0deg 0% 100%) — чисто белый с 0% насыщенностью.

hsl(0deg 100% 100%) тоже чисто белый, даже при полной насыщенности.

Если мы установим яркость на 95%, разница будет, но едва уловимая:

То же самое справедливо и для очень темных цветов:

Однако, когда мы находимся прямо в середине спектра светлоты, доступен полный диапазон насыщенности:

Вот как я об этом думаю: 50% яркости — это версия «по умолчанию» для всех оттенков. Яркость не влияет на насыщенность, когда она составляет 50%.

Когда мы увеличиваем или уменьшаем яркость от этого 50%-го наилучшего цвета, мы уменьшаем количество доступного пигмента в цвете. Цвет не может быть полностью насыщенным, светлым или темным.

Насыщенность % является относительной мерой, основанной на том, сколько пигмента доступно при данной светлоте.

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

Собираем все вместе

В этом уроке мы рассмотрели 3 разные идеи:

  1. Создание сплоченной среды путем координации наших теней.
  2. Использование слоев для создания более реалистичных теней.
  3. Настройка цветов для предотвращения «размытых» серых теней.

Вот пример, в котором применяются все эти идеи:

Первоначально опубликовано на https://www.joshwcomeau.com.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .

Заинтересованы в масштабировании запуска вашего программного обеспечения? Ознакомьтесь с разделом Схема.