HTML & CSS

Тіні та фільтри в CSS

Повний гід по box-shadow, text-shadow, filter та backdrop-filter. Анатомія тіней, шарування, inset-тіні, drop-shadow для SVG, blur, brightness, contrast, glassmorphism. Продуктивність і best practices.

Тіні та фільтри в CSS

Чому одна тінь може зробити дизайн преміальним — або зламати його

Відкрийте будь-який сучасний дизайн-сайт — Linear, Vercel, Stripe — і придивіться до карток, кнопок, модальних вікон. Вони «зависають» над сторінкою природно, як матеріальні об'єкти. Секрет — не в складному коді, а в правильних тінях.

Погана тінь (різка, темна, з неправильним кутом) робить елемент важким і дешевим. Хороша тінь (м'яка, багатошарова, з правильним розмиттям) створює ілюзію глибини і відчуття преміальності. Різниця — часто в кількох параметрах і розумінні того, як тіні влаштовані фізично.

У цій статті ми розберемо повний арсенал CSS-тіней: від базового box-shadow до складних ефектів з filter: drop-shadow() та сучасного glassmorphism через backdrop-filter: blur().


Анатомія box-shadow — шість параметрів

box-shadow — це властивість, що додає тінь ззовні (або зсередини) прямокутної форми елемента. Повний синтаксис виглядає так:

box-shadow: offset-x offset-y blur-radius spread-radius color;
/* або з inset: */
box-shadow: inset offset-x offset-y blur-radius spread-radius color;

Розберемо кожен параметр детально:

offset-x
length required
Горизонтальне зміщення тіні. Позитивне значення — тінь зміщується вправо (джерело світла зліва). Негативне — тінь зміщується вліво. 0 — тінь симетрична по горизонталі.
offset-y
length required
Вертикальне зміщення тіні. Позитивне значення — тінь зміщується вниз (джерело світла зверху — найбільш природно). Негативне — тінь вгору. 0 — симетрична по вертикалі.
blur-radius
length
Радіус розмиття. 0 — чітка тінь без розмиття. Чим більше значення — тим м'якша і більша тінь. Не може бути від'ємним. Фізично імітує дифузне джерело світла.
spread-radius
length
Розширення тіні. Позитивне — тінь збільшується у всі боки (ширша ніж елемент). Негативне — тінь звужується (корисно для softened shadows). 0 — розмір тіні дорівнює розміру елемента.
color
color
Колір тіні. Рекомендується використовувати rgba() або hsl(... / alpha) з низькою непрозорістю для природнього вигляду. Уникайте непрозорого чорного #000 — виглядає штучно.
inset
keyword
Якщо вказано — тінь малюється всередині елемента, а не ззовні. Корисно для ефектів вдавлених кнопок, полів вводу, wells.

Живий інтерактивний приклад

🔒localhost:3000

Кольори тіней — найпоширеніша помилка

Більшість початківців пишуть box-shadow: 0 4px 8px black. Результат виглядає штучно і «дешево». Причина — в реальному світі тіні не бувають абсолютно чорними. Вони напівпрозорі та злегка забарвлені оточенням.

❌ Погано — непрозорий чорний

box-shadow: 0 4px 12px #000000;

Виглядає як намальована олівцем тінь — різка, неприродня.

✅ Добре — напівпрозорий чорний

box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);

М'яко, природньо. Прозорість 10–20% — типовий діапазон.

✅ Відмінно — забарвлена тінь

.btn-primary {
  background: #6366f1;
  box-shadow: 0 8px 24px rgba(99, 102, 241, 0.35);
}

Тінь успадковує відтінок елемента — дуже сучасний прийом.

🔒localhost:3000

Множинні тіні — секрет глибини

box-shadow приймає список тіней через кому. Реальні об'єкти завжди мають кілька шарів тіні — ближня (чітка) та далека (розмита).

/* Одна тінь — пласко */
.card-flat {
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
}

/* Дві тіні — вже є глибина */
.card-layered {
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.08),
    0 8px 24px rgba(0, 0, 0, 0.12);
}

/* Три тіні — преміальний ефект */
.card-premium {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.06),
    0 4px 8px rgba(0, 0, 0, 0.08),
    0 16px 40px rgba(0, 0, 0, 0.10);
}
Правило шарування: менша тінь ближча до елемента (мале зміщення, маленький blur, більша непрозорість), більша — далі (велике зміщення, великий blur, менша непрозорість). Це імітує фізику поширення тіні від точкового джерела світла.
🔒localhost:3000

inset — тіні всередині

Ключове слово inset перетворює зовнішню тінь на внутрішню. Корисно для:

  • Ефекту вдавленої кнопки при натисканні (:active стан)
  • Стилізації полів вводу (фокус-стан)
  • Neumorphism — поєднання зовнішніх тіней для 3D-ефекту
