company_banner

Недокументированные приемы CSS

  • Tutorial
Всем привет! Зовут меня Дмитрий Григоров. Работаю фронтедером в Райффайзенбанке в команде RBO PRO. Я расскажу и покажу вам, как можно творчески применять данные возможности CSS. В статье мы рассмотрим следующие темы:

  • Фоны и рамки;
  • Фигуры;
  • Визуальные эффекты.




Фоны и рамки


В первой теме «Фоны и рамки» я расскажу, что такое currentColor в CSS3, как cделать прозрачные рамки, несколько рамок, что такое гибкое позиционирование фона. Во второй теме «Фигуры» приведу методы создания различных видов прямоугольников с помощью css. В визуальных эффектах рассмотрю примеры наложения различных цветовых тонов. А в теме «Взаимодействие с пользователем» покажу, как сделать интерактивное сравнение изображений.

Как вы думаете, какого цвета будет border у блока с текстом «Hello world»?



Такого же синего? Да, правильно. А почему?



Цвет будет такой же, #38A потому что в CSS есть такая прекрасная переменная, как currentCollor, которая берет свое значение цвета из свойства color. И если мы не передадим цвет в border, outline, text-shadow, box-shadow, то по умолчанию получим такой же цвет, что и в свойстве color.

На рисунке ниже можно увидеть, что currentColor можно передавать, как явным образом, так и не передавать вовсе.



Переменная currentColor предоставляет нам очень удобный код и соответствует принципам DRY (don’t repeat yourself — не повторяйся). И как показано на следующем рисунке, изменяя только свойство color, для блока с кодом, который был представлен выше, мы получаем разное отображение элемента.



Полупрозрачные рамки


Если бы меня кто-нибудь спросил раньше, как сделать полупрозрачные рамки, то я бы ответил: «Легко! Я бы сделал два блока дива: родительский и дочерний. И уже в родительском задал бы некоторый padding: 10px и background-color: rgba(255, 255, 255, 0.5) (полупрозрачный), который был бы цветом моей прозрачной границы». Но это можно сделать гораздо проще.





Что если мы просто передадим полупрозрачный border для нашей рамки? Мы ничего хорошего не получим. Почему? В CSS есть такое свойство, как background-clip, и многие забывают о его существовании. Background-clip отвечает за распространения фона и имеет три значения: border-box (по умолчанию), content-box и padding-box.

По умолчанию оно у нас border-box, что значит, что наш фон будет заходить под нашу рамку, и мы не увидим ту самую прозрачность, которую передали в border, так как у нас наш фон будет под нашей границей. Также в background-clip можно передавать content-box, что будет значить, что наш фон распространяется под нашим контентом. Но тут передаем padding-box и получаем вот такую прозрачную рамку.



Несколько рамок


Несколько рамок мы можем создать двумя способами, один используя border и outline. Border и Outline хороши, но с помощью их мы можем сделать только две рамки.



А что если нам потребуется куда больше рамок, к примеру 3, 4 или более, то тут нам на помощь приходят тени.



Все из нас сталкивались со свойством box-shadow. Многие знают, что если передать нулевое вертикальное смещение (v-offset), нулевое горизонтальное смещение (h-offset), нулевое размытие (blur) и четвертый параметр, называемый радиусом распространения (spread radius), который делает тень больше, то получится что-то похожее на рамку. И так можно создать сколько угодно рамок, разделяя их запятой.

Гибкое позиционирование фона


Следующая тема – это гибкое позиционирование фона. Многие из нас сталкивались с такой проблемой, как расположить картинку на нашем фоне. Расположить ее можно с помощью background-position. Хочу отметить, что такие ключевые слова, как right, top, bottom, left в CSS были обновлены. Теперь, когда мы пишем right 10 px и bottom 20 px для нашей картинки, то это будет значить, что сделай нам отступ справа 10 px, а снизу 20 px.



Точно также, если написать background-position: right 10 px top 20 px, то получим отступ справа 10 px, сверху 20 px.



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



Фон в полоску




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

Но простой фон в полоску можно сделать с помощью одного лишь CSS.

Все мы знаем, как выглядит стандартный градиент.



А что если мы этому градиенту зададим границы распространения?



То по краям мы увидим сплошной цвет.

А что если мы сведем градиент к одной точке?



