Веб-разработка
June 3, 2022

Теневое искусство и линейные градиенты — Тренажёр HTML Academy

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

Бокс с тенью box-shadow

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

Забегая вперед напишу, что есть еще фильтр drop-shadow(), который мы разберём чуть по позже, и свойство text-shadow, которое я уже упоминал в мобильном приложении, а в тренажёрах Академии они будут в самом последнем блоке «Тонкостей».

В этой части именно про box-shadow — тень блока элемента, не текста и не контента. Это свойство само по себе комплексное как, например, рамки border и принимает целый список значений:

  • Позиция тени inset — необязательный параметр указывающий, что тень внутренняя, а не внешняя как по умолчанию;
  • Смещение по X — обязательный параметр, работающий подобно функции translateX(), но для тени блока;
  • Смещение по Y — обязательный параметр, аналогичный параметр для вертикального смещения;
  • Размытие — необязательный параметр, принимает величину размытия границ тени — чем больше значение, тем шире и светлее тень;
  • Растяжение — необязательный параметр, изменяет площадь тени на указанную величину, по умолчанию она равна размеру блока;
  • Цвет тени — необязательный параметр окрашивающий тень, принимаются все варианты — слова, HEX, RGB (a) и так далее.

Важно заменить, что порядок параметров в этом свойстве крайне важен. Несмотря на то, что обязательными являются только значения смещения тени. Например, что бы задать тени только растяжение 5px и цвет red, всё равно нужно указывать нулевые значения смещений и размытия:

.shadow-border {
  box-shadow: 0 0 0 5px red;
}

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

.flat-shadow {
  box-shadow: 10px 10px red;
}

По аналогии с фоновыми изображениями background-image, свойство тени элемента box-shadow может принимать сразу несколько наборов параметров, тем самым генерируя несколько теней:

.glitch-shadow {
  box-shadow:
    10px 10px red,
    -10px -10px blue;
}

При этом тень указанная выше по коду будет так же выше по слою отображения, то есть в нашем примере red будет перекрывать blue в местах их соприкосновения.

Особенно хорошо видно как работает этот нюанс с внутренними тенями inset — на этих особенностях свойства построена вторая половина части. Мы с нуля, только с помощью внутренних теней отрисовали кольца логотипа Audi:

.circle {
  margin: 10px auto;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  box-shadow:
    inset 2px 2px 2px 0 white,
    inset 0 0 0 4px #4f5054,
    inset 0 0 0 5px black,
    inset -5px -5px 5px 3px white,
    inset 0 0 0 9px #6c6d70,
    inset 0 0 0 10px black;
}

Испытания

Часть сама по себе очень небольшая и очень простая. Первое испытание аналогично — простое и слегка скучное. Нужно просто сделать три кнопки с разными тенями:

А вот по поводу второго испытание мне есть, что сказать. И без мата здесь обойтись трудно. Испытание называется «Зловещие тени», задача на множественные тени — разместить их как на примере.

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

Да, это тени, просто без размытия

С помощью только свойства box-shadow сделать это невозможно, как раз из-за перекрытия теней. Если смещать внутренние тени на половину, они закрасят эту половину кнопки и даже если накорячить сверху синие «тени» как замену заливки, то зелёные тени с другой стороны будут такие же.

И что вы думаете, здесь есть какой-то изящный выход? Какая-то хитрость со свойством? Не-а. Здесь есть дополнительный пустой блок .help который надо тупо налепить поверх:

Ребята на форуме еще городили псевдоэлементы, что менее кастыльный вариант, но, имхо, всё еще какое-то дристалово. Ну вот нафига? Чему это испытание должно научить? Двигать div’ы? Причем тут тени?

В общем, испытание я, конечно, сделал, но осадочек остался:

Линейные градиенты

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

Именно функцию градиента мы подставляем как значение вместо url():

.gradient-box {
  background-image: linear-gradient(yellow, green);
}

Функция принимает минимум два атрибута — два цвета между которыми строится плавный переход. «Минимум» потому, что таких цветов можно задать сколько угодно, таким образом задавая сложный многоцветный градиент. Цвета будут отображаться в том порядке, в котором они указаны в функции.

Направление градиента

У функции линейного градиента linear-gradient() есть еще один необязательный атрибут — направление или угол наклона градиента. Он обязательно указывается первым, перед всеми цветами.

Направление можно задать с помощью ключевых слов top, bottom, right, left с предлогом to перед направлением, например:

.to-top-gradient {
  background-image: linear-gradient(to top, yellow, green);
  /* снизу вверх, от жёлтого к зелёному */
}

.to-angle-gradient {
  background-image: linear-gradient(to right top, yellow, green);
  /* от левого нижнего угла к верхнему правому */
}

Или можно задать угол наклона градиента в градусах deg, по аналогии с функцией поворота rotate(), положительные значения поворачивают по часовой стрелке, отрицательные — против часовой:

.gradient-60deg {
  background-image: linear-gradient(60deg, yellow, green);
}

.gradient-135deg {
  background-image: linear-gradient(-135deg, yellow, green);
}

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

При изменении размера блока, градиент с ключевыми словами направления будет также меняться, так как «правый верхний» to right top угол будет менять свое положение. В случае указания градусов поворота deg, градиент останется в том же положении.