.btn:active {
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.25);
  transform: translateY(1px);
}

.input:focus {
  box-shadow:
    0 0 0 3px rgba(99, 102, 241, 0.2),
    inset 0 1px 3px rgba(0, 0, 0, 0.1);
}
🔒localhost:3000

text-shadow — тіні для тексту

text-shadow працює аналогічно до box-shadow, але застосовується до форми літер, а не до прямокутника елемента. Синтаксис спрощений — немає параметрів spread та inset:

text-shadow: offset-x offset-y blur-radius color;
/* Легка читабельна тінь */
h1 {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}

/* Тінь для тексту на зображенні */
.hero-title {
  color: white;
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
}

/* Неонове світіння */
.neon {
  color: #00f5ff;
  text-shadow:
    0 0 8px #00f5ff,
    0 0 20px #00f5ff,
    0 0 40px #0080ff;
}

/* Множинні тіні для глибини */
.retro {
  color: white;
  text-shadow:
    2px 2px 0 #f59e0b,
    4px 4px 0 #d97706;
}
🔒localhost:3000

filter — CSS фільтри

CSS-властивість filter застосовує графічні ефекти до елемента та всього його вмісту (включно з дочірніми елементами). На відміну від box-shadow, яка обходить прямокутник, filter: drop-shadow() слідує реальній формі елемента.

Огляд функцій filter

ФункціяОписПриклад
blur(r)Розмиттяblur(4px)
brightness(n)Яскравістьbrightness(1.5)
contrast(n)Контрастcontrast(1.2)
grayscale(n)Знебарвленняgrayscale(100%)
hue-rotate(deg)Зміна відтінкуhue-rotate(90deg)
invert(n)Інвертуванняinvert(100%)
opacity(n)Прозорістьopacity(0.5)
saturate(n)Насиченістьsaturate(2)
sepia(n)Сепіяsepia(80%)
drop-shadow(...)Тінь за формоюdrop-shadow(2px 4px 8px black)
🔒localhost:3000

Комбінування фільтрів

Кілька функцій записуються через пробіл — вони застосовуються зліва направо:

/* Фото у вінтажному стилі */
.vintage {
  filter: sepia(40%) brightness(0.9) contrast(1.1) saturate(0.8);
}

/* Hover-ефект на картці з зображенням */
.card img {
  filter: grayscale(100%) brightness(0.8);
  transition: filter 0.4s ease;
}
.card:hover img {
  filter: grayscale(0%) brightness(1);
}
🔒localhost:3000

filter: drop-shadow() vs box-shadow

Це найважливіша різниця, яку варто зрозуміти. Обидві властивості створюють тіні, але принципово по-різному:

  • box-shadow — малює тінь від прямокутного bounding box елемента. Форма тіні завжди прямокутна (або заокруглена через border-radius).
  • filter: drop-shadow() — малює тінь від реальних пікселів елемента. Ідеально для PNG зображень з прозорістю та SVG-іконок.
/* Синтаксис drop-shadow — як box-shadow, але без spread */
filter: drop-shadow(offset-x offset-y blur color);
filter: drop-shadow()не має параметра spread-radius та inset. Якщо потрібне розширення тіні — лише box-shadow.
🔒localhost:3000

Подивіться на трикутник: box-shadow дає прямокутну тінь, а drop-shadow точно повторює форму трикутника. Для SVG-іконок, логотипів та PNG — завжди використовуйте drop-shadow.


backdrop-filter — фільтр під елементом

backdrop-filter — це одна з найефектніших властивостей сучасного CSS. На відміну від filter, що застосовується до самого елемента та його вмісту, backdrop-filter застосовується до того, що знаходиться ЗА елементом.

Це основа для ефекту glassmorphism (матового скла):

.glass-card {
  background: rgba(255, 255, 255, 0.15);
  backdrop-filter: blur(12px) saturate(1.8);
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 16px;
}
backdrop-filter вимагає, щоб елемент мав напівпрозорий або прозорий фон. Якщо background: white — ефект не буде видно, бо фон перекриє зображення під ним.
🔒localhost:3000

Практичний паттерн: навігаційна панель з blur

Один із найпопулярніших застосувань backdrop-filter — «липкий» хедер, який розмиває вміст сторінки під собою:

.navbar {
  position: sticky;
  top: 0;
  z-index: 100;

  background: rgba(255, 255, 255, 0.75);
  backdrop-filter: blur(16px) saturate(1.5);
  -webkit-backdrop-filter: blur(16px) saturate(1.5);

  border-bottom: 1px solid rgba(0, 0, 0, 0.08);
}

