Маски как элемент декора

Маски необходимы, чтобы скрыть часть объекта, к которому применяются. Это не единственный способ вырезания в 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, одновременно с ними изменятся и фоны масок, в моём случае — волнообразных границ. Помимо сплошных цветов в качестве фона можно использовать градиенты, с той лишь разницей, что их необходимо грамотно подстраивать, чтобы не было заметно перехода от родительского объекта к дочернему, с неровной гранью. Можно также совмещать сплошной цвет с градиентом; я применил такую технику, когда работал над футером данного сайта (чтобы увидеть, как это работает, нужно нажать на кнопку переключения цветовой схемы, она в правом углу футера, рядом с кнопкой «наверх»).

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

  • ⦁ создание сайтов ⦁
  • ⦁ индивидуальные проекты ⦁
  • ⦁ компьютерная графика ⦁