Мы увидим просто две полоски. Вот эти две полосы будут основой нашего фона в полоску. Далее задаем background-size: 30px. Одна полоса будет 15 px и вторая тоже 15 px, так как градиент разделен 50/50. И получаем вот такой вот фон в полоску.



Для того чтобы сделать одну полосу больше, другую меньше, мы для желтого цвета задаем 30%, а для синего — 0. Что значит вот этот ноль? 30% у нас, понятное дело, будет занимать желтый цвет. А вот что значит вот этот 0, кто-нибудь может сказать? По сути, это просто оставшееся расстояние нашего background-size. То есть 30% из 30px – это примерно 9px у нас заполнится желтым, а вся остальная часть синим.



Для того чтобы нарисовать несколько цветов в нашем фоне, мы сталкиваемся с такой ситуацией, как промежуточное повторение цветов. То есть я говорю нашему желтому цвету: заполни мне 33% нашего фона желтым цветом, а ставшуюся часть заполни синим. Потом синему цвету говорю: нет, до 66% заполни, и все остальное заполни желто-зеленым, и получаем 3 цвета в нашем фоне.



Для того чтобы сделать вертикальные полосы — все то же самое, только у нас меняется background-size и в linear-gradient появляется ключевое слов to right. Также вместо ключевого слова мы можем вставить 90° и все отобразится, как надо.



Если мы совместим горизонтальные и вертикальные полосы вместе, то получим вот такой вот фон в решетку.

У нас есть квадратный background-size, мы передаем через запятую в background-image наши градиенты и получаем фон в решетку.



С фоном в диагональную полосу немного посложнее. Здесь мы уже не пользуемся обычным linear-gradient-ом, мы здесь пользуемся repeating-linear-gradient. Обратите внимание, что наш фон распространяется до 30 px, и background-size у нас квадратный 42px на 42px. Почему же все-таки 42?



А что, если мы передадим что-нибудь другое? К примеру 30px вместо 42px.





Почему же все-таки 42px. На помощь приходит обычная школьная математика.



Мы знаем, что наш фон – квадрат, а квадрат состоит из двух равнобедренных треугольников. Дальше мы делаем некоторые математические преобразования, но при этом помним, что наш фон распространяется до 30px.



Подставляем в нашу формулу 30 и получаем примерно 42. Округляем в меньшую степень. Получаем вот такой фон, диагональные полосы.




lea.verou.me/css3patterns

У автора книги «CSS секреты» Леа Веру, сотрудника всемирного веб-консорциума w3с, есть целая подборка фонов, которые она реализует с помощью градиентов.

Примеры, которые реализует Леа Веру.
Примеры, реализованные Беннеттом Фили.

Фигуры


И начну я эту тему с параллелограммов.



Все из нас знают, как выглядят параллелограммы. Параллелограмм – это, прежде всего, нестандартный прямоугольник, у которого углы должны быть не всегда прямые. Для того чтобы сделать скошенные углы, можно обойтись псевдоклассом before. Задаем относительное позиционирование (position: relative) классу button, а абсолютно позиционируем псевдокласс before. Задаем псевдоклассу background, делаем трансформацию с помощью skewX и получаем вот такие скошенные углы.



Для того чтобы сделать трапецию — все то же самое, аналогично. Только здесь мы передаем перспективу и rotateX. И получаем вот такую трапецию.



Изображение в форме ромба можно сделать различными способами. Один из них также с помощью трансформации. То есть у нас есть родительский div, и в него вложено изображение.



Поворачиваем родительский div на 45 градусов, и уже получаем ромб, но изображение у нас наклонилось тоже. Мы хотим его вернуть к нормальному виду и разворачиваем наше изображение обратно на -45 градусов. В итоге получается шестиугольник. Почему? А потому что у нас здесь два прямоугольника, и они срезают углы. Для того чтобы у нас получился именно ромб, мы просто задаем scale(1.42), увеличиваем наше изображение и получаем вот такой ромб.



Изображение в форме ромба можно сделать также с помощью clip-path. Туда мы можем передавать различные имена такие, как circle, polygon и другие. Здесь я пользуюсь полигоном. Я передаю в polygon середину каждой стороны квадрата, а при hover-e возвращаю точки к углам квадрата и получаю вот такую вот анимацию. Это очень хорошее свойство.



<source lang="css"><img src="tiger.jpg" alt=" " />
<img src="tiger2.jpg" alt=" "/>

