Магия одного div. Мастеркласс от создателя a.singlediv.com

Почему Single Div?

В мае 2013 года я присутствовала на CSSConf и услышала, как Лиа Веру говорит об укрощении свойства border-radius. Это было поучительно и позволило мне понять о CSS то, чего я раньше не понимала. Это напомнило мне времена, когда я изучала изящные искусства, когда я постоянно стремилась повысить свой профессиональный уровень. Мой уровень владения CSS можно назвать средним, поэтому я бросила себе вызов, чтобы узнать все, что я смогу, исследуя и экспериментируя со свойствами

Но почему именно один DIV?

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

Я решила запустить проект a.singlediv.com, где намеревалась каждые несколько дней размещать нечто новенькое, созданное с помощью CSS. Я поставила перед собой ограничение использовать только один DIV.

Инструментарий

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

Псевдо-элементы

Один DIV в HTML позволяет работать с тремя элементами, благодаря использованию псевдо-элементов. Таким образом, с div, div:before, and div:after, мы можем получить что-то вроде этого:

97c10dc484f04bfbbb6933f1cb86c261

 

  div { background: red; }
  div:before { background: yellow; }
  div:after { background: blue; }

Для упрощения вы можете думать об этих элемента, как о трех слоях. Выглядит это примерно так:

1947d3c01f5a4cf0b447563974e7889b

Формы

С помощью CSS и одного элемента мы получили три основных формы. Мы можем использовать свойства width и height для создания квадратов / прямоугольников, а также border-radius, чтобы создать круги/эллипсы, и border для создания треугольников/трапеций.

73ecdcb1412a4819af04dc17de03dc55

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

Множественность формы

С несколькими box-shadows мы можем создать множество версий одной и той же формы, в том или ином размере, цвете, или использовать размытие. Использование осей х и у дает нам почти бесконечные вариации.

16680d96db6346c4b1a80b86eca51b5f

 

div {
    box-shadow: 170px 0 10px yellow,
                330px 0 0 -20px blue,
                330px 5px 5px -20px black;
}

Мы можем использовать box-shadows для box-shadows. Обратите внимание на порядок объявления. Здесь также уместен образ слоев.

Градиенты

Градиенты могут быть использованы, чтобы добавить затенение и глубину, подразумевая источник света. Это делает простые, плоские формы более реалистичными. Свойство background-images позволяет использовать несколько видов градиента для получения более сложного элемента.

0ba6a3d00b8d4e2dba4bae98805ec519

 

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.

Пример

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

Для начала возьмем зеленый карандаш:

Карандаш состоит из двух основных форм: прямоугольный корпус и треугольный наконечник.

292b6920f0e347fdbab4f1d1720efe1d

Я должна была реализовать следующие вещи, чтобы добиться реалистичности:

разноцветная обертка;
графика и слова на обертке;
иллюзия округлости;
глянцевость, которая подчеркивает форму и имитирует влияние источника освещения.

Итак, сначала я создала основной корпус карандаша:

9b56f3b1029b40a488ed74a7493d5127

Обратите внимание, я использую смешение 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, так что нижняя заливка немного проглядывает.

d91c05d9a9624129ac844aaf68866228

 

div { 
    background-image : linear-gradient (to right, 
                                  transparent  12px, 
                                  rgba (41, 237, 133, .6)  12px, 
                                  rgba (41, 237, 133, .6)  235px, 
                                  transparent  235px), 
}

Далее я использовала ту же технику градиента, чтобы создать полосы на карандаше.

9d37ba55bc58410ca452acb6fafd6633

 

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), 
}

А для нанесения эллипса прекрасно работает радиальный градиент!

e32a765d65654b91a5efa1853f7c925e

 

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

ea08f9b7a9334b6a890272e2d19c6dfa

 

div :before { 
    height :  10px, 
    border-right :  48px  solid  #237449, 
    border-bottom :  13px  solid  transparent, 
    border-top :  13px  solid  transparent, 
}

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

6c8df1cde8dd40c495deca6e77d726a8

 

div :after { 
    background-image : linear-gradient (to bottom, 
                                    white (0)  12px, 
                                    white (.2)  17px, 
                                    white (.2)  19px, 
                                    white (0)  24px), 
}

Как последний штрих, я добавила текст с помощью after, и разместил его на карандаше:

5c2ddacfc4ae4cacb3fb265f99d39dbf

 

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.

e64044e057ae4ecd8313ae46bf74ad05

Вот GIF, иллюстрирующая некоторые элементы, которые будут добавлены с помощью псевдо-элементов и box-shadows.

c3a777882ce34e6c9ca0ddc14377c1cc

 

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, 
}

Следующий этап:

473d113d4f05408b8ded9021e4c1b729

 

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 применяется к форме блока, а не к его границам. Все это затрудняет создание нескольких треугольников с помощью одного объекта. Вот пример, как это выглядит:

8b7e8ba9f5664cb4b40dc756d82a855f

 

 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-индекс, а также, чтобы понять, что именно будет видно, а что нет. Но эффективное использование этой техники позволит придать вашим рисункам высокий уровень детализации.

Вот рисунок в процессе создания, показывающий градиенты, которые охватывают всю ширину контейнера.

f1d434a91cc6494ba10bbadef705e735

Используя градиенты, направленные слева-направо и справа-налево, я могу скрыть часть градиента:

cfd079f7f239449696cb4d98dd7aa0fe

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

Теория в действии

Прекрасная вещь, которая стала побочным результатом этого проекта, — расширение для Сhrome, которое называется CSS Gradient Inspector. Оно позволяет включить и выключить отображение каждого из градиентов по аналогии с видимостью слоев в Photoshop.