Почему Single Div?
В мае 2013 года я присутствовала на CSSConf и услышала, как Лиа Веру говорит об укрощении свойства border-radius. Это было поучительно и позволило мне понять о CSS то, чего я раньше не понимала. Это напомнило мне времена, когда я изучала изящные искусства, когда я постоянно стремилась повысить свой профессиональный уровень. Мой уровень владения CSS можно назвать средним, поэтому я бросила себе вызов, чтобы узнать все, что я смогу, исследуя и экспериментируя со свойствами
Но почему именно один DIV?
Когда я училась рисовать, мой класс делал упражнение, в ходе которого мы получали цвета смешением трех основных: красного, желтого и синего. Целью этого занятия были изучение поведения материалов и понимание силы комбинации. Конечно, вы можете купить зеленую краску, но также можете получить ее, смешав синий и желтые цвета. Большее количество доступных вариантов решения проблемы заставляет нас пересматривать наши привычные решения.
Я решила запустить проект a.singlediv.com, где намеревалась каждые несколько дней размещать нечто новенькое, созданное с помощью CSS. Я поставила перед собой ограничение использовать только один DIV.
Инструментарий
Может показаться, что использование только одного элемента и свойств, поддерживаемых браузерами, — слишком ограниченный инструмент. Но это не так, если вы не ограничиваете себя их базовым назначением.
Псевдо-элементы
Один DIV в HTML позволяет работать с тремя элементами, благодаря использованию псевдо-элементов. Таким образом, с div, div:before, and div:after, мы можем получить что-то вроде этого:
div { background: red; }
div:before { background: yellow; }
div:after { background: blue; }
Для упрощения вы можете думать об этих элемента, как о трех слоях. Выглядит это примерно так:
Формы
С помощью CSS и одного элемента мы получили три основных формы. Мы можем использовать свойства width и height для создания квадратов / прямоугольников, а также border-radius, чтобы создать круги/эллипсы, и border для создания треугольников/трапеций.
Есть и другие формы, которые мы можем создать с помощью CSS, но большинство вещей может быть упрощено до некоторой комбинации основных форм. В таком виде сложными формами значительно проще управлять
Множественность формы
С несколькими box-shadows мы можем создать множество версий одной и той же формы, в том или ином размере, цвете, или использовать размытие. Использование осей х и у дает нам почти бесконечные вариации.
div {
box-shadow: 170px 0 10px yellow,
330px 0 0 -20px blue,
330px 5px 5px -20px black;
}
Мы можем использовать box-shadows для box-shadows. Обратите внимание на порядок объявления. Здесь также уместен образ слоев.
Градиенты
Градиенты могут быть использованы, чтобы добавить затенение и глубину, подразумевая источник света. Это делает простые, плоские формы более реалистичными. Свойство background-images позволяет использовать несколько видов градиента для получения более сложного элемента.
div {
background-image : linear-gradient (to right, gray, white, gray, black),
}
div :after {
background-image : radial-gradient (circle, yellow 50%, transparent 50%),
linear-gradient (to right, blue, red),
}
Визуализация
Самой трудной частью является визуализация того, как собрать все эти части в единое целое, в узнаваемый рисунок. Эта часть процесса имеет решающее значение. Чтобы помочь себе в этом, я часто смотрю на фотографию предмета, и мысленно разделяю его на составляющие, все формы и все цвета. Я разбиваю общую картину на более мелкие формы или цветовые блоки, которые я смогу создать с помощью CSS.
Пример
Давайте внимательнее посмотрим на два рисунка и выделим некоторые части, которые составляют большие объекты.
Для начала возьмем зеленый карандаш:
Карандаш состоит из двух основных форм: прямоугольный корпус и треугольный наконечник.
Я должна была реализовать следующие вещи, чтобы добиться реалистичности:
разноцветная обертка;
графика и слова на обертке;
иллюзия округлости;
глянцевость, которая подчеркивает форму и имитирует влияние источника освещения.
Итак, сначала я создала основной корпус карандаша:
Обратите внимание, я использую смешение black(a) и white(a) вместо RGBA
div {
background : #237449,
background-image : linear-gradient (to bottom,
transparent 62%,
black (.3) 100%),
box-shadow : 2px 2px 3px black (.3),
}
Затем я добавила линейный градиент на обоих концах, чтобы создать обертку. Он имеет значение альфа-0,6, так что нижняя заливка немного проглядывает.
div {
background-image : linear-gradient (to right,
transparent 12px,
rgba (41, 237, 133, .6) 12px,
rgba (41, 237, 133, .6) 235px,
transparent 235px),
}
Далее я использовала ту же технику градиента, чтобы создать полосы на карандаше.
div {
background-image : linear-gradient (to right,
transparent 25px,
black (.6) 25px,
black (.6) 30px,
transparent 30px,
transparent 35px,
black (.6) 35px,
black (.6) 40px,
transparent 40px,
transparent 210px,
black (.6) 210px,
black (.6) 215px,
transparent 215px,
transparent 220px,
black (.6) 220px,
black (.6) 225px,
transparent 225px),
}
А для нанесения эллипса прекрасно работает радиальный градиент!
div {
background-image: radial-gradient(ellipse at top,
black(.6) 50px,
transparent 54px);
}
Я разделила код, чтобы продемонстрировать каждый элемент, но имейте в виду: изображение будет на самом деле выглядеть следующим образом:
div {
// эллипс
background-image: radial-gradient(ellipse at top,
black(.6) 50px,
transparent 54px),
// полосы
linear-gradient(to right,
transparent 25px,
black(.6) 25px,
black(.6) 30px,
transparent 30px,
transparent 35px,
black(.6) 35px,
black(.6) 40px,
transparent 40px,
transparent 210px,
black(.6) 210px,
black(.6) 215px,
transparent 215px,
transparent 220px,
black(.6) 220px,
black(.6) 225px,
transparent 225px),
// обертка
linear-gradient(to right,
transparent 12px,
rgba(41,237,133,.6) 12px,
rgba(41,237,133,.6) 235px,
transparent 235px),
// оттенение
linear-gradient(to bottom,
transparent 62%,
black(.3) 100%)
}
Таким образом, после завершения div, я использовала псевдо-элемент before для создания трехстороннего наконечника. Используя свойства solid и transparent, я создала треугольник и разместила его рядом с div
div :before {
height : 10px,
border-right : 48px solid #237449,
border-bottom : 13px solid transparent,
border-top : 13px solid transparent,
}
Это выглядит немного плоско, но это будет исправлено посредством псевдо-элемента after. При этом я добавила линейный градиент, чтобы создать эффект блеска, который охватывает всю ширину карандаша.
div :after {
background-image : linear-gradient (to bottom,
white (0) 12px,
white (.2) 17px,
white (.2) 19px,
white (0) 24px),
}
Как последний штрих, я добавила текст с помощью after, и разместил его на карандаше:
div :after {
content : 'green',
font-family : Arial, sans-serif,
font-size : 12px,
font-weight : bold,
color : black (.3),
text-align : right,
padding-right : 47px,
padding-top : 17px,
}
Еще один пример (фотоаппарат):
Вот корпус камеры, созданный с помощью background-image и border-image.
Вот GIF, иллюстрирующая некоторые элементы, которые будут добавлены с помощью псевдо-элементов и box-shadows.
div :before {
background : #333,
box-shadow : 0 0 0 2px #eee,
-1px -1px 1px 3px #333,
-95px 6px 0 0 #ccc,
30px 3px 0 12px #ccc,
-18px 37px 0 46px #ccc,
-96px -6px 0 -6px #555,
-96px -9px 0 -6px #ddd,
-155px -10px 1px 3px #888,
-165px -10px 1px 3px #999,
-170px -10px 1px 3px #666,
-162px -8px 0 5px #555,
85px -4px 1px -3px #ccc,
79px -4px 1px -3px #888,
82px 1px 0 -4px #555,
}
Следующий этап:
div :after {
background : linear-gradient (45deg, #ccc 40%, #ddd 100%),
border-radius : 50%,
box-shadow : 0 3px 2px #999,
1px -2px 0 white,
-1px -3px 2px #555,
0 0 0 15px #c2c2c2,
0 -2px 0 15px white,
-2px -5px 1px 17px #666,
0 10px 10px 15px black (.3),
-90px -51px 1px -43px #aaa,
-90px -50px 1px -40px #888,
-90px -51px 0 -34px #ccc,
-90px -50px 0 -30px #aaa,
-90px -48px 1px -28px black (.2),
-124px -73px 1px -48px #eee,
-125px -72px 0 -46px #666,
-85px -73px 1px -48px #eee,
-86px -72px 0 -46px #666,
42px -82px 1px -48px #eee,
41px -81px 0 -46px #777,
67px -73px 1px -48px #eee,
66px -72px 0 -46px #666,
-46px -86px 1px -45px #444,
-44px -87px 0 -38px #333,
-44px -86px 0 -37px #ccc,
-44px -85px 0 -34px #999,
14px -89px 1px -48px #eee,
12px -84px 1px -48px #999,
23px -85px 0 -47px #444,
23px -87px 0 -46px #888,
}
Немного сложно, но, как вы видите, несколько box-shadows могут добавить много деталей к одному элементу.
Серьезные вызовы
Два самых больших препятствия, с которыми я столкнулась, — ограничения при создании треугольника и поведение градиентов.
Проблема с треугольниками
Методика создания треугольников ограничивает возможные действия. Добавление градиента с помощью border-image затрагивает все границы объекта, а не одну конкретную сторону. Box-shadows применяется к форме блока, а не к его границам. Все это затрудняет создание нескольких треугольников с помощью одного объекта. Вот пример, как это выглядит:
div {
border-left : 80px solid transparent,
border-right : 80px solid transparent,
border-bottom : 80px solid red,
}
div :before {
border-left : 80px solid transparent,
border-right : 80px solid transparent,
border-bottom : 80px solid red,
border-image : linear-gradient (to right, red, blue),
}
div :after {
border-left : 80px solid transparent,
border-right : 80px solid transparent,
border-bottom : 80px solid red,
box-shadow : 5px 5px 5px gray,
}
Расслоение градиента
Градиент стремится заполнить весь элемент. Это решается наложением нескольких градиентов друг на друга. Потребуется немного времени, чтобы обдумать прозрачность и Z-индекс, а также, чтобы понять, что именно будет видно, а что нет. Но эффективное использование этой техники позволит придать вашим рисункам высокий уровень детализации.
Вот рисунок в процессе создания, показывающий градиенты, которые охватывают всю ширину контейнера.
Используя градиенты, направленные слева-направо и справа-налево, я могу скрыть часть градиента:
В результате создается иллюзия того, что объект выполнен из множества элементов.
Теория в действии
Прекрасная вещь, которая стала побочным результатом этого проекта, — расширение для Сhrome, которое называется CSS Gradient Inspector. Оно позволяет включить и выключить отображение каждого из градиентов по аналогии с видимостью слоев в Photoshop.