- Фоны и рамки;
- Фигуры;
- Визуальные эффекты.
![](https://habrastorage.org/webt/xl/fc/9q/xlfc9q5myw2gcdzv0panh5f1kla.gif)
Фоны и рамки
В первой теме «Фоны и рамки» я расскажу, что такое currentColor в CSS3, как cделать прозрачные рамки, несколько рамок, что такое гибкое позиционирование фона. Во второй теме «Фигуры» приведу методы создания различных видов прямоугольников с помощью css. В визуальных эффектах рассмотрю примеры наложения различных цветовых тонов. А в теме «Взаимодействие с пользователем» покажу, как сделать интерактивное сравнение изображений.
Как вы думаете, какого цвета будет border у блока с текстом «Hello world»?
![](https://habrastorage.org/webt/iw/ke/jp/iwkejp3znnh2s9v5cgr1qcxuaas.png)
Такого же синего? Да, правильно. А почему?
![](https://habrastorage.org/webt/sp/f5/al/spf5alj7mt3hz0oksbz01bwehlw.png)
Цвет будет такой же, #38A потому что в CSS есть такая прекрасная переменная, как currentCollor, которая берет свое значение цвета из свойства color. И если мы не передадим цвет в border, outline, text-shadow, box-shadow, то по умолчанию получим такой же цвет, что и в свойстве color.
На рисунке ниже можно увидеть, что currentColor можно передавать, как явным образом, так и не передавать вовсе.
![](https://habrastorage.org/webt/fb/vt/um/fbvtumsfacwxqw_sl14wqkzpzp0.png)
Переменная currentColor предоставляет нам очень удобный код и соответствует принципам DRY (don’t repeat yourself — не повторяйся). И как показано на следующем рисунке, изменяя только свойство color, для блока с кодом, который был представлен выше, мы получаем разное отображение элемента.
![](https://habrastorage.org/webt/ek/kg/rf/ekkgrfs_zurwomllqndd8oz1m5o.png)
Полупрозрачные рамки
Если бы меня кто-нибудь спросил раньше, как сделать полупрозрачные рамки, то я бы ответил: «Легко! Я бы сделал два блока дива: родительский и дочерний. И уже в родительском задал бы некоторый padding: 10px и background-color: rgba(255, 255, 255, 0.5) (полупрозрачный), который был бы цветом моей прозрачной границы». Но это можно сделать гораздо проще.
![](https://habrastorage.org/webt/ga/bz/ak/gabzakfxtxdjicd6qjjq28qbgom.png)
![](https://habrastorage.org/webt/dk/ss/ga/dkssganmxcdv1rsubthcledawoc.png)
Что если мы просто передадим полупрозрачный border для нашей рамки? Мы ничего хорошего не получим. Почему? В CSS есть такое свойство, как background-clip, и многие забывают о его существовании. Background-clip отвечает за распространения фона и имеет три значения: border-box (по умолчанию), content-box и padding-box.
По умолчанию оно у нас border-box, что значит, что наш фон будет заходить под нашу рамку, и мы не увидим ту самую прозрачность, которую передали в border, так как у нас наш фон будет под нашей границей. Также в background-clip можно передавать content-box, что будет значить, что наш фон распространяется под нашим контентом. Но тут передаем padding-box и получаем вот такую прозрачную рамку.
![](https://habrastorage.org/webt/y1/hc/5z/y1hc5za8zmt7dsoyhqzhjp4ylfg.png)
Несколько рамок
Несколько рамок мы можем создать двумя способами, один используя border и outline. Border и Outline хороши, но с помощью их мы можем сделать только две рамки.
![](https://habrastorage.org/webt/ox/dl/bq/oxdlbqr0gplfrbyuvmb5x4gyddm.png)
А что если нам потребуется куда больше рамок, к примеру 3, 4 или более, то тут нам на помощь приходят тени.
![](https://habrastorage.org/webt/qz/h_/yl/qzh_yljnqkr7rhu5xidhd9652ho.png)
Все из нас сталкивались со свойством 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.
![](https://habrastorage.org/webt/xl/ml/bl/xlmlblqw5orkmuc6bidt03t8cyo.png)
Точно также, если написать background-position: right 10 px top 20 px, то получим отступ справа 10 px, сверху 20 px.
![](https://habrastorage.org/webt/8e/c9/2b/8ec92ba53bn4wajmjqwiabnqytc.png)
С помощью гибкого позиционирования можно располагать несколько картинок в нашем фоне. Мы им всем говорим no-repeat и с помощью ключевых слов раскидываем по разным углам. Вот так круто получается. отлично все поддерживается, пользуйтесь.
![](https://habrastorage.org/webt/bu/lp/cn/bulpcnk7ckr080sxgwm8svlpz-4.png)
Фон в полоску
![](https://habrastorage.org/webt/5x/tj/_z/5xtj_zyzgm3loukqfn0qizq4bls.png)
Поговорим о создании фона. Обычно для создания какого-либо неоднотонного фона мы прибегаем к использованию различных картинок, которые сделаны с помощью визуальных редакторов. Или нам дизайнер нарисовал картинку, мы ее вставили, и у нас все красиво отображается.
Но простой фон в полоску можно сделать с помощью одного лишь CSS.
Все мы знаем, как выглядит стандартный градиент.
![](https://habrastorage.org/webt/u5/wb/mc/u5wbmctlm8oc0ohk7ym35xcvxr8.png)
А что если мы этому градиенту зададим границы распространения?
![](https://habrastorage.org/webt/si/2p/xg/si2pxgigxlawew1-njlorplqdom.png)
То по краям мы увидим сплошной цвет.
А что если мы сведем градиент к одной точке?
![](https://habrastorage.org/webt/ud/1c/ol/ud1col8nfekvoegbizv4429l3hu.png)
Мы увидим просто две полоски. Вот эти две полосы будут основой нашего фона в полоску. Далее задаем background-size: 30px. Одна полоса будет 15 px и вторая тоже 15 px, так как градиент разделен 50/50. И получаем вот такой вот фон в полоску.
![](https://habrastorage.org/webt/v_/uo/9d/v_uo9dzev_r0phrnnlz97ww8hxy.png)
Для того чтобы сделать одну полосу больше, другую меньше, мы для желтого цвета задаем 30%, а для синего — 0. Что значит вот этот ноль? 30% у нас, понятное дело, будет занимать желтый цвет. А вот что значит вот этот 0, кто-нибудь может сказать? По сути, это просто оставшееся расстояние нашего background-size. То есть 30% из 30px – это примерно 9px у нас заполнится желтым, а вся остальная часть синим.
![](https://habrastorage.org/webt/iu/sr/et/iusreta84ivaookkaonrfc5zniq.png)
Для того чтобы нарисовать несколько цветов в нашем фоне, мы сталкиваемся с такой ситуацией, как промежуточное повторение цветов. То есть я говорю нашему желтому цвету: заполни мне 33% нашего фона желтым цветом, а ставшуюся часть заполни синим. Потом синему цвету говорю: нет, до 66% заполни, и все остальное заполни желто-зеленым, и получаем 3 цвета в нашем фоне.
![](https://habrastorage.org/webt/al/no/nl/alnonl0emgo1jswvgf4ccmzioq0.png)
Для того чтобы сделать вертикальные полосы — все то же самое, только у нас меняется background-size и в linear-gradient появляется ключевое слов to right. Также вместо ключевого слова мы можем вставить 90° и все отобразится, как надо.
![](https://habrastorage.org/webt/cj/-b/a0/cj-ba0sdfnldoydwcu6-di4qgeq.png)
Если мы совместим горизонтальные и вертикальные полосы вместе, то получим вот такой вот фон в решетку.
У нас есть квадратный background-size, мы передаем через запятую в background-image наши градиенты и получаем фон в решетку.
![](https://habrastorage.org/webt/pq/9b/z6/pq9bz62u8otk0yrzkkxm1waktw0.png)
С фоном в диагональную полосу немного посложнее. Здесь мы уже не пользуемся обычным linear-gradient-ом, мы здесь пользуемся repeating-linear-gradient. Обратите внимание, что наш фон распространяется до 30 px, и background-size у нас квадратный 42px на 42px. Почему же все-таки 42?
![](https://habrastorage.org/webt/_u/nc/zq/_unczqnrgqt0aahdjgef-lrdqes.png)
А что, если мы передадим что-нибудь другое? К примеру 30px вместо 42px.
![](https://habrastorage.org/webt/x1/xi/k-/x1xik-9afjdrctlfiz55svnjuve.png)
![](https://habrastorage.org/webt/8u/op/f0/8uopf0v00vzdv4qgia4c5jpsmeq.png)
Почему же все-таки 42px. На помощь приходит обычная школьная математика.
![](https://habrastorage.org/webt/en/h5/dv/enh5dv-e9m4ss6eknycg8pkjpc0.png)
Мы знаем, что наш фон – квадрат, а квадрат состоит из двух равнобедренных треугольников. Дальше мы делаем некоторые математические преобразования, но при этом помним, что наш фон распространяется до 30px.
![](https://habrastorage.org/webt/4x/or/cf/4xorcffglorqonzhkmfv1z7elb0.png)
Подставляем в нашу формулу 30 и получаем примерно 42. Округляем в меньшую степень. Получаем вот такой фон, диагональные полосы.
![](https://habrastorage.org/webt/yc/ax/0y/ycax0yoez7iispbcpytwaybczck.png)
![](https://habrastorage.org/webt/og/kb/oy/ogkboygnmr3r9fkjtednhtw8fho.png)
lea.verou.me/css3patterns
У автора книги «CSS секреты» Леа Веру, сотрудника всемирного веб-консорциума w3с, есть целая подборка фонов, которые она реализует с помощью градиентов.
Примеры, которые реализует Леа Веру.
Примеры, реализованные Беннеттом Фили.
Фигуры
И начну я эту тему с параллелограммов.
![](https://habrastorage.org/webt/jk/ny/44/jkny44oto8ryodsnmiz1fgk9hec.png)
Все из нас знают, как выглядят параллелограммы. Параллелограмм – это, прежде всего, нестандартный прямоугольник, у которого углы должны быть не всегда прямые. Для того чтобы сделать скошенные углы, можно обойтись псевдоклассом before. Задаем относительное позиционирование (position: relative) классу button, а абсолютно позиционируем псевдокласс before. Задаем псевдоклассу background, делаем трансформацию с помощью skewX и получаем вот такие скошенные углы.
![](https://habrastorage.org/webt/bj/ec/jc/bjecjcdej7vlx7upd2bflkpu-gg.png)
Для того чтобы сделать трапецию — все то же самое, аналогично. Только здесь мы передаем перспективу и rotateX. И получаем вот такую трапецию.
![](https://habrastorage.org/webt/vr/i1/wc/vri1wcknf19n9d_mh1a_2br98eg.png)
Изображение в форме ромба можно сделать различными способами. Один из них также с помощью трансформации. То есть у нас есть родительский div, и в него вложено изображение.
![](https://habrastorage.org/webt/ja/-a/ie/ja-aieex8xhow1ptukhpt95xmty.png)
Поворачиваем родительский div на 45 градусов, и уже получаем ромб, но изображение у нас наклонилось тоже. Мы хотим его вернуть к нормальному виду и разворачиваем наше изображение обратно на -45 градусов. В итоге получается шестиугольник. Почему? А потому что у нас здесь два прямоугольника, и они срезают углы. Для того чтобы у нас получился именно ромб, мы просто задаем scale(1.42), увеличиваем наше изображение и получаем вот такой ромб.
![](https://habrastorage.org/webt/hk/wd/rp/hkwdrpsxakxrydl0tevelsfuz_q.png)
Изображение в форме ромба можно сделать также с помощью clip-path. Туда мы можем передавать различные имена такие, как circle, polygon и другие. Здесь я пользуюсь полигоном. Я передаю в polygon середину каждой стороны квадрата, а при hover-e возвращаю точки к углам квадрата и получаю вот такую вот анимацию. Это очень хорошее свойство.
![](https://habrastorage.org/webt/oo/iq/fu/ooiqfudhqr7hdzegtvorjrlu5ma.gif)
<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.
![](https://habrastorage.org/webt/3o/io/5g/3oio5gudlzbi2xo71oeuvsvjxrq.png)
Как сделать срезанные углы? Вспомним тему про фон в полоску. Здесь точно также с градиентами. Мы, по сути, разделяем наш фон на 4 части. У нас есть 4 градиента, которые мы раскидываем с помощью гибкого позиционирования по разным углам и закрашиваем их от прозрачного цвета до синего. И получаем срезанные углы.
![](https://habrastorage.org/webt/z-/0b/xo/z-0bxosjbyzf7nj9n1-mldurpmw.png)
Для того чтобы сделать срезанные углы во внутрь, здесь используется radial-gradient. Единственное, что у нас появляется, это такие ключевые слова, как circle at top left, чтобы расположить кружочки в различных углах. Опять же 4 части расставляем, с помощью ключевых слов, по местам и получаем такие углы.
![](https://habrastorage.org/webt/u5/p6/_k/u5p6_ks5wuwiyhodg_bydaf43tk.png)
![](https://habrastorage.org/webt/u5/p6/_k/u5p6_ks5wuwiyhodg_bydaf43tk.png)
Как сделать простые секторные диаграммы с помощью одно лишь CSS. Обычно, чтобы создать секторные диаграммы, мы пользуемся каким-либо фреймворком, например, d3.js. Но простую секторную диаграмму можно сделать на CSS.
У нас есть блок, мы из него делаем круг.
![](https://habrastorage.org/webt/48/2f/oz/482foznd6pwuxx0jcvaz2f6i_lm.png)
Половину круга закрашиваем коричневым цветом.
![](https://habrastorage.org/webt/aq/jx/nd/aqjxndqmxvmsw-qazkth8b3ztq4.png)
Дальше делаем псевдокласс, который закрашиваем в тот же зеленый цвет, который уже есть в блоке.
![](https://habrastorage.org/webt/ak/fy/qd/akfyqd0bguv77r7cx-essu4ttnk.png)
По сути, просто двигая этот псевдокласс, уже получается некоторый вид секторной диаграммы, но только до половины, так как другая часть у нас зеленая.
![](https://habrastorage.org/webt/vd/l9/jx/vdl9jx_ln_pegkghnt2fbjirvmc.gif)
![](https://habrastorage.org/webt/wf/tx/pw/wftxpwx5wxllxe7ikmd5jkr9dog.gif)
Опишу такой интересный подход, если передавать в наш блок отрицательный animation-delay и при этом animation-play-state оставить в состоянии paused, то можно заметить, что изменяется состояние нашего элемента. И если у нас анимация проигрывается до 4s (4 секунд), и мы напишем в стилях -2s, то получим на половину проигравшее состояние, и наш круг будет на половину закрашен.
![](https://habrastorage.org/webt/r6/qz/db/r6qzdbs2colbnkjhvku16iaotzi.png)
Визуальные эффекты
![](https://habrastorage.org/webt/4c/pg/2u/4cpg2uj3qpel-mcxvifhvrdssag.png)
Наложения цвета можно сделать различными способами, я приведу два примера: первый из них наложения цвета с помощью фильтров. С помощью фильтров мы можем наложить множество оттенков, но добиться какого-либо конкретного будет проблемой для многих. И тут на помощь приходит такое свойство, как background-blend-mode.
![](https://habrastorage.org/webt/n7/bh/dg/n7bhdgr3zg03cupakop3tqnmpec.png)
И перейдем к гораздо более адаптивному способу: это 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;
}
Но, к сожалению, у это свойства не всё хорошо с поддержкой. И пользоваться им или нет, решать вам.
![](https://habrastorage.org/webt/tl/_2/hc/tl_2hcfavkuiqb8ttlxn24t2gpw.png)
Следующий пример — плавная анимация состояния. Почему он так называется, давайте посмотрим.
У нас есть панорама, и мы хотим добавить немного анимации.
![](https://habrastorage.org/webt/jd/pz/25/jdpz25rrw_luqhdzgnqvqdwfxyo.png)
Помещаем изображение на фоне и после анимируем 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;}
}
![](https://habrastorage.org/webt/bl/rt/v_/blrtv_djavskci_qzpuuqb8hvh0.png)
Обратите внимание именно на верстку, на HTML. У нас есть контейнер, image-slider, и у него есть одно изображение, которое вложено в div, а другое не вложено. Для родительского контейнера мы задаем position: relative, а для вложенного в div изображения, с ним и будем работать, мы задаем position: absolute и ширину 50%. Самое главное — мы ему делаем resize: horizontal.
![](https://habrastorage.org/webt/jc/oh/gg/jcohggyfknotueqfvynkdz5oxsy.png)
С помощью этого resize у нас будет интерактивное сравнение. Так как у меня очень хорошее разрешение, мы не видим такого бага, который возникает из-за resize: horizontal. У нас появляется ползунок, который подобен resize-ползунку HTML-элемента textarea. Для того чтобы его убрать, мы просто закрашиваем его псевдоклассом и завязываем на нем cursor: ew-resize.
![](https://habrastorage.org/webt/fm/c6/jf/fmc6jfag_peg1rilmjtp7vqrnho.png)
Хочу отметить, что в основу статьи вошла книга Css Secrets. Better Solutions to Everyday Web Design Problems. Хоть она уже и давно вышла, я настоятельно рекомендую прочитать эту книгу. Из этой книги вы узнаете гораздо больше, чем я здесь представил и по-настоящему попробую многие секреты CSS вживую.
Ссылка на репозиторий с примерами и презентацией
Комментарии (23)
extempl
17.01.2018 19:24+1Шерить код картинками да ещё и разными размерами — так себе решение. Особенно для туториала, где возможность скопировать код — маст хев.
А так — довольно полезно для тех, кто не следит за Lea Verou.
Хотя не знал про относительное позиционирование (right 10px) и про применения background-clip для решения прозрачных рамок, хотя решение конечно лежит на поверхности.SelenIT3
17.01.2018 20:30+1У background-clip вообще немало полезных применений. Причем вполне документированных!:)
kartvladek
18.01.2018 14:45кстати да — для себя именно это и отметил. всё остальное известно именно от Lea Verou
Amareis
17.01.2018 20:35Маленький трюк. Небольшую треугольную стрелочку можно нарисовать с помощью div'а нулевых размеров, у которого установлен border: %n%px solid transparent; (где %n% — размер стрелки) и затем красим только одну границу в нужный цвет: border-left-color: green; получится зелёная стрелка, которая показывает вправо (!). Хорошо работает в комбинации с :after и :before псеводэлементами.
https://jsfiddle.net/zvwpv3eb/2 тут можно потыкать и понять почему и как это.
tehnolog
17.01.2018 20:50Параллелограмм – это, прежде всего, нестандартный прямоугольник, у которого углы должны быть не всегда прямые.
Это мощное утверждение, опровергать я его, конечно, не буду. ))bb0ff
19.01.2018 06:36Там ещё из пересечения двух квадратов шестиугольник получается, тоже миленько ;)
Но главное тут — ссылка на книжку, за это спасибо.
daemonhk
18.01.2018 07:54Анимация зелено-коричневого круга глючит в Хроме — в самый последний момент анимации моргает, возвращается градусов эдак на 10 назад и повторяет анимацию.
А так узнал много нового, спасибо большое) Вот только встает вопрос о поддержке браузерами некоторых «грязных» трюков, вроде currentColor, да и вообще, насколько это «правильно» с позиции стандартов CSS и разработки?extempl
18.01.2018 08:40"грязный" трюк вроде currentColor поддерживается всеми браузерами практически с момента их выпуска в мир и является очень базовым механизмом никак не относящимся ни к трюкам, ни, тем более, к грязным из них.
Ну ладно, IE8 и ниже его не поддерживают, но это укладывается в "практически всеми".
rrrrex
18.01.2018 10:09Есть еще сайт, на котором выкладывают анимации с ограниченным размером кода. Конечно функций там не так много используется, но разнообразие полученного результата поражает.
www.dwitter.net
mdss
18.01.2018 11:00все примеры из книги есть на сайте play.csssecrets.io
А в статье надергали несколько глав из самой книги.
jamepock
18.01.2018 12:32Параллелограмм – это, прежде всего, нестандартный прямоугольник, у которого углы должны быть не всегда прямые.
Параллелограмм — четырёхугольник, у которого противоположные стороны параллельны, частным случаем которого является прямоугольник. Вроде как и понятно что имелось ввиду, но если честно такие определения вызывают дикое жжение и портят впечатления от статьи.
justboris
18.01.2018 12:33Недокументированные приемы CSS
Очень даже документированные. Все происходит как и описано в спецификации.
Малоизвестные — да, но никак не «недокументированные»
batmandarkside
18.01.2018 20:59Хорошо зашло! Спасибо
В комментах пуканы горят, как будто личное оскорбление в названии статьи
YuryKa
CSS мощная штука. И статья интересная.
Kwisatz
Если бы еще все это еще не превращалось в ад когда нужно добицо кроссброузерности, цены бы ему не было.
Ну и действительно важные вещи не развиваются десятилетиями. 2018 год а для печати из броузеров до сих пор применяются костыли. Просто пример: попробуйте в хроме поставить разрыв страницы между строками таблицы 8)