34 Модуль 7 Графика и эффекты 16 мин урок 9 из 25

Фильтры и эффекты

Размытие, стеклянные панели и разница между drop-shadow и box-shadow, из-за которой тень вокруг прозрачной картинки выглядит неправильно.

Что ты научишься делать

  • Соберёшь стеклянную панель, читаемую на любом фоне
  • Поймёшь, когда нужен drop-shadow, а когда box-shadow
  • Научишься оценивать цену эффекта для браузера

#Один инструмент вместо графического редактора

Свойство filter — это набор готовых обработок: размыть, осветлить, обесцветить, повернуть цвета. Раньше ради каждой из них картинку правили в редакторе и хранили вторую копию файла.

Теперь копия не нужна: наведение, тёмная тема, состояние «недоступно» — всё это варианты одного и того же изображения.

Интерактивный разбор доступен при включённом JavaScript.

#Порядок имеет значение

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

filter: blur(4px) brightness(1.5) сначала размывает, потом осветляет размытое. filter: brightness(1.5) blur(4px) сначала осветляет, потом размывает уже осветлённое — результат другой.

ФункцияЧто делаетНейтральное значение
blur(4px)Размытие по Гауссу0
brightness(1.2)Яркость1
contrast(1.4)Контраст1
saturate(0.4)Насыщенность1
grayscale(1)Обесцвечивание0
hue-rotate(90deg)Сдвиг цветового круга0deg
drop-shadow(0 4px 8px …)Тень по форме содержимого
opacity(.5)Прозрачность внутри стека фильтров1

#drop-shadow против box-shadow

Это разные вещи, и путаница здесь стоит дорого.

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

filter: drop-shadow() обводит непрозрачные пиксели. Тень повторяет силуэт картинки, текст или фигуру, обрезанную через clip-path.

Одна фигура, две тени
В песочницу

#backdrop-filter: стекло

filter обрабатывает сам элемент. backdrop-filter обрабатывает то, что за ним, — так делают матовые панели поверх фотографии.

Обязательное условие: элемент должен быть полупрозрачным. Через непрозрачный фон размытую подложку всё равно не видно.

Стеклянная панель
В песочницу

#Тень у текста и иконок

У drop-shadow есть применение, о котором часто забывают: тень для текста сложной формы и для иконок-контуров.

Свойство text-shadow работает только с текстом и не умеет обводить SVG. А drop-shadow обведёт что угодно — надпись, иконку из спрайта, вырезанную фигуру, — потому что смотрит на непрозрачные пиксели, а не на тип элемента.

