CSS
31 August 2010

Дрессируем 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 весьма-таки неплох.

+124
78.6k 185
Comments 56
Top of the day