img {
max-width: 250px;
margin: 20px;
clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
transition: all 1s;
}

img:hover {
clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}


Оно поддерживает анимацию, но к сожалению, очень плохо поддерживается браузерами. Его поддерживают только Chrome и Firefox.



Как сделать срезанные углы? Вспомним тему про фон в полоску. Здесь точно также с градиентами. Мы, по сути, разделяем наш фон на 4 части. У нас есть 4 градиента, которые мы раскидываем с помощью гибкого позиционирования по разным углам и закрашиваем их от прозрачного цвета до синего. И получаем срезанные углы.



Для того чтобы сделать срезанные углы во внутрь, здесь используется radial-gradient. Единственное, что у нас появляется, это такие ключевые слова, как circle at top left, чтобы расположить кружочки в различных углах. Опять же 4 части расставляем, с помощью ключевых слов, по местам и получаем такие углы.





Как сделать простые секторные диаграммы с помощью одно лишь CSS. Обычно, чтобы создать секторные диаграммы, мы пользуемся каким-либо фреймворком, например, d3.js. Но простую секторную диаграмму можно сделать на CSS.

У нас есть блок, мы из него делаем круг.



Половину круга закрашиваем коричневым цветом.



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



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





Опишу такой интересный подход, если передавать в наш блок отрицательный animation-delay и при этом animation-play-state оставить в состоянии paused, то можно заметить, что изменяется состояние нашего элемента. И если у нас анимация проигрывается до 4s (4 секунд), и мы напишем в стилях -2s, то получим на половину проигравшее состояние, и наш круг будет на половину закрашен.



Визуальные эффекты





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



И перейдем к гораздо более адаптивному способу: это background-blend-mode.
Более адаптивный он, потому что он может не просто накладывать желаемые цвета, но и смешивать, и это свойство прекрасно анимируется. Плюс, с помощью его мы можем сделать различные цветовые эффекты.





.tinted-image {
...
backgroung-color: hsl(335, 100%, 50%);
background-blend-mode: luminosity;
transition: .5s background-color;
}

.tinted-image {
...
backgroung-color:yellow;
background-blend-mode: difference;
transition: .5s background-color;
}

.tinted-image:hover {
background-color: transparent;
}


Но, к сожалению, у это свойства не всё хорошо с поддержкой. И пользоваться им или нет, решать вам.





Следующий пример — плавная анимация состояния. Почему он так называется, давайте посмотрим.



У нас есть панорама, и мы хотим добавить немного анимации.



Помещаем изображение на фоне и после анимируем background-position, и получаем анимацию.

.panoramic {
width: 300px, height: 300px;
background: url('b.jpg');
background-size: auto 100%;
border-radius: 50%;
animation: panoramic 10s linear infinite alternate;
animation-play-state: paused;
}
.panoramic:hover, .panoramic:focus {
animation-play-state:running;
}
@keyframes panoramic {
to {background-position: 100% 0;}
}




Обратите внимание именно на верстку, на HTML. У нас есть контейнер, image-slider, и у него есть одно изображение, которое вложено в div, а другое не вложено. Для родительского контейнера мы задаем position: relative, а для вложенного в div изображения, с ним и будем работать, мы задаем position: absolute и ширину 50%. Самое главное — мы ему делаем resize: horizontal.



С помощью этого resize у нас будет интерактивное сравнение. Так как у меня очень хорошее разрешение, мы не видим такого бага, который возникает из-за resize: horizontal. У нас появляется ползунок, который подобен resize-ползунку HTML-элемента textarea. Для того чтобы его убрать, мы просто закрашиваем его псевдоклассом и завязываем на нем cursor: ew-resize.



Хочу отметить, что в основу статьи вошла книга Css Secrets. Better Solutions to Everyday Web Design Problems. Хоть она уже и давно вышла, я настоятельно рекомендую прочитать эту книгу. Из этой книги вы узнаете гораздо больше, чем я здесь представил и по-настоящему попробую многие секреты CSS вживую.

