Дрессируем box-shadow

    Простой пример box-shadow Разработчики W3C сделали box-shadow очень гибким свойством. Благодаря этому можно получать весьма интересные результаты, если использовать это свойство нетривиальным образом. В этой статье я напишу о некоторых эффектах, которые мне удалось получить при помощи «теневых технологий».

    Пока я составлял примеры, я неожиданно обнаружил, что браузеры отображают их совсем неодинаково. В итоге, помимо простой демонстрации возможностей box-shadow, получился еще и маленький браузерный тест на поддержку CSS 3. Все примеры снабжены CSS-кодом и картинкой (общий объем всех PNG: 161 КБ). В статье я не стал прописывать свойства с вендорными префиксами -moz- и -webkit-, чтобы не ухудшать читабельность. В суммарной странице со всеми примерами эти префиксы есть (предупреждаю, что у Оперы есть баг с прорисовкой внешних box-shadow при прокрутке).

    Клонирование (шлейф)


    Свойство box-shadow позволяет создать множество теней, что можно использовать весьма своеобразно. Ниже показан div-элемент с неким подобием шлейфа (в некоторых играх снаряды примерно такие «хвосты» описывают).

    Клонирование (шлейф)

    Как получилось у меня? Потребовалось просто создать несколько «теней» с разным позиционированием и цветом. Напоминаю порядок линейных размеров свойства box-shadow: отступ по оси X (положительное значение — вправо, отрицательное — влево), отступ по оси Y, радиус размытия и последний — масштаб.

    Как выходит у браузеров? У Opera и Firefox никаких проблем не возникло. Что касается webkit-браузеров, то они, похоже, любят играть в разоблачителей. «Тени» они нарисовали квадратными, обнажая истинную сущность круга: квадрат с максимальным закруглением уголков. Это, конечно, интересно, но FAIL. Кстати, весьма примечательно, что самую последнюю «тень» они всё-таки нарисовали круглой (если вы ее совсем не видите, то пора разбираться с гаммой вашего монитора).

    #trail {
    	background: #d0d0d0;
    	border: 1px solid #c0c0c0;
    	border-radius: 40px;
    	box-shadow: #d8d8d8 110px -25px 0 -10px,
    	            #e0e0e0 210px  15px 0 -15px,
    	            #e8e8e8 310px -10px 0 -20px,
    	            #f0f0f0 410px   5px 0 -25px,
    	            #f4f4f4 510px   0px 0 -30px;
    	height: 75px;
    	margin: 20px;
    	width: 75px;
    	}
    


    Свечение


    Всякую тень, которую можно окрасить в яркий цвет и сильно размыть, можно использовать для эффекта свечения. Так как CSS box-shadow это позволяет, то почему бы не воспользоваться?

    Свечение

    Как получилось у меня? Я залил круг (квадрат) светло-красным цветом и пустил 2 красные размытые «тени»: одну внутрь, другую наружу. Тем самым я получил эффект свечения, при котором центральная часть кажется ярче. Во всяком случае, звезды обычно так и рисуют.

    Как выходит у браузеров? Ни один браузер не сделал это идеально. У Opera и Firefox (а также у Safari, но не так выраженно) почему-то вышла тонкая светлая обводка вокруг элемента. Чем выше гамма монитора, тем она заметнее. В принципе эту обводку можно избежать, если сделать элемент прозрачным и оставить только внешнюю «тень». Но тогда и не будет эффект более светлого участка в центре. Ан-нет. Оказывается, стандарт предписывает обрезать тень под элементом, так что прозрачность не поможет. Теперь понятно, откуда взялась окантовка: это anti-aliasing Safari и Chrome сделали свечение недостаточно округлой. У Chrome просто безобразие.

    #glow {
    	background: #ff8080;
    	border-radius: 40px;
    	box-shadow: inset #ff0000 0 0 40px 10px,
    	                  #ff0000 0 0 24px 12px;
    	height: 75px;
    	margin: 45px; 
    	width: 75px;
    	}
    


    Мнократный border


    Возможно, у вас иногда будет появляться необходимость использовать две или больше линий вокруг элемента. Outline даст только одну дополнительную, да и не во всех браузерах закруглишь ее. А у border-style фантазия ограничена. В таком случае поможет box-shadow. В данном примере изображена беговая дорожка.

    Мнократный border

    Как получилось у меня? Нужно наложить несколько «теней» подряд с разными масштабами (размерами). Для коричневых дорожек я увеличивал масштаб на 3 пикселя по сравнению с предыдущей тенью (ну или рамкой). Для белой линии — на один пиксель. Нужно помнить, что более глубокие слои должны находиться в списке последними, так как порядок имеет значение).

    Как выходит у браузеров? Opera и Firefox отрисовали почти идентично. А вот Chrome и Safari показали нечто гипнотическое. Тут же, кстати, можно обнаружить причину недостаточно округлой «тени» в предыдущем примере (свечение). Оказывается Webkit-ы не увеличивают и не уменьшают border-radius для тени пропорционально увеличению/уменьшению самой тени. Досадный косяк.

    #multi-border {
    	background: #804020;
    	border: 1px solid #ffffff;
    	border-radius: 40px;
    	box-shadow:
    	/* линии внутри */
    	inset #804020 0 0 0  3px,
    	inset #ffffff 0 0 0  4px,
    	inset #804020 0 0 0  7px,
    	inset #ffffff 0 0 0  8px,
    	/* линии снаружи */ 
    	      #804020 0 0 0  3px,
    	      #ffffff 0 0 0  4px,
    	      #804020 0 0 0  7px,
    	      #ffffff 0 0 0  8px,
    	      #804020 0 0 0 15px;
    	height: 75px;
    	margin: 35px;
    	width: 150px;
    	}
    


    Эффект объема (выпуклость)


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

    Эффект объема (выпуклость)

    Как получилось у меня? Потребовалось создать две внутренние «тени»: одна светлая, другая темная. Светлая — со смещением вправо вниз, темная — влево вверх. При этом светлая и темная «тени» должны быть созданы с помощью полупрозрачности белого и черного цветов. Благодаря полупрозрачности (если правильно отрегулированы альфа-каналы), места слияния темной и светлой «тени» обретают цвет, близкий к цвету background-а. В противном случае, одна из «теней» будет преобладать, что уменьшит реалистичность. Если в примере обнулить размытие «теней», то будет легче понять принцип работы кода.

    Как выходит у браузеров? Будем считать, что Opera, Firefox и Safari нарисовали объемный прямоугольник одинаково. Что касается Chrome, тот тут мы и находим причину некоторых косяков в предыдущих примерах: внутренние «тени» всегда вылезают за пределы border-radius.

    #embossment {
    	background: #404040;
    	border-radius: 20px;
    	box-shadow: inset rgba(255,255,255,0.2) 8px  8px 18px 5px,
    	            inset rgba(0,0,0,0.5)      -8px -8px 18px 5px;
    	height: 75px;
    	margin: 20px; 
    	width: 150px;
    	}
    


    Градиент


    Маразм крепчает. Теперь рисуем с помощью box-shadow радужный градиент. Вообще градиенты предусмотрены в черновике W3C, но Opera пока не поддерживает их. Так что практическая польза в этом, как ни странно, есть.

    Градиент

    Как получилось у меня? Сначала залил прямоугольник красным фоном. Затем поочередно наложил «тени» нужных цветов (для удобства сначала без размытия): желтый, зеленый, голубой, синий, фиолетовый, снова красный. Каждый последующий цвет должен был быть выше по глубине и правее смещен, чтобы был виден предыдущий цвет. Затем применил размытие: радиус должен совпадать с протяженностью цвета в градиенте. Как только увидел результат, я вспомнил, что заблюривание идет во все стороны, а не только по бокам, из-за чего верхняя и нижняя часть всего градиента пропустила сквозь себя красный фон. Чтобы избавится от этого эффекта, пришлось увеличить все «тени» и потом на такую же величину сместить их вправо, чтобы компенсировать изменение размеров. Для контроля проверил без размытия. Готово.

    Как выходит у браузеров? Opera и Firefox опять показали идентичный глазу результат. Chrome показал более насыщенный цвет в местах минимального размытия теней. Не возьмусь сказать, кто правильнее сделал. Кажется, что правда лежит посередине. Safari совсем слабо заблюрил «тени», поэтому градиент вышел явно неправильным. Все браузеры, кроме Chrome, притормаживали во время прокрутки страницы до нужного блока с градиентом. Safari тормозил несравненно феерично.

    #gradient {
    	background: #ff0000;
    	border: 1px solid #000000;
    	box-shadow: inset #FF0000 -150px 0 100px -100px,
    	            inset #FF00FF -250px 0 100px -100px,
    	            inset #0000FF -350px 0 100px -100px,
    	            inset #00FFFF -450px 0 100px -100px,
    	            inset #00FF00 -550px 0 100px -100px,
    	            inset #FFFF00 -650px 0 100px -100px;
    	height: 200px;
    	margin: 20px;
    	width: 600px;
    	}
    


    Пламя!


    Ну а теперь апофеоз фрик-кодинга: огонь с помощью box-shadow! Убил на него, наверное, часа 2, поскольку постоянно приходилось переделывать. В данном примере изображена горящая спичка, находящаяся параллельно к земле и повернутая головкой в сторону зрителя. Получилось, конечно, не слишком правдоподобно. Но ведь это пламя в CSS!

    Пламя!

    Как получилось у меня? Без комментариев, смотрите сразу код :)

    Как выходит у браузеров? У Opera и Firefox отличия минимальные. У Safari «тени» опять слишком квадратные, поэтому пламя вышло шире. За головкой спички — какой-то странный черный квадрат. Chrome тоже сделал огонь слишком широким, но в добавок еще и размытие отрисовал весьма грубо.

    <div id="black-background">
    	<div id="burning"></div>
    </div>
    

    #black-background {background: #000000;}
    
    #burning {
    	background: #402000;
    	border-radius: 40px;
    	box-shadow:
    	/* головка */
    	inset #806040 0 0 10px 2px,
    	/* прозрачно-голубо-белая часть */
    	#102030 0px    0px 20px   6px,
    	#c8d8e0 0px  -10px 17px   4px,
    	#d8e8f0 0px  -20px 15px  -2px,
    	#e0f0f8 0px  -30px 14px  -6px,
    	#e8f8ff 0px  -40px 12px  -9px,
    	#ffffff 0px  -50px 10px -12px,
    	#ffffe0 0px  -55px 10px -14px,
    	#ffffc0 0px  -60px 10px -20px,
    	#ffffa0 0px  -62px 10px -22px,
    	#ffff80 0px  -64px 10px -24px,
    	/* желто-красная часть */
    	#ffff40 0px    0px 15px   4px,
    	#ffff30 0px  -10px 13px   6px,
    	#ffff20 0px  -20px 12px   8px,
    	#ffff10 0px  -30px 11px   6px,
    	#ffff00 0px  -40px 10px   4px,
    	#fff000 0px  -50px 10px   2px,
    	#ffe000 0px  -60px 10px   0px,
    	#ffd000 0px  -70px 10px  -4px,
    	#ffc000 0px  -80px 10px  -6px,
    	#ffa000 0px  -90px 10px -10px,
    	#ff8000 0px -100px 10px -14px,
    	#ff6000 0px -110px 10px -16px,
    	#ff4000 0px -120px 10px -20px,
    	#ff2000 0px -124px 10px -22px,
    	#ff0000 0px -127px 10px -24px;
    	height: 60px;
    	margin: 125px 35px 30px 35px;
    	width: 60px;
    	}
    

    UPD: Из любезно предоставленного скриншота из IE9 PP4, можно сказать, что новый IE весьма-таки неплох.

    Похожие публикации

    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама

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

      +3
      В 7 хроме вообще все печально
        +1
        А у вас какой канал? В Канарейке точно так же, как и в 5-м Chrome Stable.
          0
          dev 7.0.503
          скорее всего какое-то расширение виновато
            0
            Расширение может менять рендеринг?
              +3
              Нет, не влияет никак. Chrome подкачал, надо идти писать слёзные мольбы разработчикам. Это безобразие!
              Спасибо вам за такое сравнение!
        +3
        Градиенты это клево.
          +1
          Отличное исследование!

          Сафари на радуге, конечно, феерично тормозит — только при прокрутке вниз, если скроллить вверх, то всё ок. Ну и при переключении на эту вкладку тоже тормозит. И ещё смешнее — если открыть вкладку, но не скроллить, то тормозит при переходе на другую вкладку — т.е. получается, что он дорендеривает зачем-то её содержимое.
            0
            Сафари тормозит когда нужно отрисовать радугу, без разницы вверх или вниз. Сделайте окно маленьким, чтобы радуга выглядывала сверху, будет тормозить при прокрутке вверх.
              0
              Да, тормоза проявляются именно когда градиент попадает из невидимой части страницы в видимую (прокруткой). Так же в Опере и Fx, но не в такой степени. Получается, что box-shadow в этих браузерах отрисовывается именно после попадания в площадь обзора и «забываются» как только мимо него пролетаешь. А у Хрома, похоже, один раз и насовсем.
            +4
            Вот они CSS 3 Tricks!
            Меня пламя поразило. Спасибо.
            От Хрома конечно не ожидал, что так подкачает))
              0
              Как бы там ни было, но он однозначно лучше чем ИЕ.
              А по поводу «подкачает», то не переживайте, багов рендеринга там много, браузер молодой, горячий.
                +2
                На самом деле эти баги рендеринга зарепорчены довольно давно и смержелись в вот этот багрепорт:
                code.google.com/p/chromium/issues/detail?id=29427

                Можно звездочками поддержать важность бага )
                  +1
                  Да разве? В конце статьи появился скриншот IE9TPP4, на мой взгляд, он лучше отрисовал, чем Хром.
                    0
                    Я в общем.
                0
                А где же гвоздь программы — IE9 preview? :)
                  +1
                  Я бы рад, но XP-шка не пускает) Буду благодарен, если кто-то сделает скриншот сводной страницы под IE9 PP4.
                    0
                    box-shadow на данный момент очень глючный в IE9, надеюсь в бета-версии это исправят.
                    +12
                    ie9 — dl.dropbox.com/u/3971799/httpd/screens/screen2.jpg
                    не знаю насколько dropbox подвержен хабраэффекту
                    кстати ie8 печален :)
                    dl.dropbox.com/u/3971799/httpd/screens/screen3.jpg
                      +1
                      Странно, та же версия IE9, но последний тест:
                      habrastorage.org/storage/53b5675e/1fbebdad/ea3f8087/aecdbfd4.png
                        0
                        Да, есть такой глюк, только что дома проверил.
                        ВОт что нашел по этому поводу в комментариях журнала разработчиков IE:
                        the box-shadow feature is actually complete, but its blur radius property is extremely buggy (I submitted a bug on it, still waiting for an answer): if you specify '0' for blur radius, the shadow works properly. If you specify anything other than '0', you get the following cases:
                        — blur is non-linear
                        — shadow's opacity is set around 0.5 and impossible to override
                        — shadow cuts off before the page's bottom
                        Последний пункт, как раз этот случай…
                          0
                          Да. Такое бывает, Но исчезает сразу после скроллинга.
                      0
                      Хром7==Хром5 — без изменений вообще
                        0
                        fix: Хромиум7==Хром5
                          0
                          хром7 тот же результат показывает, так что первая фраза тоже верна
                      • НЛО прилетело и опубликовало эту надпись здесь
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • НЛО прилетело и опубликовало эту надпись здесь
                              +1
                              А какой смысл был их вообще проводить у них же нет поддержки CSS3.
                              Ради смеха только.
                                0
                                кроме 9.
                          0
                          беговую дородку можно было бы сделать только наружной тенью и тогда небыло бы такого ахтунга
                            0
                            Вот подобные штуки нужно добавить в новый ACID(4/5)? для проверки поддержки CSS3, а то ACID3 устарел… :)

                            (ACID4 вроде собирались делать но не уверен что есть уже готовые результаты)
                              0
                              а проблемы с вылезанием тени можно решить обёрткой с overflow: hidden
                                +1
                                Chrome 5, XP SP3. Не помогает.
                                  –1
                                  7.0.503.0 dev — помогает
                                  хром вроде единственный браузер, который умеет обрезать внутренние элементы по бордер-радиусу

                                  #glow ins {
                                  overflow: hidden;
                                  display: block;
                                  margin: 45px;
                                  /* */ -moz-border-radius: 40px;
                                  border-radius: 40px;
                                  /* */ -moz-box-shadow:

                                  #ff0000 0 0 24px 12px;

                                  /* */ -webkit-box-shadow:

                                  #ff0000 0 0 24px 12px;

                                  box-shadow:

                                  #ff0000 0 0 24px 12px;
                                  height: 75px;

                                  width: 75px; }
                                  #glow div {
                                  background: #ff8080;

                                  /* */ -moz-border-radius: 40px;

                                  border-radius: 40px;

                                  /* */ -moz-box-shadow:

                                  inset #ff0000 0 0 40px 10px;

                                  /* */ -webkit-box-shadow:

                                  inset #ff0000 0 0 40px 10px;

                                  box-shadow:

                                  inset #ff0000 0 0 40px 10px;

                                  height: 75px;

                                  width: 75px; }

                                    +2
                                    опера отлично вырезает бордер радиус с хидден, и фф
                                      0
                                      <div style=«border-radius:10px;border:1px solid red;width:50px;height:50px;overflow:hidden»>
                                      <div style=«background:blue;width:50px;height:50px».</div>
                                      </div>
                                        +1
                                        Я про обертку, все ок :)
                                          0
                                          чего ок?
                                            +1
                                            ок — я согласен с твоим самым верхним комментом :)
                                +2
                                У Opera и Firefox (а также у Safari, но не так выраженно) почему-то вышла тонкая светлая обводка вокруг элемента.

                                Я так думаю, программисты броузеров сейчас дружно икают и нервно ворочаются в постелях. Мало того, что им пришлось написать с добрую треть „Фотошопа“ для работы со всеми этими графическими объектами, так ещё и алгоритмы антиальясинга двух разных элементов должны совпадать до субпикселя!

                                Кстати, в спецификации ничего не говорится про само размытие, должно ли оно быть линейным или логарифмическим, должна ли учитываться гамма и цветовые профили затронутых объектов и монитора, с какой точностью производить вычисления координат и цветов и нужна ли диффузия последних… Вполне может оказаться, что всё авторы в своём праве.
                                  +1
                                  <user mode>Ну а наше право, как пользователей, требовать чтоб было красиво :)</user mode>

                                  Я бы все-тааки больше трети оценил — добавил css-transform'ов, что требует проработку поворотов, искажений (skew). При чем, если у нас над-под этими объектами еще webgl…

                                  0
                                  Сделайте ещё тест по свойству text-shadow, будет интересно. Хром (а может и всё семейство вебкита) в сравнении с оперой как топором тени рубит, особенно на средне-мелком тексте, уж лучше совсем без теней (ИЕ8), чем с таким убожеством, которое выдаёт Хром.
                                    +1
                                    text-shadow не такой гибкий: нельзя менять размер тени. А вообще тема уже достаточно хорошо изжевана, например здесь
                                      0
                                      не знаю что там разжёвано, я имел вввиду имено визуальное сравнение отображения одних и тех же эффектов в разных браузерах, ровно то, что сделано в этой статье.
                                    +2
                                    Баловался тенями. Всё круто. Убрал, и сайт сразу полегчал визуально.

                                    Но показалось оправданным:
                                    — наличие тени у всплывающих меню
                                    — скругление углов
                                    — повышение контраста белого текста на бледном фоне (тонка темная рамка вокруг текста — text-shadow:0 0 1px #505050;, например), но это не совсем по теме
                                      +1
                                      Интересно, что под Виндой радуга в хроме действительно отображается моментально, а вот под Маком тормозит почище чем в сафари.
                                        +13
                                        Такие извращенцы Хабру нужны!
                                          –1
                                          торт!
                                            +1
                                            У Оперы ещё есть баг неполноценного обрезания внешнего box-shadow атрибутом overflow:hidden;, из-за чего появляется полоса прокрутки из-за такого элемента, расположенного близко у края окна. Тень становится невидимой, но влияет на вычисление размера документа.
                                              0
                                              Значит, не только внешнего, но и внутреннего box-shadow. Ведь горизонтальный скролл появляется в Опере в сводной странице именно из-за большой и сильно сдвинутой вправо внутренней «тени» у градиента.
                                              +1
                                              Отличная статья. Про градиенты очень понравилось.
                                                0
                                                Отличная статья! Спасибо за сравнения.
                                                  0
                                                  Картинки за давностью пропали,… жаль.
                                                    0
                                                    Куда сейчас лучше всего заливать для Хабра? Пофикшу.
                                                      0
                                                      Загружайте изображения на habrastorage.org.
                                                      )
                                                        0
                                                        Восстановил все залитые мной картинки. Думаю, понятно, что результаты тестов безнадежно устарели ;)
                                                        Заодно причесал весь код (надеюсь, нигде не попортил случайно — проверять не стал).
                                                        Пока не знаю куда лучше залить HTML-страницу со всеми примерами в куче.

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

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