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

в 16:12, , рубрики: css, onediv, Блог компании Paysto, метки: ,

Почему Single Div?

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

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

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

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

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

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

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

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

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

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

image

Формы

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

image

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

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

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

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

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

Градиенты

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

image
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.

Пример

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

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

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

image

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

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

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

image

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

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

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

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

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

image

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

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

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

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

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

image
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.

image

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

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

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

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

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

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

image

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

image

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

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

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

Автор: Irina_Ua

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js