htmlbook.ru - Для тех, кто делает сайты
Статьи Книги Шаг за шагом Рецепты Форум Графика для Web
Главная страница > Статьи > Использование слоев > Создание тени по типу «луковой шелухи»

Создание тени по типу «луковой шелухи»

Брайан Уильямс

Текстовая версия   Добавить комментарий

Перевод: Влад Мержевич и Евгений Богомольный.

Да, «луковая шелуха». Аниматоры используют этот эффект, чтобы показать то, что обычно невозможно увидеть: кадры движения во времени. И теперь веб-дизайнеры могут использовать подобный эффект, чтобы показать другую кажущуюся невозможность: создание реалистичной тени с использованием CSS.

Особенности

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

Чистим луковицу

«Луковая шелуха» используется при создании анимации для наложения кадров последовательности движения друг на друга, чтобы можно было заметить небольшие различия между отдельными кадрами. Аниматор просто просматривает набор слоев, чтобы увидеть одно целое движение через композицию его частей. Непрозрачные области на одном слое могут быть замечены на прозрачном слое выше него. Мы можем сделать то же самое и с тегом <DIV>. Используя CSS, допустимо наложить друг на друга несколько элементов <DIV> подобно луковице и таким образом получить желаемую композицию. В частности, создать тень (рис. 1).

Рис. 1. Изометрическая проекция слоев в виде луковой шелухи

Рис. 1. Изометрическая проекция слоев в виде «луковой шелухи»

Три слоя, каждый из которых содержит фрагмент изображения тени, накладываясь друг на друга, позволяют получить единую тень. Просто поместите ваш объект внутри трех контейнеров <DIV> и каждому из них дайте название класса, которое соответствует его роли. В примере 1, в частности, используются имена wrap1, wrap2 и wrap3 (класс wrap1 соответствует внешнему слою, а wrap3 — внутреннему).

Пример 1. Структура слоев для создания тени

<div class="wrap1">
 <div class="wrap2">
  <div class="wrap3">
   <img src="object.gif" alt="Рисунок с тенью">
  </div>
 </div>
</div>

Код CSS сложнее кода HTML, но не намного. В основном, для создания тени требуется пройти три шага, которые выполняются через правила стиля.

Шаг 1. Отображение тени

Основная идея состоит в том, чтобы сопоставить каждый из трех компонентов изображения тени своему контейнеру <DIV> через соответствующий класс. Цель применения трех изображений состоит в том, чтобы использовать два маленьких рисунка для маскирования среза края тени и создания плавного закругления краев. Для этого один рисунок помещается в правый верхний угол тени от объекта, а второй — в левый нижний.

Чтобы один рисунок находился поверх другого и маскировал его, необходимо изменить его положение с помощью стилевого параметра z-index. На самом деле волноваться по этому поводу не стоит, т.к. вложенная структура тегов <DIV> работает на нас и позволяет автоматически получить нужный порядок. Мы просто назначаем класс с тенью самому нижнему тегу <DIV> в наборе слоев. Поскольку нижние теги <DIV> будут располагаться наверху, то им присвоим классы, которые отображают уголки тени (пример 2).

Пример 2. Стили для отображения рисунков с тенью

.wrap1 {
 background-image: url(shadow.gif);
}
.wrap2 {
 background-image: url(corner_bl.gif);
}
.wrap3 {
 background-image: url(corner_tr.gif);
}

Когда мы назначаем требуемый рисунок к нужному классу, следует установить для него позиционирование с помощью свойства background-position. Если мы оставим его значение по умолчанию, то все, что мы увидим — это повторяющийся рисунок corner_tr.gif, поскольку слой с ним находится наверху набора слоев. Помните, техника «луковой шелухи» требует прозрачности верхних слоев, чтобы мы могли бы увидеть то, что находится ниже них. Для этого следует отменить повторение фонового рисунка с помощью значения no-repeat и позиционировать рисунок в нужном месте композиции.

Здравый смысл говорит нам, что изображение с именем corner_tr.gif должно находиться в правом верхнем углу, в то время как corner_bl.gif — в левом нижнем. Но что касается основного рисунка с тенью (shadow.gif), надо ли позиционировать и его? Факт — надо. Если мы хотим, чтобы тень отбрасывалась правее и ниже любого объекта, то следует определить ее положение в классе wrap1. В противном случае рисунок заполнит элемент <DIV> относительно его верхнего левого угла, т.е. совсем не там, где он требуется.

Основной слой — DIV.wrap1