CSSПодпись поверх фотографии
/* Мягкая тень делает белый текст читаемым на светлых участках */.caption {  color: #fff;  filter: drop-shadow(0 1px 2px rgb(0 0 0 / .8));}/* Тот же приём для иконки из спрайта */.icon--onphoto {  filter: drop-shadow(0 1px 3px rgb(0 0 0 / .7));}

#Цена эффекта

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

Что делаемЦена
grayscale, brightness, saturate на небольшом элементеДёшево
blur на иконке или кнопкеТерпимо
blur на полноэкранном блокеДорого
backdrop-filter на липкой шапке при прокруткеДорого: пересчёт на каждом кадре
Анимация filterОчень дорого — фильтр считается заново каждый кадр

#SVG-фильтры: когда CSS не хватает

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

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

HTMLЗернистость поверх градиента
<svg width="0" height="0" aria-hidden="true">  <filter id="grain">    <!-- Генерируем шум -->    <feTurbulence type="fractalNoise" baseFrequency="0.8" numOctaves="3"/>    <!-- И приглушаем его -->    <feColorMatrix type="saturate" values="0"/>    <feComponentTransfer>      <feFuncA type="linear" slope="0.35"/>    </feComponentTransfer>  </filter></svg>
CSSПодключение из CSS
.hero::after {  content: "";  position: absolute;  inset: 0;  filter: url(#grain);  mix-blend-mode: overlay;  pointer-events: none;}

#Как это выглядит в реальном проекте

CSSui.css
@layer components {  /* Липкая шапка. Размытие — только когда страница прокручена */  .header {    position: sticky;    inset-block-start: 0;    background: color-mix(in oklab, var(--bg) 86%, transparent);  }  .header.is-scrolled {    backdrop-filter: blur(14px) saturate(140%);    -webkit-backdrop-filter: blur(14px) saturate(140%);  }  /* Недоступный товар: обесцвечен, но остаётся читаемым */  .product[data-out-of-stock] .product__media {    filter: grayscale(1) contrast(.9);  }  /* Логотипы партнёров: одноцветные, цвет проявляется при наведении */  .partners img {    filter: grayscale(1) opacity(.65);    transition: opacity .25s ease;  }  .partners a:hover img,  .partners a:focus-visible img {    /* Меняем только прозрачность — фильтр остаётся прежним */    opacity: 1;  }}

#Когда НЕ надо

  • Прятать содержимое размытием. Размытый текст остаётся в разметке и читается программой чтения с экрана; выделить и скопировать его тоже можно. Для скрытия данных это не годится.
  • Стекло на пёстром фоне без подложки. Панель будет выглядеть эффектно на скриншоте и станет нечитаемой на настоящей фотографии.
  • Анимировать filter. Каждый кадр считается заново. Анимируй opacity отдельного слоя.
  • Чинить фильтром плохую картинку. contrast и saturate не вернут детали, которых нет в файле. Это косметика, а не восстановление: пересохранить исходник в нужном размере всегда лучше.

#Поддержка браузерами

ВозможностьСостояние
filter с функциямиВо всех браузерах, давно
filter: url(#id) из SVGВо всех современных браузерах
backdrop-filterПоддерживается везде; в части сборок WebKit нужен префикс -webkit-
drop-shadowВо всех браузерах
CSSФоллбэк для стекла
/* База: плотная подложка, читается всегда */.panel { background: rgb(255 255 255 / .92); }/* Улучшение: там, где размытие есть, подложку делаем легче */@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {  .panel {    background: rgb(255 255 255 / .3);    backdrop-filter: blur(12px);    -webkit-backdrop-filter: blur(12px);  }}

Где спотыкаются почти все

Размылась карточка вместе с текстом

Почему filter действует на элемент и всех потомков — исключений нет.

Как надо Вешай фильтр на псевдоэлемент или отдельный слой под содержимым.

Квадратная тень вокруг прозрачного PNG

Почему box-shadow рисует тень от прямоугольника элемента и не смотрит на содержимое.

Как надо Для силуэта нужен filter: drop-shadow().

backdrop-filter не работает

Почему Чаще всего фон элемента непрозрачный: размытие есть, но его не видно. Иногда мешает overflow: hidden у предка.

Как надо Сделай фон полупрозрачным и проверь, что предок не обрезает слой.

Анимация filter тормозит

Почему Фильтр пересчитывается на каждом кадре, а размытие — самая дорогая из операций.

Как надо Держи два слоя и анимируй opacity размытого.

Фильтр filter
Обработка элемента и его содержимого: размытие, яркость, обесцвечивание.
Фильтр подложки backdrop-filter
Обработка того, что находится позади элемента.
Тень по силуэту drop-shadow
Тень, повторяющая непрозрачные пиксели, а не рамку элемента.
SVG-фильтр SVG filter
Собственный эффект, собранный из примитивов вроде feTurbulence.

Проверь себя

  1. Почему после <code>filter: blur(6px)</code> размылся и текст внутри карточки?

    Исключений нет. Чтобы размыть только фон, фильтр вешают на отдельный слой или псевдоэлемент.

  2. У прозрачного PNG тень получилась квадратной. Что использовать?

    <code>box-shadow</code> рисует тень от прямоугольника. Силуэт обводит только <code>drop-shadow</code>.

  3. Стеклянная панель не размывает фон. Первое, что стоит проверить?

    Через непрозрачный фон размытую подложку не видно. Второе по частоте — <code>overflow: hidden</code> у предка.

  4. Как дешевле сделать плавное появление размытия?

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

  5. Что даёт <code>filter: brightness(1.5) blur(4px)</code> по сравнению с <code>blur(4px) brightness(1.5)</code>?

    Каждый следующий фильтр работает с результатом предыдущего. Осветлить и размыть — не то же, что размыть и осветлить.

Задание

Стеклянная панель, читаемая всегда

На пёстром фоне лежит панель с текстом — сейчас его почти не разобрать.

Сделай панель стеклянной: добавь backdrop-filter с размытием и повышенной насыщенностью, полупрозрачную светлую подложку и светлую рамку. Не забудь префиксную строку для WebKit.

Отдельно: у звезды сейчас box-shadow, и после обрезки тени не видно. Замени на тень по силуэту.

Открыть в песочнице
    Подсказка 1

    Стекло: backdrop-filter: blur(12px) saturate(140%); и та же строка с префиксом -webkit-.

    Подсказка 2

    Подложка обязательна: background: rgb(255 255 255 / .3); плюс border: 1px solid rgb(255 255 255 / .45);

    Подсказка 3

    Тень по силуэту вешается на родителя: .star-wrap { filter: drop-shadow(0 8px 10px rgb(20 24 48 / .5)); }

    Показать решение
    HTMLindex.html
    <div class="scene">  <div class="glass">    <h3>Кофейня «Полка»</h3>    <p>Этот текст должен читаться на любом участке фона.</p>  </div>  <div class="star-wrap">    <div class="star"></div>  </div></div>
    CSSstyle.css
    .scene {  position: relative;  padding: 26px;  border-radius: 14px;  background:    radial-gradient(circle at 18% 22%, #ffd166 0 15%, transparent 16%),    radial-gradient(circle at 80% 72%, #4bd1a0 0 18%, transparent 19%),    linear-gradient(135deg, #6544e0, #f2777a);}.glass {  padding: 16px;  border-radius: 12px;  color: #16181d;  -webkit-backdrop-filter: blur(12px) saturate(140%);  backdrop-filter: blur(12px) saturate(140%);  background: rgb(255 255 255 / .3);  border: 1px solid rgb(255 255 255 / .45);}.glass h3 { margin: 0 0 6px; font-size: 17px; }.glass p { margin: 0; font-size: 14px; }.star-wrap {  margin-top: 18px;  filter: drop-shadow(0 8px 10px rgb(20 24 48 / .5));}.star {  width: 70px;  height: 70px;  background: #fff;  clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);}

    Проверь себя