Пропорции и колорстопы

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

Этим поведением цветов в градиенте можно управлять с помощью так называемых колорстопов (color-stop) — значение позиции цвета в градиенте, то с какой или до какой позиции будет распространяться цвет.

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

.gradient-colorstop {
  background-image: linear-gradient(to right, yellow 0%, green 100%);
}
Да, это тот же градиент, что и выше.

Если читать это человеческим языком, то получается градиент от жёлтого в самом начале — 0% от ширины размера блока, до зелёного в самом конце — 100% ширины блока.

Если поменять колорстоп зелёного на 50%, то получится следующее:

.gradient-colorstop50 {
  background-image: linear-gradient(to right, yellow 0%, green 50%);
}

Теперь градиентный переход идёт от жёлтого в 0% до зелёного в 50%, а всё что дальше занимает зелёный как «финальный» цвет перехода.

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

В случае, например, трёхцветного градиента — по умолчанию позиции цветов равно удалены друг от друга, то есть занимают 0%, 50% и 100%:

.gradient-trio {
  background-image: 
     linear-gradient(to right, red 0%, yellow 50%, green 100%);
}

Например, мы хотим, чтобы жёлтый цвет по центру занимал 50% площади. Для этого нам нужно добавить еще один жёлтый колорстоп:

.gradient-trio-50 {
  background-image: 
     linear-gradient(to right, red 0%, yellow 25%, yellow 75%, green 100%);
}

Таким образом, всю площадь между 25% и 50% занимает жёлтый цвет, а между краями задаются градиентные переходы.

Что будет если задать двум цветам одинаковый колорстоп? В этом случае переход будет резкий, без градиентной «размывки». Например, зададим red 25% и green 75% в примере выше, получится такая картина:

Эта особенность помогает в создании огромного количества декоративных эффектов. Чаще всего в этом случае используются колорстопы в пикселях px, так как они позволяют задать точный размер декоративного элемента, а также прозрачность — ключевое слово transparent или с помощью RGBA.

Например, в тренажёре мы сделали вот такой «цветок»:

Повторяющиеся и множественные градиенты

Можно пойти еще дальше, функция линейного градиента имеет своего старшего брата — repeating-linear-gradient() функция повторяющегося линейного градиента.

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

С помощью повторяющегося линейного градиента repeating-linear-gradient() можно делать простенькие паттерны, буквально одной строчкой кода:

А можно и не простенькие! Как я уже писал выше — формально, градиент это изображение. А как мы помним из части про фоны, свойство background-image может принимать сразу несколько значений и градиенты не исключение.

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

Еще на градиент работает свойство background-size, которое почему-то в той же части про фоны пропустили (я перепроверил!). Это свойство задаёт размер фонового изображения или, если их несколько, работает аналогично background-position сопоставляя порядок указанный в background-image.

Используя все эти особенности и линейные градиенты можно создавать достаточно сложные фигуры, которые с помощью background-repeat превращаются в уже комплексные паттерны:

.pattern {
  height: 100%;
  background-color: #333333;
  background-image:
    linear-gradient(135deg, white 25%, transparent 25%),
    linear-gradient(225deg, white 25%, transparent 25%),
    linear-gradient(45deg, white 25%, transparent 25%),
    linear-gradient(315deg, white 25%, transparent 25%);
  background-position:
    25px 0, /* смещены вправо */
    25px 0,
    0 0,
    0 0;
  background-size: 50px 50px;
  background-repeat: repeat;
}

Испытания

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

Первое супер простенькое, на направление градиента:

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

Третье испытание ломает мозги. И это я сейчас не с негативом! В отличие от испытания с тенями, тут все логически понятно и решается использованием одного инструмента, без костылей. Делаем паттерн сюрикенов:

Просидел я на нём минут 40, наверное, но это тот случай когда сложность испытания какая-то приятная, что ли.

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

Есть подвохи, например, с последним спутником, а есть совсем простые как Титан, где только один градиент. Было увлекательно, главное не запутаться в комментариях в CSS.


На этом закончим. Градиенты были очень интересной темой. От теней немного подпортило впечатление последнее испытание. Следом у нас «Кекстаграм» — посмотрим на CSS-фильтры и возвращаемся к JavaScript!

Вам большое спасибо за внимание! Прошу прощение, за негатив, но без него было бы, наверное, слишком обезличено.

Ссылки на предыдущие статьи по HTML Academy:

Знакомство с Веб-разработкой
Знакомство с HTML и CSS
Знакомство с JavaScript
Знакомство с PHP
Таблицы и подробно о формах
Наследование, каскады и селекторы
Блочная модель, поток и сетка на float
Гибкие флексбоксы display: flex
Удобные сетки на гридах display: grid
Пропуск блока «Погружение»
Позиционирование и двумерные трансформации
Теневое искусство и линейные градиенты <- Вы здесь
CSS-фильтры и Кекстаграм
Мастерские
Продвинутые Мастерские
...

Остальные статьи можно посмотреть у меня на главной странице блога.

Также мои соц. сетки, которые я продолжаю вести:

Мой Twitter
Мой Telegram
Мой Паблик ВК

Заходите куда удобно вам и подписывайтесь! Еще раз спасибо за внимание!