Внешний <DIV> содержит самый большой из трех компонентов тени (файл shadow.gif), который позиционирован по правому и нижнему краю (пример 3).

Пример 3. Стиль для основного слоя

.wrap1 {
 background: url(shadow.gif) right bottom no-repeat;
}

На рис. 2 показано содержимое слоя и требуемый графический файл.

Рис. 2. Содержимое слоя wrap1

Рис. 2. Содержимое слоя wrap1

Средний слой — DIV.wrap2

Второй <DIV>, вложенный внутри первого, маскирует срез левого нижнего края тени и устанавливает плавное закругление (пример 4).

Пример 4. Стиль для среднего слоя

.wrap2 {
 background: url(corner_bl.gif) left bottom no-repeat;
}

На рис. 3 показано содержимое слоя и требуемый графический файл.

Рис. 3. Содержимое слоя wrap2

Рис. 3. Содержимое слоя wrap2

Внутренний слой — DIV.wrap3

Третий <DIV>, вложенный внутри второго, занимается срезом верхнего правого края тени.

Пример 5. Стиль для внутреннего слоя

.wrap3 {
 background: url(corner_tr.gif) right top no-repeat;
}

На рис. 4 показано содержимое слоя и требуемый графический файл.

Рис. 4. Содержимое слоя wrap3

Рис. 4. Содержимое слоя wrap3

Шаг 2. Отбрасывание тени

Следующий шаг для CSS — смещение тени, которое создает эффект ее отбрасывания. Проще не бывает. Все что требуется — это добавить параметр padding, который устанавливает поля слева и снизу для самого нижнего слоя. Когда padding применяется к тегу <DIV>, то он изменяет размеры объекта, и остальные два слоя изменяются вместе с ним. Как результат, все три компонента тени, расположенные по правой и нижней стороне этих слоев, смещаются одновременно. Теперь их можно увидеть через пустой промежуток, созданный с помощью атрибута padding (пример 6).

Пример 6. Использование полей для отбрасывания тени

.wrap3 {
 padding: 0px 4px 4px 0px;
 background: url(corner_tr.gif) right top no-repeat;
}

Результат данного примера продемонстрирован на рис. 5.

Рис. 5. Использование смещения содержимого

Рис. 5. Использование смещения содержимого

Модификация смещения

Изменение величины смещения тени делается почти также просто, как и замена значений параметра padding для слоя wrap3. Мы говорим «почти», поскольку настройка значения padding просто перемещает тень, в то время как уголки продолжают прижиматься к краям контейнеров. Чтобы точно смоделировать смещение тени, для обоих уголков следует использовать атрибут background-position.

Некоторые разработчики сказали бы, что достаточно настроить значение padding и остановиться на этом. Нет смысла усложнять себе жизнь вниманием к мелким деталям, когда большинство пользователей их просто не заметит. Другие бы привели аргумент, что срезанные уголки снижают эффект производимый тенью. Если метод технически и эстетически позволяет добиться желаемой точности, то разработчику грех не воспользоваться заложенным потенциалом. Тем не менее, каждый выбирает свой собственный путь.

Судите сами. Рис. 6 используется ниже для демонстрации двух видов тени.

Рис. 6. Исходное изображение для создания тени

Рис. 6. Исходное изображение для создания тени

Все образцы в обоих наборах используют одинаковое значение свойства background-image. Иными словами, одни и те же графические изображения применяются к каждому образцу. Различается только степень смещения тени.

В наборе 1 сдвиг тени регулируется только значением параметра padding для слоя wrap3, при этом перемещается только сама тень без уголков. В наборе 2 значения padding и background-position изменяются таким образом, чтобы одновременно смещалась тень и ее уголки.

Набор 1. Результат использования параметра padding
8 пикселов 12 пикселов 18 пикселов

 

Набор 2. Результат одновременного использования параметров padding и background-position
8 пикселов 12 пикселов 18 пикселов

Если вы замечаете различия между приведенными наборами и предпочитаете второй вариант, то к стилю уголков следует прибавить параметр background-position и настроить его значение таким образом, чтобы компенсировать влияние атрибута padding. Далее к изображению уголков с внешней стороны следует добавить пустое белое пространство. Это позволяет рисунку перемещаться на достаточно большое расстояние от границы слоя, без того, чтобы не терять способность маскировать край тени. Каждый вид тени немного отличается от другого, и как только вы начнете экспериментировать со смещением, то сразу станет понятно, на какую величину следует увеличить белое пространство у картинки с уголками.