Ссылка на репозиторий с примерами и презентацией
Райффайзенбанк 208,49
Развеиваем мифы об IT в банках
Поделиться публикацией
Комментарии 27
  • 0

    CSS мощная штука. И статья интересная.

    • +2
      Если бы еще все это еще не превращалось в ад когда нужно добицо кроссброузерности, цены бы ему не было.

      Ну и действительно важные вещи не развиваются десятилетиями. 2018 год а для печати из броузеров до сих пор применяются костыли. Просто пример: попробуйте в хроме поставить разрыв страницы между строками таблицы 8)
    • 0
      Спасибо! Полезная подборка!
      • +9

        Шерить код картинками да ещё и разными размерами — так себе решение. Особенно для туториала, где возможность скопировать код — маст хев.
        А так — довольно полезно для тех, кто не следит за Lea Verou.
        Хотя не знал про относительное позиционирование (right 10px) и про применения background-clip для решения прозрачных рамок, хотя решение конечно лежит на поверхности.

        • +2

          У background-clip вообще немало полезных применений. Причем вполне документированных!:)

          • 0
            кстати да — для себя именно это и отметил. всё остальное известно именно от Lea Verou
            • 0
              Ручное переписывание кода намного увеличивает скорость его усвоения.
              Этим пользуются многие программерские обучалки.
            • –6
              Одна проблема большинства этих решений — они не работают в IE11. А большинство заказчиков его хочет поддерживать.
              • 0
                Те, кто пользуется IE 11 должны страдать))
                • 0
                  А они-то как раз и не страдают.
              • 0

                Где найти такое же, но с текстовыми примерами кодов? Ещё лучше — с кодами в JSFiddle / CodePen / CSS Deck / JS Bin / Dabblet / Plunker ?

                • +3
                  Добавил ссылку на GitHub в конец статьи
                • +1

                  Маленький трюк. Небольшую треугольную стрелочку можно нарисовать с помощью div'а нулевых размеров, у которого установлен border: %n%px solid transparent; (где %n% — размер стрелки) и затем красим только одну границу в нужный цвет: border-left-color: green; получится зелёная стрелка, которая показывает вправо (!). Хорошо работает в комбинации с :after и :before псеводэлементами.
                  https://jsfiddle.net/zvwpv3eb/2 тут можно потыкать и понять почему и как это.

                  • +20
                    Параллелограмм – это, прежде всего, нестандартный прямоугольник, у которого углы должны быть не всегда прямые.

                    Это мощное утверждение, опровергать я его, конечно, не буду. ))
                    • 0
                      Там ещё из пересечения двух квадратов шестиугольник получается, тоже миленько ;)
                      Но главное тут — ссылка на книжку, за это спасибо.
                    • 0
                      Анимация зелено-коричневого круга глючит в Хроме — в самый последний момент анимации моргает, возвращается градусов эдак на 10 назад и повторяет анимацию.

                      А так узнал много нового, спасибо большое) Вот только встает вопрос о поддержке браузерами некоторых «грязных» трюков, вроде currentColor, да и вообще, насколько это «правильно» с позиции стандартов CSS и разработки?
                      • +2

                        "грязный" трюк вроде currentColor поддерживается всеми браузерами практически с момента их выпуска в мир и является очень базовым механизмом никак не относящимся ни к трюкам, ни, тем более, к грязным из них.
                        Ну ладно, IE8 и ниже его не поддерживают, но это укладывается в "практически всеми".


                        Ref: https://caniuse.com/#search=currentColor

                      • 0
                        Есть еще сайт, на котором выкладывают анимации с ограниченным размером кода. Конечно функций там не так много используется, но разнообразие полученного результата поражает.
                        www.dwitter.net
                        • +3
                          все примеры из книги есть на сайте play.csssecrets.io
                          А в статье надергали несколько глав из самой книги.
                          • +3
                            Параллелограмм – это, прежде всего, нестандартный прямоугольник, у которого углы должны быть не всегда прямые.

                            Параллелограмм — четырёхугольник, у которого противоположные стороны параллельны, частным случаем которого является прямоугольник. Вроде как и понятно что имелось ввиду, но если честно такие определения вызывают дикое жжение и портят впечатления от статьи.
                            • +4
                              Недокументированные приемы CSS

                              Очень даже документированные. Все происходит как и описано в спецификации.


                              Малоизвестные — да, но никак не «недокументированные»

                              • +1
                                Не понимаю почему статья зовет все это «недокументированными» трюками css?
                                • 0
                                  Хорошо зашло! Спасибо
                                  В комментах пуканы горят, как будто личное оскорбление в названии статьи
                                • 0
                                  Книга действительно стоящая
                                  • 0
                                    ага, с первого абзаца узнал эту книгу.

                                    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                    Самое читаемое