company_banner

CSS3. Работа с тенями. Часть 1

  • Tutorial
Так получилось (и прошу считать это удачным совпадением), именно сегодня на Хабре опубликован топик про практическое применение теней из CSS3 для создания интересных эффектов, а мы в свою очередь подготовили топик про основы для этого творчества.

Мы попробуем разобраться в том, как работают тени в новых модулях CSS3. С практической точки зрения, мы рассмотрим два правила: box-shadow и text-shadow, определенные соответственно в модулях CSS3 Backgrounds and Borders и CSS3 Text.

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

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

box-shadow


Сдвиги и цвет


Simple Shadow

В самом простом варианте для задания тени достаточно указать два параметра, задающие соответственно горизонтальный и вертикальный сдвиги тени (1.1):
box-shadow: 3px 3px;

Положительные значения сдвига смещают тень вправо и вниз, отрицательные — влево и вверх.

По умолчанию, если цвет тени не задан, в большинстве браузеров (все, кроме webkit-based) он берется из цвета текста (color) в текущем контексте (1.2), впрочем, похоже, этот момент спецификацией не обговаривается:
box-shadow: 3px 3px; color:blue;

Чтобы задать цвет тени, достаточно указать его дополнительным параметром (1.3):
box-shadow: 3px 3px darkgreen;

Очевидно, цвет можно указывать любым из доступных способов: от прямого указания названия и шестнадцатеричного кода, до rgb или rgba и hsla с прозрачностью (мы рассмотрим такие примеры чуть позже).

Размытие

Blured Shadow
Третий «линейный» параметр, который можно задать при описании тени — это радиус размытия (blur), положительная величина, указывающая насколько сильно нужно размывать тень по пространству (2.1–2.3):
box-shadow:3px 3px 3px darkgrey;

По умолчанию радиус размытия равен 0 и в этом случае тень получается четкой.
В сочетании с разными сдвигами тени, можно получить разные эффекты, например, на (2.3) оба сдвига тени равны нулю, но за счет размытия тень выступает с разных сторон:
box-shadow:0 0 9px black;

Сам алгоритм размытия спецификацией не описывается, кроме указания того, что это должен быть эффект, аналогичный размытию по Гауссу (Gaussian blur) с половинным радиусом в обе стороны от границы тени (2.4):
Gaussian blur

Растяжение

Sprayed Shadow
Еще один интересный параметр — это растяжение или распространие тени (spray), позволяющее увеличить или уменьшить ее размеры (по умолчанию размеры тени соответствуют размеру исходного объекта). Надо отметить, что этот параметр не сразу появился в спецификации, поэтому во множестве примеров в интернете он просто не рассматривается.
Для увеличения тени нужно указать положительный spray-параметр (3.1, 3.2):
box-shadow:6px 6px 0px 4px darkred;

Для уменьшения — отрицательный (3.3):
box-shadow:12px 12px 8px -4px darkred;

Растяжение или сжатие тени можно расценивать как операцию масштабирования, но спецификация описывает это несколько более хитро (через аналогию с размытием и удаление прозрачных или непрозрачных пикселей), что, впрочем, не меняет сути дела:
Sprayed Shadow
На примере выше (3.4) тень смещена на 6px вниз и влево и увеличена на 8px с каждой стороны:
box-shadow:6px 6px 0 8px grey;

Если в вашем блоке используются скругленные уголки, будьте готовы к тому, что в расширенной тени радиус скругления также будет пропорционально смаштабирован (3.5):
Sprayed Shadow with border-radius

Внутренняя тень

Inner Shadow
Наконец, еще один хитрый параметр — это возможность применения тени внутри блока. Для этого используется специальное ключевое слово inset (4.1-4.4):
box-shadow:inset 4px 4px rgba(66,66,66,0.5); /* (4.1) */
box-shadow:inset 4px 4px 0 8px rgba(198,198,198,1); /* (4.2) */
box-shadow:inset -2px -2px 8px 0px black; /* (4.3) */
box-shadow:inset 0 0 4px 0px black; /* (4.4) */

Обратите внимание, что внутренняя тень отрисовывается только внутри блока, к которому применено соответствующее правило, причем применение spray-параметра для внутренней тени (4.2) в отличие от внешней приводит к уменьшению внутреннего перимерта тени.

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