Шаг 3. Размер по объекту

Потребуется небольшая ловкость рук, чтобы убедить браузер устанавливать тень по ширине объекта. Без этого потребовалось бы вычислять ширину, чтобы корректно добавить тень.

В большинстве браузеров <DIV> принимает размер объекта, когда для него добавляется параметр float. Данный способ подойдет, но только не в том случае, если вы используете Internet Explorer 5 под Macintosh. Простой факт, что есть люди, которые пользуются этим браузером, заставил поискать альтернативное решение. К сожалению, ни одно не было найдено, по крайней мере, такое, которое было бы универсальным.

Некоторое экспериментирование показало, что использование значения inline-table атрибута display может спасти ситуацию. Так, применение комментариев совместно со слэшем (/* */display: block/**/) позволяет скрыть этот код от браузера Internet Explorer 5 под Macintosh, «подсовывая» ему строку display: inline-table, в то время как остальные браузеры «видят» параметр float: left. Таким образом, получается, что «размер по объекту» работает во всех браузерах (рис. 6).

Рис. 6. Конечный результат

Рис. 6. Конечный результат

В итоге CSS с учетом всех трех шагов показан в примере 7.

Пример 7. Окончательный стиль для создания тени

.wrap1, .wrap2, .wrap3 {
 display: inline-table;
 /* */display: block/**/
}

.wrap1 {
 float: left;
 background: url(shadow.gif) right bottom no-repeat;
}

.wrap2 {
 background: url(corner_bl.gif) left bottom no-repeat;
}

.wrap3 {
 padding: 0px 4px 4px 0px;
 background: url(corner_tr.gif) right top no-repeat;
}

Еще один стиль для хорошего тона

Как было показано в примерах выше, изображения достаточно часто используются с приведенной техникой. В подобном случае для рисунка, к которому добавляется тень, следует установить свойство display со значением block. Во многих случаях это поможет избежать наложения элементов друг на друга. Просто добавьте следующий стиль (пример 8).

Пример 8. Стиль для изображений

.wrap3 IMG {
 display: block;
}

Комментарии переводчика

В данной статье Брайан Уильямс изложил свою универсальную методику создания тени на основе слоев. Однако многие читатели хотели бы видеть не принцип добавления тени к объекту, а готовый код, который с легкостью можно скопировать и модифицировать «под себя». Для таких людей и написан приведенный далее текст.

Итак, вам понадобится три рисунка: собственно сама тень (рис. 7), правый верхний уголок (рис. 8) и левый нижний уголок (рис. 9).

Рис. 7

Рис. 7. Изображение тени (файл shadow.gif)

Рис. 8

Рис. 8. Изображение правого верхнего уголка (файл corner_tr.gif)

Рис. 9

Рис. 9. Изображение левого нижнего уголка (файл corner_bl.gif)

Рамка вокруг рисунков приведена для наглядности и естественно к картинкам не добавляется. Ширина изображения тени зависит от цели ее использования, например, если планируется устанавливать тень для рисунков шириной не более 600 пикселов, то имеет смысл сделать такой же размер и у тени.

Код для формирования тени с помощью приведенных картинок и методики «луковой шелухи» показан в примере 9.

Пример 9. Создание тени

Валидный HTML
Валидный CSS
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Создание тени</title>
<style type="text/css">
.wrap1 {
 display: block;
 background:
  url(images/shadow.gif) /* Рисунок с тенью */
  no-repeat /* Отменяем повторение фона */
  right bottom; /* Размещаем тень в правом нижнем углу */
 float: left; /* Создание обтекания для правильного положения тени */
}
.wrap2 {
 display: block;
 background: url(images/corner_bl.gif)
  no-repeat /* Отменяем повторение рисунка */
  left bottom; /* Располагаем в левом нижнем углу */
 background-position: /* Положение уголка тени */
  -15px /* Смещаем уголок, чем меньше значение, тем левее располагается уголок */
  100%;
}
.wrap3 {
 display: block;
 padding:
  0
  12px /* Ширина тени справа */
  12px /* Высота тени снизу */
  0;
 background:
  url(images/corner_tr.gif) /* Правый верхний уголок тени */
  no-repeat /* Отменяем повторение рисунка */
  right top; /* Располагаем в правом верхнем углу */
 background-position: /* Положение уголка тени */
  100%
  -15px; /* Смещаем уголок, чем меньше значение, тем выше уголок */
}
.wrap3 IMG {
 display: block;
}
</style>
</head>
<body>
<div class="wrap1">
<div class="wrap2">
<div class="wrap3"><img src="images/pic.jpg" width="72" height="72" alt="Картинка"></div>
</div>
</div>
</body>
</html>

