Box-shadow

box-shadow добавляет тени к элементу: внешние и внутренние, одиночные и множественные. Тени не влияют на размер и поток элемента. Также рассмотрим text-shadow для текстовых теней.

Зачем нужно

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

Где используется

  • Карточки (elevation)
  • Кнопки (pressed/hover state)
  • Модальные окна
  • Neumorphism дизайн
  • Фокус-индикаторы (замена outline)
  • Декоративные эффекты

Предпосылки


Базовый синтаксис

/* box-shadow: offsetX offsetY blur spread color */
.card {
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

/* С spread (расширение) */
.box {
  box-shadow: 0 4px 12px 2px rgba(0, 0, 0, 0.15);
}

/* Inset (внутренняя тень) */
.inset {
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.2);
}

/* Без тени */
.flat() { box-shadow: none; }
Параметр Описание Обязателен?
inset Внутренняя тень Нет
offsetX Горизонтальное смещение Да
offsetY Вертикальное смещение Да
blur Радиус размытия Нет (default: 0)
spread Расширение/сжатие тени Нет (default: 0)
color Цвет тени Нет (default: currentColor)

Множественные тени

/* Реалистичная тень — несколько слоёв */
.realistic {
  box-shadow:
    0 1px 2px rgba(0, 0, 0, 0.07),
    0 2px 4px rgba(0, 0, 0, 0.07),
    0 4px 8px rgba(0, 0, 0, 0.07),
    0 8px 16px rgba(0, 0, 0, 0.07);
}

/* Мягкая тень (Material Design подход) */
.soft {
  box-shadow:
    0 2px 4px rgba(0, 0, 0, 0.06),
    0 4px 6px rgba(0, 0, 0, 0.1);
}

Система elevation (уровни возвышения)

:root {
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1),
               0 2px 4px -2px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1),
               0 4px 6px -4px rgba(0, 0, 0, 0.1);
  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1),
               0 8px 10px -6px rgba(0, 0, 0, 0.1);
  --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);
}

.card         { box-shadow: var(--shadow-md); }
.card:hover   { box-shadow: var(--shadow-lg); }
.dropdown     { box-shadow: var(--shadow-lg); }
.modal        { box-shadow: var(--shadow-2xl); }

Креативные эффекты

Neumorphism

.neumorphic {
  background: #e0e5ec;
  border-radius: 16px;
  box-shadow:
    8px 8px 16px #b8bec7,
    -8px -8px 16px #ffffff;
}

.neumorphic-pressed {
  background: #e0e5ec;
  border-radius: 16px;
  box-shadow:
    inset 8px 8px 16px #b8bec7,
    inset -8px -8px 16px #ffffff;
}

Цветная тень

.glow {
  background: #3498db;
  box-shadow: 0 8px 24px rgba(52, 152, 219, 0.5);
}

.neon {
  box-shadow:
    0 0 5px #3498db,
    0 0 10px #3498db,
    0 0 20px #3498db,
    0 0 40px #3498db;
}

Одностороняя тень

/* Только нижняя тень */
.bottom-only {
  box-shadow: 0 4px 8px -2px rgba(0, 0, 0, 0.1);
  /* Отрицательный spread скрывает боковые стороны */
}

/* Только верхняя */
.top-only {
  box-shadow: 0 -4px 8px -2px rgba(0, 0, 0, 0.1);
}

Замена outline для фокуса

button:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px rgba(52, 152, 219, 0.5);
  /* spread без blur = ровная рамка, повторяет border-radius */
}

text-shadow

/* text-shadow: offsetX offsetY blur color */
h1 {
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3);
}

/* Несколько теней */
.emboss {
  color: #666;
  text-shadow:
    1px 1px 0 #fff,
    -1px -1px 0 #999;
}

/* Свечение текста */
.glow-text {
  color: white;
  text-shadow:
    0 0 10px rgba(52, 152, 219, 0.8),
    0 0 20px rgba(52, 152, 219, 0.5);
}
box-shadow text-shadow
Есть inset Нет inset
Есть spread Нет spread
Тень от бокса Тень от глифов текста
Учитывает border-radius Следует форме букв

Производительность

/* box-shadow НЕ вызывает reflow, только repaint */
/* Но анимация box-shadow дороже, чем transform */

/* МЕДЛЕННО — анимация box-shadow */
.card {
  transition: box-shadow 0.3s;
}
.card:hover {
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
}

/* БЫСТРО — анимация через pseudo-element */
.card {
  position: relative;
}
.card::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: 0 20px 40px rgba(0, 0, 0, 0.2);
  opacity: 0;
  transition: opacity 0.3s;
}
.card:hover::after {
  opacity: 1; /* Анимируем opacity — GPU-ускорение */
}

Частые ошибки

  1. Слишком тёмная/резкая тень — реалистичные тени мягкие и полупрозрачные:

    /* ГРУБО */
    box-shadow: 5px 5px 5px black;
    /* ХОРОШО */
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    
  2. Анимация box-shadow напрямую — дорого для GPU. Используйте opacity на псевдоэлементе

  3. Забыт rgba/hsla для прозрачностиbox-shadow: 0 2px 8px black слишком жёсткий

  4. box-shadow для фокуса без border-radius — если элемент скруглён, box-shadow повторяет его форму (это плюс), но нужно помнить про это

Практика

  • Создать систему elevation из 5 уровней теней
  • Реализовать neumorphism для кнопки
  • Создать hover-эффект с анимированной тенью (через pseudo-element)
  • Заменить outline на box-shadow для :focus-visible
  • Создать неоновый эффект свечения

Связанные темы

Ресурсы