Ну и теперь еще один нюанс: на самом деле, к блокам можно применять любое количество теней одновременно, для этого достаточно их перечислить через запятую при описании box-shadow.
Rainbow Shadows
Например, чтобы получить радужную тень (5.1) достаточно последовательно указать 7 теней с увеличивающимся растяжением:
box-shadow: 0 0 2px 1px red,
            0 0 2px 2px orange,
            0 0 2px 3px yellow,
            0 0 2px 4px green,
            0 0 2px 5px lightblue,
            0 0 2px 6px blue,
            0 0 2px 7px violet;

Обратите внимание, что фактически тени выстраиваются в стек в обратном порядке и отрисовываются, начиная с последней, причем каждая из них применяется к исходному объекту так, как будто есть только она.
Colour Shadows
Так как тени независимы, вы легко можете сочетать тени, выстроенные в разных направлениях (5.2):
box-shadow: -6px -6px 8px -4px rgba(255,0,0,0.75),
            6px -6px 8px -4px rgba(0,255,0,0.75),
            6px 6px 8px -4px rgba(255,255,0,0.75),
            -6px 6px 8px -4px rgba(0,0,255,0.75);

Inner Shadows
Аналогично, можно сразу задавать внутренние и внешние тени (5.3):
box-shadow: inset 0 0 8px lightgray,
            1px 1px 3px darkgray;

Underline Shadows
Или «продвинутое подчеркивание» (5.4):
box-shadow: 0 1px red,
            0 3px 3px -2px black

Slick Shadows
Или, если проявить еще немного фантазии и дополнительных спецэффектов, сделать slick-box, описанный, например, у Matt Hamm (5.5):
.slick-box {
    position: relative;
    height: 50px;
    border: 1px solid #efefef;
    background: #fff;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;
}

.slick-box:before, .slick-box:after {
    content: '';
    z-index: -1;
    position: absolute;
    left: 10px;
    bottom: 10px;
    width: 70%;
    max-width: 300px; /* avoid rotation causing ugly appearance at large container widths */
    height: 55%;
    box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);
    transform: skew(-15deg) rotate(-6deg);                 
}
            
.slick-box:after {
    left: auto;
    right: 10px;
    transform: skew(15deg) rotate(6deg);                 
}

(Для упрощения, я убрал код с вендорными префиксами, но вам нужно будет добавить -ms-transform, -webkit-transform и т.д.)

Общий синтаксис


Резюмируя, синтаксис для описания теней выглядит следующим образом:
box-shadow: <shadow> [ , <shadow> ]*;
<shadow> = inset? && [ <length>{2,4} && <color>? ]

Последнее в полном виде разворачивается в следующую схему:
box-shadow: inset? h-offset v-offset blur-radius spread-distance color;

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

Интерактив


Hands-on: box-shadow
Если вы хотите просто поиграться с тенями в интерактивном режиме, наши коллеги к прошедшей в сентябре конференции Build подготовили демонстрационную страницу: "Hands-on: box-shadow".

Internet Exlorer


Насущный для многих вопрос: box-shadow поддерживается в IE9 и выше.

И еще одна важная деталь: стандартные css-правила, начиная с 9й версии Internet Explorer, работают с использованием аппаратного ускорения — в отличие от нестандартных старых фильтров вроде filter:DXImageTransform.Microsoft.Shadow. То есть, использовать стандарты не только правильнее, но и эффективнее.

Мой совет: старайтесь использовать стандартные возможности, исходя из идей progressive enhacenment.
Microsoft
272,00
Microsoft — мировой лидер в области ПО и ИТ-услуг
Поделиться публикацией