Параметры, которые управляют положением тени относительно объекта, подбираются экспериментально, исходя из собственных предпочтений и дизайна сайта.

Статья опубликована: 25.04.2006 Последнее обновление: 02.05.2008

Прежде, чем писать комментарий к статье, примите во внимание следующие моменты.

  1. Не задавайте вопросы в комментариях, для этой цели предназначен форум, где вы получите нужную помощь.
  2. Удаляются любые комментарии, которые:
    • включают множество ошибок;
    • написаны безграмотно;
    • не имеют отношения к данной статье;
    • не содержат никакой полезной информации для посетителей.
  3. Для выделения отдельных слов используйте следующие команды: [b]жирный[/b], [i]курсив[/i], [color=цвет]цветной текст[/color], [tag]тег[/tag], [var]параметр[/var], [code]пример[/code].
  4. Потренироваться в написании комментариев вы можете в песочнице.

Комментарии к статье

Владислав

05.05.2006

Здравствуйте Влад.
Не могли ли бы Вы выложить этот пример в качестве сверстанного html документа чтобы все было более наглядно?
Заранее благодарю.

Влад Мержевич

05.05.2006

Добавлю свои комментарии в статью в ближайшее время. Если же не терпится получить код, смотрите исходник статьи.

Влад Мержевич

11.05.2006

Полный листинг по просьбам читателей добавил, можете использовать.

Денис Левченко

20.07.2006

Спасибо большое очень грамотный сайт smile))
Везде искал, а здесь вс? и про вс?.
Очень помогает

Александр

18.08.2006

А как на счет тени с PNG рисунками? MS IExplore их корректно не отображает sad

Влад Мержевич

21.08.2006

Это проблема IE, в седьмой версии Microsoft обещала ввести полную поддержку формата PNG.

Virtual Spirit

30.08.2006

Очень полезный эффект для кталога, где картинки отобразаются подобным образом, при большом количестве картинок - экономия места.

elanc

26.09.2006

Для решения проблем с IE6 при работе с PNG, имеющими alpha-канал, советую обратиться к js-хаку "IE7" от Dean Edwards -- http://dean.edwards.name/
Весь пакет подключать не советую использовать -- появляются проблемы с FF, да и страницы станут слишком "тяжелыми"..

Witty

03.11.2006

для эксплорера в png можно ипользовать фильтры..тогда в мозилле имаги пропадают а в иксплорере появляються с нормальным отображением !
#Image1 {
background-image: none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=`crop`, src=`img/image1.png`);
}

3bepek

12.02.2007

а если так - то всем хорошо.

в стили добавляем строку:
* {filter:expression(fixPNG(this));}

и такой скриптик еще юзаем:

function fixPNG(element)
{
if (/MSIE (5.5|6).+Win/.test(navigator.userAgent))
{
var src;

if (element.tagName==`IMG`)
{
if (/.png$/.test(element.src))
{
src = element.src;
element.src = "decoration/blank.gif";
}
}
else
{
src = element.currentStyle.backgroundImage.match(/url("(.+.png)")/i)
if (src)
{
src = src[1];
element.runtimeStyle.backgroundImage="none";
}
}

if (src) element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src=`" + src + "`,sizingMethod=`scale`)";
}
}

3bepek

12.02.2007

где "decoration/blank.gif"
это путь к файлу blank.gif - однопиксельный прозрачный гиф

3bepek

12.02.2007

но если пнг - фон, то эта тема не катит))

Wink

22.02.2007

Влад, хороший эффект получается и пользоваться удобно, но есть одна неприятность - изображение тени появляется раньше самого рисунка, т.е. сначала бесформенное голубое пятно с рамкой незагрузившегося еще рисунка, а потом через некоторое время сам рисунок. Нельзя ли как-нибудь избавиться от такого эффекта или хотя бы минимизировать его?

Влад Мержевич

02.03.2007

Wink, только если прелоад сделать рисунков с помощью JavaScript.

eugenijus

23.06.2007

Cпасибо Влад,профессионально,кратко,вразумительно!Браво!

X

03.07.2007

JavaScript выполняеться после загрузки страницы, поэтому и получаеться такой эффект, возможно лучше использовать языки: php, perl, JavaScript хорош в решении других задач, хотя с его помощью проблему решить можно.

