Маски необходимы, чтобы скрыть часть объекта, к которому применяются. Это не единственный способ вырезания в CSS, но сегодня я хочу поговорить о нём, в контексте дизайна крупных объектов веб-страниц. В последнее время маски используются ещё и потому, что к приложениям и веб-страницам стали применять несколько цветовых схем, минимум две: тёмную и светлую, в связи с чем появилась необходимость в изменении цвета одних и тех же объектов, не имеющих ровных очертаний.
Итак, о чём речь? Наверняка вам встречались необычные формы шапки сайта, например такие:
Как известно, по умолчанию блоки в CSS имеют ровные стороны. Рамки, закругления, трансформацию — то есть всё, что касается неровных граней, нужно задавать самостоятельно. Можно создать неровность так: добавить блок, задать ему прозрачный фон и вставить картинку png, не имеющую фона. Но что произойдёт, если, на сайте встроен переключатель на другую цветовую схему и есть необходимость изменить цвет данного блока? В таком случае придётся менять и изображение. Подобные замены — большая нагрузка на сайт, переключение не произойдёт мгновенно, и посетитель увидит, как подгружаются изображения. И это в лучшем случае. При слабом интернете такие блоки с png-картинками могут вообще не загрузиться. Наверняка вам встречалось такое: сначала грузится контент, а потом с большим скрипом подгружаются «декорации», постепенно на наших глазах веб-страничка как будто одевается. Поэтому в прежние времена в большом ходу были «лоадеры» («loaders»), которые давали время загрузиться декорациям и скрывали от посетителя это безобразие. Кстати, они не утратили актуальность и сейчас, здесь можно посмотреть и выбрать какой душа пожелает.
Маска в качестве рамки
Ниже я хочу поговорить о сравнительно новой технике, которая позволяет создавать неровные грани и при этом:
- не перегружает страницу
- не расползается при растяжении, то есть формообразующая картинка не является растровой
- работает с несколькими цветовыми схемами, даже если фон представляет собой не один сплошной цвет, а градиент
Для начала нужно открыть любое приложение, которое работает с вектором и позволяет создавать svg-изображения. В моём случае это Adobe Illustrator. В нём нужно создать прямоугольник шириной 1000px и высотой 25px и одну из его горизонтальных сторон сделать волнообразной:
Обрежу по границам иллюстрации и экспортирую как SVG. Это будет верхней границей блока, волнистая грань для футера или любого другого объекта. Вернусь в графический редактор и разверну изображение по вертикали и горизонтали, так же экспортирую, но уже для хедера. Я развернул по горизонтали, чтобы волнистые грани не были по сути отражением друг друга, хотя если вам необходимо как раз такое отражение, то можно оставить и так, главное — отразить по вертикали.
Замечу, чтобы неровности служили гранями для объекта, находящегося где-нибудь в центре странички, который должен, например, напоминать изогнутую ленту, то вторая заготовка для маски разворачивается и по вертикали и по горизонтали.
Теперь я создам HTML и напишу следующий код:
<content>
<header>
<h3>Это пример применения маски к "header"</h3>
</header>
</content>
Как можно видеть, я собираюсь сделать шапку сайта. Теперь нужно стилизовать её:
@import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@700&display=swap');
html,
body {
--col-header: #b973f2;
--col-general: #fff;
height: 100%;
}
body {
width: 100%;
margin: 0;
padding: 0;
font-family: 'Comfortaa', cursive;
color: var(--col-general);
background-color: var(--col-general);
}
h3 {
font-size: min(2vw, 3rem);
padding: 0.5em;
}
content {
width: 100%;
height: 100%;
}
header {
display: inline-block;
width: 100%;
height: auto;
background: var(--col-mask);
text-transform: uppercase;
text-align: center;
white-space: nowrap;
letter-spacing: 2px;
}
У меня получилась обычная шапка с максимальной шириной и ровными краями. Добавлю ей элемент ::after
, к которому применю маску. Но для этого самой шапке необходимо задать позиционирование relative
:
header {
display: inline-block;
position: relative;
width: 100%;
height: auto;
background: var(--col-header);
text-transform: uppercase;
text-align: center;
white-space: nowrap;
letter-spacing: 2px;
}
header::after {
position: absolute;
content: "";
width: 100%;
height: 50px;
top: 100%;
left: 0;
background: var(--col-header);
}
Теперь собственно маска. Необходимо открыть файл SVG, который создан для нижней стороны (волна располагается по нижнему краю). Можно подгрузить его отдельно, как картинку, задав идентификатор для path
, например так: mask-image: url(border-bottom.svg#wave)
; SVG должен быть очищен от всего лишнего и выглядеть так:
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 25">
<path id="wave" d="M1000 16.88c-142.14-6.29-278.49-3.52-418.2 3.21C385.48 29.54 210.49 23.6 0 16.88V0h1000Z"/>
</svg>
В том случае, если path
очень короткий, можно встроить его непосредственно в CSS, что я и сделаю. В итоге полная стилизация маски будет выглядеть следующим образом:
header::after {
--mask-img: url('data:image/svg+xml,\ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 25">\<path d="M1000 16.88c-142.14-6.29-278.49-3.52-418.2 3.21C385.48 29.54 210.49 23.6 0 16.88V0h1000Z"/>\</svg>');
-webkit-mask-image: var(--mask-img);
mask-image: var(--mask-img);
-webkit-mask-size: 100%;
mask-size: 100%;
-webkit-mask-repeat: repeat-x;
mask-repeat: repeat-x;
/* <...> */
}
Из-за того что маскам необходимо отдельно прописывать правила для браузеров webkit, код получается слишком большой, но можно его сократить, это делается так же, как и в случае с фоновыми изображениями:
-webkit-mask: var(--mask-img) left top / 100% repeat-x;
mask: var(--mask-img) left top / 100% repeat-x;
Результат:
See the Pen Masks as an element of decor-1 by haracan (@haracan) on CodePen.
Теперь я попробую добавить футер и аналогичным образом стилизую его. Мне придётся немного изменить код HTML:
<content>
<header>
<h3>Это пример применения маски к "header"</h3>
</header>
<footer>
<h3>Это пример применения маски к "footer"</h3>
</footer>
</content>
Также изменю кое-что в файле стилей:
@import url('https://fonts.googleapis.com/css2?family=Comfortaa:wght@700&display=swap');
html,
body {
--col-header: #b973f2;
--col-footer: #4f2175;
--col-general: #fff;
height: 100%;
}
body {
width: 100%;
margin: 0;
padding: 0;
font-family: 'Comfortaa', cursive;
color: var(--col-general);
background-color: var(--col-general);
}
h3 {
font-size: min(2vw, 3rem);
padding: 0.5em;
}
content {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
header,
footer {
display: inline-block;
position: relative;
width: 100%;
height: auto;
text-transform: uppercase;
text-align: center;
white-space: nowrap;
letter-spacing: 2px;
}
header {
background: var(--col-header);
}
footer {
background: var(--col-footer);
}
header::after,
footer::after {
position: absolute;
content: "";
width: 100%;
height: 50px;
left: 0;
-webkit-mask-image: var(--mask-img);
mask-image: var(--mask-img);
-webkit-mask-size: 100%;
mask-size: 100%;
-webkit-mask-repeat: repeat-x;
mask-repeat: repeat-x;
}
header::after {
--mask-img: url('data:image/svg+xml,\ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 25">\<path d="M1000 16.88c-142.14-6.29-278.49-3.52-418.2 3.21C385.48 29.54 210.49 23.6 0 16.88V0h1000Z"/>\</svg>');
top: 100%;
background: var(--col-header);
-webkit-mask-position: left top;
mask-position: left top;
}
footer::after {
--mask-img: url('data:image/svg+xml,\ <svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 25">\<path d="M0 8.12c142.14 6.29 278.49 3.52 418.2-3.21C614.52-4.54 789.51 1.4 1000 8.12V25H0Z"/>\</svg>');
bottom: 100%;
background: var(--col-footer);
-webkit-mask-position: left bottom;
mask-position: left bottom;
}
Думаю, вы уже обратили внимание на то, что фоновый цвет для псевдоэлементов, к которым применены маски, совпадает с цветом фона родительских объектов; для экономии места в CSS это можно оформить и так:
header,
header::after {
background: var(--col-header);
}
footer,
footer::after {
background: var(--col-footer);
}
В результате вот что должно получиться:
See the Pen Masks as an element of decor-2 by haracan (@haracan) on CodePen.
Вот в общем и всё. Как видите, не особо сложно, нужна лишь небольшая практика. Чтобы при переключении цветовой схемы изменились цвета данных объектов, достаточно поменять значения цвета в --col-header
и --col-footer
, одновременно с ними изменятся и фоны масок, в моём случае — волнообразных границ. Помимо сплошных цветов в качестве фона можно использовать градиенты, с той лишь разницей, что их необходимо грамотно подстраивать, чтобы не было заметно перехода от родительского объекта к дочернему, с неровной гранью. Можно также совмещать сплошной цвет с градиентом; я применил такую технику, когда работал над футером данного сайта (чтобы увидеть, как это работает, нужно нажать на кнопку переключения цветовой схемы, она в правом углу футера, рядом с кнопкой «наверх»).