Комментарии 30

    +2
    Эх, оставили меня без темы для следующей статьи :) Придется, видимо, о луковом супе писать.
      +2
      Ага, забавное совпадение :)
      +3
      Из каких соображений нет поддержки text-shadow?
        +1
        * в IE
          0
          text-shadow есть в IE10, об этом будет во второй части.

          А так соображения чисто практические: востребованность, приоритезация и наличие ресурсов на реализацию в конкетный временной отрезок. В общем, text-shadow не попал в цикл разработки IE9, но уже реализован в рамках работы над IE10.
            +1
            А правда ли то, что знаменитое полное аппаратное ускорение не работает в IE 9 64 bit, причём ни полностью, ни частично?
              0
              Насколько я могу судить, аппаратное ускорение графики работает одинаково в обоих версиях.
                0
                На производительности теней я не тестировал, но непонятно почему FishIE Tank так работает (на переднем фоне IE 64 bit, на заднем — 32)

                  0
                  Странно, а если запустить их по отдельности, а не одновременно? Я знаю, что у них js-движки отличаются, но конкретно в этой демонстрации это не должно сказываться.
                    +2
                    При 1000 рыбках — все упирается уже в js движок.
            0
            День CSS теней :)
              0
              Точнее, вечер.
              +2
              Весьма хороший топик. А можно сказать, что из рассказанного поддерживается в ie8 (кажется последний для xp sp3) и ie9?
                0
                Все рассказанное поддерживается в IE9. IE8 box-shadow по понятным причинам не поддерживает.
                  0
                  Ясно, спасибо.
                0
                Расскажите про прозрачность тени. Что бы она не была как в 3.5 с четкими границами и блёром на, а будто тень — прозраный png.
                  0
                  Чтобы сделать тень прозрачной, достаточно указать цвет с прозрачностью, например, через rgba(r,g,b,a). В примере 5.2 тени смешиваются между собой.
                    0
                    Да, моя ошибка. Свойство border рисует границу внутри объекта, а не снаружи и прозрачность границы сталкивается с окрашенным фоном. В моем случае была проблема с прозрачностью меню из элементов списка ul/li. Сейчас все стало на места.
                • НЛО прилетело и опубликовало эту надпись здесь
                    0
                    Интересная статья.
                      0
                      Спасибо Корпорации Microsoft за поддержку этих свойств; правда, пользователи WinXP, очевидно, останутся без неё, если не откажутся от Internet Explorer в пользу альтернативного браузера: IE9 и IE10 для WinXP нет и никогда, никогда не будет.
                        0
                        Скажите, а градиенты и скругленные уголки уже починили в IE10? А то помню в одном из превью Microsoft ну очень хвасталась этими функциями по-отдельности, но при попытке применить их вместе получался epic fail.
                          0
                          По-моему градиенты и скругленные уголки изначально работали отлично вместе, если делать без извращений с фильтрами.
                            0
                            А, ну да, сейчас проверил — действительно -ms-linear-gradient и border-radius работает хорошо вместе (тестил в IE10 P2). Но стоит добавить filter для старших версий IE, как все сразу ломается. Я не думаю, что кто-то пишет только под IE10 сейчас, а ставить условные коментарии и искать css хаки чтобы это работало только в определенной версии IE достало, достало, достало, достало. Хак для 6, хак для 7, хак для 8, хак для 9 и хак для 10 теперь, чтобы он не увидел фильтров. Замечательно.
                              0
                              Проблема в том что когда придумывались фильтры — все блоки на вэб странице могли быть только прямоугольной формы — и фильтры на это и рассчитывали. Само собой что переписывать код фильтров в 9 ИЕ чтобы они работали нормально совместно с бордер радиус никто не стал.

                              CSS градиенты же вообще штука довольна новая, по сравнению даже с закругленными уголками. Поэтому их и нет в ИЕ9. Зато там есть SVG градиенты — и вот вполне себе удобный инструмент для этого ie.microsoft.com/testdrive/Graphics/SVGGradientBackgroundMaker/Default.html
                                –1
                                Проблема в том, что для не нужно для IE9+ делать хаков. Хаки — это зло.

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

                                Лично мое мнение: даже для старых браузеров не нужно использовать фильтры.
                                  +1
                                  Хаки для IE можно не использовать, можно просто добавить после doctype:

                                  <!doctype html>
                                  <!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
                                  <!--[if IE 7]> <html class="ie7" lang="en"> <![endif]-->
                                  <!--[if IE 8]> <html class="ie8" lang="en"> <![endif]-->
                                  <!--[if gt IE 8]><!--> <html lang="en"> <!--<![endif]-->
                                  <head>


                                  А в css писать — .ie6 div { color: #ff8000; }.
                              0
                              Мне кажется, этот пост вместо «Microsoft» был бы более уместен в «Каскадные Таблицы Стилей».
                                0
                                Но за содержание +
                                0
                                Прекрасно отображается и в Opera 11.52. Правда, когда на странице много элементов типа slick-box с навороченными тенями — начинает заметно подтормаживать при прокрутке.

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

                                Самое читаемое