/* Темна тема */
@media (prefers-color-scheme: dark) {
  .navbar {
    background: rgba(15, 23, 42, 0.8);
    border-bottom-color: rgba(255, 255, 255, 0.08);
  }
}
Prefixing:backdrop-filter досі вимагає вендорного префікса для WebKit. Завжди додавайте обидва рядки: -webkit-backdrop-filter та backdrop-filter.

Система тіней у design system

Замість хаотичних значень у кожному компоненті — визначте систему CSS-змінних заздалегідь. Це те, що роблять великі design systems (Tailwind, Material, Radix):

:root {
  /* За рівнями підняття (elevation) */
  --shadow-xs:  0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-sm:  0 1px 3px rgba(0, 0, 0, 0.1),
                0 1px 2px rgba(0, 0, 0, 0.06);
  --shadow-md:  0 4px 6px rgba(0, 0, 0, 0.07),
                0 2px 4px rgba(0, 0, 0, 0.06);
  --shadow-lg:  0 10px 15px rgba(0, 0, 0, 0.1),
                0 4px 6px rgba(0, 0, 0, 0.05);
  --shadow-xl:  0 20px 25px rgba(0, 0, 0, 0.1),
                0 10px 10px rgba(0, 0, 0, 0.04);
  --shadow-2xl: 0 25px 50px rgba(0, 0, 0, 0.25);

  /* Кольорові тіні для CTA-елементів */
  --shadow-primary:  0 8px 24px rgba(99, 102, 241, 0.35);
  --shadow-success:  0 8px 24px rgba(16, 185, 129, 0.35);
  --shadow-danger:   0 8px 24px rgba(239, 68, 68, 0.35);

  /* Фокус-кільця (доступність) */
  --ring-primary: 0 0 0 3px rgba(99, 102, 241, 0.35);
  --ring-danger:  0 0 0 3px rgba(239, 68, 68, 0.35);
}

Використання:

.card        { box-shadow: var(--shadow-md); }
.modal       { box-shadow: var(--shadow-2xl); }
.btn-primary { box-shadow: var(--shadow-primary); }
.btn:focus   { box-shadow: var(--ring-primary); }
🔒localhost:3000

Продуктивність та підводні камені

Що коштує дорого

CSS-фільтри та тіні запускають compositor та іноді paint кроки в конвеєрі рендеру:

ВластивістьКрок рендеруВартість
box-shadowPaint + Composite⚠️ Помірна
filter: blur()Paint + Composite🔴 Висока
filter: drop-shadow()Paint + Composite⚠️ Помірна
backdrop-filterComposite🔴 Дуже висока
text-shadowPaint⚠️ Помірна
backdrop-filter: blur() з великим радіусом на великих елементах — один із найдорожчих ефектів у CSS. На мобільних пристроях може викликати помітне гальмування. Завжди тестуйте на реальних пристроях і обмежуйте blur до 12–16px.

Best practices

/* ✅ Анімуйте opacity + transform, а не box-shadow */
.card {
  box-shadow: var(--shadow-md);
  transition: transform 0.25s ease, box-shadow 0.25s ease;
}
.card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-xl);
}

/* ✅ will-change лише на елементах, що часто анімуються */
.animated-card:hover {
  will-change: transform, box-shadow;
}

/* ✅ prefers-reduced-motion */
@media (prefers-reduced-motion: reduce) {
  .card {
    transition: none;
  }
}

/* ❌ Не ставте backdrop-filter на весь body */
body {
  backdrop-filter: blur(20px); /* Ніколи так! */
}

/* ✅ Обмежте розмір і кількість елементів з blur */
.toast-notification {
  backdrop-filter: blur(8px); /* Невеликий елемент — ок */
}

Практика: UI-компоненти з тінями

Картка продукту

🔒localhost:3000

Резюме

Loading diagram...
mindmap
  root((CSS Тіні та Фільтри))
    box-shadow
      Параметри offset blur spread color
      inset — внутрішні тіні
      Множинні тіні через кому
      Відповідає прямокутній формі
    text-shadow
      offset blur color
      Немає spread та inset
      Неонові та retro ефекти
    filter
      blur brightness contrast
      grayscale sepia hue-rotate
      drop-shadow — тінь за формою
      Комбінування через пробіл
    backdrop-filter
      Фільтрує вміст ЗА елементом
      Glassmorphism blur
      Потребує прозорого фону
    Продуктивність
      box-shadow — Paint
      filter blur — дорого
      backdrop-filter — дуже дорого
      will-change обережно
    Design System
      CSS-змінні для тіней
      Система elevation
      Кольорові тіні для CTA

Завдання для самоперевірки


Попередня стаття: Кольори та фони в CSS

Наступна стаття: Flexbox — основи