Андрей

13.07.2007

2 3bepek
Что не работает твоя метода. Не пояснишь что к чему?

Anton

06.05.2008

в IE7 выставляешь
.wrap3 {
padding: 0px 4px 0px 0px;
нормально, но в 9-й опере тень съезжает вверх на 4 пиксела, короче внизу тени не видно

ставишь


.wrap3 {
display: block;
padding: 0px 4px 4px 0px;
background: url(corner_tr.gif) right top no-repeat;
}
в 9-й опере нормально, в IE7 тень съезжает вниз на 4 пиксела, короче внизу уже видно 8 пикселов

IE6 не поддерживает альфа PNG24, короче получается не тень, а белая фигня, с GIF как у вас такая же фигня, т.к. фон страницы может быть разным, и белые тени не везде смотрятся

Вывод: какие же придурки браузеры придумывали вобще?
и вобще HTML это ошибка, на мо?м мониторе 1680x1050 22" шрифт на некоторых сайтах уже не видно, т.к. он мелкий, но можно игнорировать шрифт в настройках браузера, тогда съезжает дизайн
про шапки сайтов в 100пикселов, их вобще не видно
при ещ? большем мониторе с большим количеством точек, но меньшем размере точек вобще нич? не видно будет
дак нафига это надо? не проще типа Word или PDF сайты делать? там хоть размер А4 фиксированный можно было всем договориться сделать и вс?, а по длине неважно хоть сколько

naruto

15.05.2008

Здравствуйте, Влад! Восхищен информативностью вашего сайта! В тему к вашей статье хочу добавить, можно сделать структуру из 5 вложенных дивов для создания тени которая не будет зависеть от ширины и высоты самого блока:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Создание тени</title>
<style type="text/css">
.wrap1 {
display: block;
background:
url(r.gif)
repeat-y
right top;
float:left
}
.wrap2 {
display: block;
background: url(b.gif) repeat-x
left bottom;
}
.wrap3 {
display: block;
background:
url(vr.gif) no-repeat
right top;
}
.wrap4 {
display: block;
background:
url(nl.gif) no-repeat
left bottom;
}
.wrap5 {
display: block;
background:
url(ugol.gif) no-repeat
right bottom;
padding:0px;
padding-right:12px;
padding-bottom:12px;
}
.wrap3 IMG {
display: block;
}
</style>
</head>
<body>
<div class="wrap1">
<div class="wrap2">
<div class="wrap3">
<div class="wrap4">
<div class="wrap5"><img src="1.jpg" width="200" height="200" alt="Картинка"></div>
</div>
</div>
</div>
</div>
</body>
</html>

, где:
r.gif - картинка размером 12х30 px - правая сторона тени
b.gif - картинка размером 30х12 px - нижняя сторона тени
nl.gif - картинка размером 12х12 px - нижний левый угол
vr.gif - картинка размером 12х12 px - верхний правый угол
ugol.gif - картинка размером 12х12 px - нижний правый угол

Добавить комментарий

Имя
Комментарий

Сохранить имя (используется cookie)

Поиск по сайту

Использование слоев
Разделы
Теги по теме

DIV
Элемент DIV является блочным элементом и предназначен для выделения фрагмента документа с целью изменения вида содержимого.

IMG
Тег IMG предназначен для отображения на веб-странице изображений в графическом формате GIF, JPEG или PNG.

CSS по теме

background
Параметр позволяет установить одновременно до пяти атрибутов стиля фона. Значения могут идти в любом порядке, браузер сам определит, какое из них соответствует нужному атрибуту.

background-image
Устанавливает фоновое изображение для элемента. Если одновременно для элемента задан цвет фона, он будет показан, пока фоновая картинка не загрузится полностью.

background-position
Задает начальное положение фонового изображения, установленного с помощью параметра background-image.

display
Многоцелевой атрибут, который определяет, как элемент должен быть показан в документе.

float
Определяет, по какой стороне будет выравниваться элемент, при этом остальные элементы будут обтекать его с других сторон.

padding
Устанавливает значение полей вокруг содержимого элемента. Полем называется расстояние от внутреннего края рамки элемента до воображаемого прямоугольника, ограничивающего его содержимое.

Copyright 2002–2008 Влад Мержевич, по всем вопросам пишите по адресу: vlad@htmlbook.ru

О сайте | Планы на будущее | Использование сайта | Борьба с ошибками | Технологии | Поддержать проект