Наклонные плоскости при помощи «after» и «before»

С недавнего времени у веб-дизайнеров проснулся интерес к неровным плоскостям объектов и они смело внедряют их в свои макеты. Не стоит однако думать, что неровную плоскость изобрели вчера, просто раньше её создавали иначе и редко применяли к крупным объектам страницы. Например, треугольник можно создать при помощи свойства border-width, достаточно лишь указать четыре (всем сторонам прямоугольника) значения и четыре значения для border-color, одно из которых будет иметь фоновый цвет, а остальным надо задать прозрачность.

.arrow {
    width: 0;
    height: 0;
    border-style: solid;
    border-width: 50px 0 50px 100px;
    border-color: transparent transparent transparent #e100f5;
}

Таким образом создаются стрелки навигации. И не только они. Сегодня же я хочу поговорить о принципиально иной технике создания неровной плоскости при помощи псевдоэлементов ::after и ::before.

В веб-дизайне теория неотделима от практики, чтобы объяснить, как и что делается, необходимо продемонстрировать сам процесс, поэтому для начала я создам div и напишу в нём что-нибудь, чтобы он не был пустым.

<div class="example">
    <h1>Привет, друг!</h1>
</div>

Добавлю стиль.

.example {
    position: relative;
    width: 600px;
    height: 300px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: coral;
}

У меня получился самый обычный прямоугольник, с фиксированным размером и текстом, который я при помощи свойства flex выровнял посередине.

Наклонные плоскости при помощи «after» и «before»

Но что если я захочу, чтобы одна из сторон шла не под прямым углом, а была наклонной, и чтобы мой объект напоминал трапецию? Очевидно, что мне придётся воспользоваться трансформацией и наклонить его в 2D пространстве. Это можно сделать при помощи функции skew по X, или Y, или по обоим вместе. Если к моему прямоугольнику применить transform: skewY(5deg), то это наклонит плоскость.

Наклонные плоскости при помощи «after» и «before»

Однако это трансформирует и всё то, что находится внутри объекта. Посмотрите, что стало с текстом. Даже если вставить внутрь ещё один div и поместить текст туда, даже если задать ему абсолютное позиционирование, это не приведёт ни к чему, — все вложения будут деформироваться так же, как оболочка.

Вот тут и приходят на помощь псевдоэлементы ::after и ::before, которые всегда имеют абсолютное позиционирование и могут подвергаться какой угодно трансформации, не затрагивая при этом ни родительский объект, ни те, что находятся внутри него. При помощи трансформации данных псевдоэлементов мы можем создать объект даже с двумя наклонными плоскостями, причём наклонными под разными углами. Это могут быть большие объекты, как шапка или подвал, это могут быть информационные разделы посреди страницы, это могут быть линки или кнопки, это может быть меню, — что угодно. Псевдоэлементы ::after и ::before не оказывают никакого влияния на расположенные вблизи объекты, в большинстве случаев они необходимы лишь для того, чтобы добавить нечто бессмысленное с точки зрения функционала, но необходимое для дизайна.

Шапка будет шапкой и без элемента ::after, линки будут работать и без него, но когда речь заходит о дизайне, то выясняется, что этот элемент необходим; чтобы что-то оформить, нет нужды создавать дополнительный объект в HTML, всё делается при помощи одного CSS.

Итак, вернусь к своему первоначальному макету. У меня есть оболочка, представляющая собой прямоугольник, — и пусть так и останется. Я не буду применять к ней трансформацию, чтобы не затронуть текст, но добавлю к ней псевдоэлемет ::after и применю трансформацию к нему.

.example::after {
    --offset: 10px;
    --skew-y: 0.025;
    content: "";
    display: block;
    position: absolute;
    width: 100%;
    height: calc(100% + var(--offset));
    background-color: coral;
    transform: matrix(1, var(--skew-y), 0, 1, 0, -15);
    z-index: -1;
}

Как можно видеть, я создал элемент .example::after, по ширине равный родительскому .example, а по высоте превышающий его на 10px, и трансформировал его при помощи функции matrix, которая содержит сразу несколько позиций трансформации:

matrix(scaleX(), skewY(), skewX(), scaleY(), translateX(), translateY())

У меня получился объект, с наклонной плоскостью наверху.

Наклонные плоскости при помощи «after» и «before»

Что тут не так? В глаза сразу бросаются лишние 10px наверху. Попробую исправить. Добавлю ::before и изменю код следующим образом:

.example {
    position: relative;
    width: 600px;
    height: 300px;
    display: flex;
    justify-content: center;
    align-items: center;
}

.example::after,
.example::before {
    content: "";
    display: block;
    position: absolute;
    height: 100%;
    width: 100%;
    background-color: coral;
}

.example::after {
    --offset: 10px;
    --skew-y: 0.025;
    content: "";
    display: block;
    position: absolute;
    width: 100%;
    height: calc(100% - var(--offset));
    transform: matrix(1, var(--skew-y), 0, 1, 0, -15);
    z-index: -1;
}

.example::before {
    height: 10%;
    bottom: 0;
    z-index: 1;
}

Здесь я убрал фоновый цвет основного объекта .example, тем самым сделал невидимым основной прямоугольник, и вниз опустил псевдоэлемент ::before, который представляет собой всего лишь ровную полосу и скрывает нижний край наклонного ::after. В итоге у меня получился объект с наклонной плоскостью наверху и ровной внизу. Если бы, например, мне понадобилось наклонить и нижнюю плоскость, то я бы мог оставить фоновый цвет основному объекту и проделать с ::before то же самое, что и с ::after, как в примере выше; в этом случае они бы дополнили друг друга и лишнее расстояние уже не мешало бы восприятию.


Напоследок хочу продемонстрировать, что с этим со всем можно сделать на примере живого кода при оформлении линка. Также добавлю простенький hover-эффеект, чтобы оживить демонстрацию.

See the Pen Inclined planes with «after» and «before» by haracan (@haracan) on CodePen.

Таким же образом можно оформлять крупные объекты, в которых помещено много контента, как шапка и подвал, например. Можно сочетать наклонные плоскости при помощи псевдоэлементов ::after и ::before с техникой масок, из предыдущей статьи.

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

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