В этой статье я покажу вам, как использовать современные приемы CSS для создания причудливых форм ленты CSS с минимальным количеством кода. В качестве дополнительного бонуса наши ленты будут иметь анимацию при наведении!
Ленты CSS повсюду, и вы можете найти массу статей о них, но те, которые мы создадим здесь, немного особенные. Мы собираемся использовать один элемент для создания каждой фигуры и переменные CSS, чтобы легко ими управлять. Мы не собираемся полагаться на фиксированные размеры или магические числа. Формы будут соответствовать их содержимому, поэтому вам не придется беспокоиться о тексте внутри.
Я собрал коллекцию ленточных фигур CSS с множеством интересных примеров, и в этой статье мы собираемся изучить два их типа, изображенных ниже.
Я буду называть левую «свернутой лентой», а правую — «повернутой лентой».
Создание формы сложенной ленты CSS
Первым шагом в создании свернутой ленты CSS является определение переменных нашей фигуры.
.ribbon { --r: 20px; /* control the cutout of the ribbon */ --s: 20px; /* size of the folded part */ --c: #d81a14; }
Две переменные будут управлять формой, а одна переменная будет управлять цветом.
Теперь перейдем к коду. В основном мы будем полагаться на clip-path. Изображение ниже иллюстрирует форму многоугольника, который мы собираемся использовать.
Мы добавляем отступы, чтобы не обрезать текст, а затем применяем clip-path:
.ribbon { --r: 20px; /* control the cutout of the ribbon */ --s: 20px; /* size of the folded part */ --c: #d81a14; line-height: 1.6; /* control the height */ padding-inline: 1.2lh calc(var(--r) + .2lh); background: var(--c); clip-path: polygon(1lh 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,100% 100%, 0 100%,0 100%); }
Использование модуля CSS lh
Вам может быть интересно, что происходит с lhустройством. Это новая единица, соответствующая значению line-height. Поскольку мы используем одну строку текста, эта line-heightнастройка управляет высотой, поэтому 1lhона эквивалентна высоте элемента, что очень полезно.
В clip-pathмне нужно вырезать форму равнобедренного треугольника, и для этого мне нужно знать высоту элемента. 1lhравна этой высоте.
Теперь, чтобы создать сложенную часть, мы по-прежнему будем использовать clip-pathи обновлять предыдущий многоугольник. Самое интересное в clip-pathтом, что он может вырезать «за пределами» границ элемента. Это может показаться удивительным или, возможно, бесполезным, учитывая, что снаружи у нас ничего нет, но это означает, что мы можем включать такие вещи, как тень блока, контур, псевдоэлементы и так далее.
В нашем случае мы будем полагаться на box-shadow. Изображение ниже иллюстрирует этот трюк.
Обратите внимание, как я обновляю элемент, clip-pathдобавляя в него четыре новых точки, три из которых находятся за пределами элемента. Поскольку часть, которую мы вырезаем, находится снаружи, она не видна, но если мы добавим большую часть, box-shadowмы сделаем ее видимой. Я использовал синий цвет, чтобы проиллюстрировать идею выше, но в коде мы будем использовать тот же цвет, что и фон:
.ribbon { --r: 20px; /* control the cutout of the ribbon */ --s: 20px; /* size of the folded part */ --c: #d81a14; line-height: 1.6; /* control the height */ padding-inline: 1.2lh calc(var(--r) + .2lh); background: var(--c); clip-path: polygon(1lh 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,1lh 100%,1lh calc(100% + var(--s)),.5lh calc(100% + var(--s) + var(--r)),0 calc(100% + var(--s)),0 100%); box-shadow: 0 0 0 999px var(--c); /* a big spread radius */ }
Наконец, мы добавим эффект тени, применив градиент и еще одну тень блока, и все готово. Наша форма ленты CSS идеальна!
Вам, наверное, интересно, как создать вторую ленту (зеленую). Делаем то же самое, но с другим полигоном. Берем первый многоугольник и инвертируем его.
Многоугольник можно записать так:
clip-path: polygon(X1 Y1, X2 Y2, ..., Xn Yn)
Чтобы получить противоположную форму, вы меняете все Xiна 100% — Xi. Так просто! Прежде чем проверять мой код, попробуйте сделать это самостоятельно, используя многоугольник первой ленты.
В приведенной выше демонстрации наведите курсор на фигуры, чтобы увидеть красивую анимацию. Чтобы добиться этого, нам нужно обновить многоугольник при наведении курсора, сместив некоторые точки. Я не буду переписывать весь многоугольник при наведении, но определю переменную CSS, которая будет управлять смещением.
Если вы сосредоточитесь на анимации, вы заметите, что у нас есть три точки, движущиеся влево, а также три точки, движущиеся вниз и влево.
Мы обновляем Xi точки, движущиеся влево, с помощью Xi + dи обновляем Yiточки, перемещающиеся с помощью Yi + d. Затем мы просто обновляем переменную dдля управления движением:
.ribbon { --d: 0px; /* This will control the offset */ clip-path: polygon(calc(1lh + var(--d)) 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,calc(1lh + var(--d)) 100%,calc(1lh + var(--d)) calc(100% + var(--s) + var(--d)),calc(.5lh + var(--d)) calc(100% + var(--s) + var(--r) + var(--d)),var(--d) calc(100% + var(--s) + var(--d)),var(--d) 100%); } .ribbon:hover { --d: .2lh; }
Если вы видите такой многоугольник впервые, вы можете растеряться, так как выглядит он немного пугающе. Но на самом деле все не так сложно. Мы начали с простого многоугольника и постепенно добавляли больше точек и вычислений, пока не дошли до этого сложного.
Создание повернутой формы ленты CSS
Давайте займемся второй формой. Для этого мы будем использовать новые тригонометрические функции вместе с переменными CSS, calc()как и в предыдущем случае. Чтобы понять логику этой фигуры, давайте повернем ее и сохраним текст в виде прямой линии.
Я добавляю немного прозрачности, чтобы увидеть части позади основного элемента. Для их создания я буду использовать псевдоэлементы. Я также добавил синий контур, чтобы проиллюстрировать область элемента. Эта форма будет управляться двумя переменными:
.ribbon { --r: 30px; /* control the cutout of the ribbon */ --a: 15deg; /* control the rotation */ }
Выполняет rту же работу, что и предыдущая фигура. Он aбудет управлять вращением основного элемента и многим другим.
Начнем с основного элемента. Из рисунка видно, что нам нужно разрезать его с каждой стороны, так что вы можете логически подумать об использовании clip-path, но не в этот раз. Мы будем использовать градиентную окраску, при которой часть, которую нам нужно вырезать, будет иметь прозрачный цвет:
.ribbon { --r: 30px; /* control the cutout of the ribbon */ --a: 15deg; /* control the rotation */ background: linear-gradient(calc(90deg + var(--a)), #0000 calc(1lh*sin(var(--a))), var(--c) 0 calc(100% - 1lh*sin(var(--a))), #0000 0 ); }
Вот и геометрия.
Это aугловая переменная, которую мы определили. Учитывая это, градиент должен иметь угол, равный 90deg + a, а прозрачный цвет должен начинаться 0и заканчиваться на d. Посчитав немного, dбудет равно 1lh*sin(a). Если мы применим ту же логику с другой стороны, мы получим следующий код:
background: linear-gradient(calc(90deg + var(--a)), #0000 0% calc(1lh*sin(var(--a))), var(--c) calc(1lh*sin(var(--a))) calc(100% - 1lh*sin(var(--a))), #0000 calc(100% - 1lh*sin(var(--a))) 100% );
Мы проводим некоторую оптимизацию, удаляя символы 0%и 100%(они неявны), и когда у нас есть две последовательные точки цвета, которые равны, мы можем заменить вторую на 0:
background: linear-gradient(calc(90deg + var(--a)), #0000 calc(1lh*sin(var(--a))), var(--c) 0 calc(100% - 1lh*sin(var(--a))), #0000 0 );
С основным элементом мы закончили, перейдем к псевдоэлементам. Здесь нам также понадобятся некоторые геометрические хитрости, чтобы определить размер.
Мы можем легко найти высоту H из предыдущего рисунка, который мы использовали для определения конфигурации градиента. Это равно 1lh/cos(a). Для ширины W она равна (100% — x)*cos(a), где 100%— ширина основного элемента и x— та маленькая часть, где у нас есть прозрачность. Это равно 1lh*tan(a).
Оба псевдоэлемента имеют одинаковый размер, поэтому наш код выглядит следующим образом:
.ribbon:before, .ribbon:after { content: ""; position: absolute; height: calc(1lh/cos(var(--a))); width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a))); }
Если вам не нравится математика и вы немного запутались в формуле, ничего страшного. Вам не нужно точно понимать их. Цель состоит в том, чтобы иметь возможность корректировать форму с помощью переменных CSS. Формулы созданы для того, чтобы упростить задачу и избежать необходимости иметь дело с жестко запрограммированными значениями и магическими числами.
После простановки размеров нам следует правильно разместить каждый псевдоэлемент, повернуть его и использовать clip-pathдля вырезаемой части:
.ribbon:before, .ribbon:after { content: ""; position: absolute; transform: translate3d(0,0,-1px); rotate: var(--a); height: calc(1lh/cos(var(--a))); width: calc(100%*cos(var(--a)) - 1lh*sin(var(--a))); background: color-mix(in srgb,var(--c),#000 40%); } h1:before { right: 0; top: 0; transform-origin: top right; clip-path: polygon(0 0,100% 0,100% 100%,0 100%,var(--r) 50%); } h1:after { left: 0; bottom: 0; transform-origin: bottom left; clip-path: polygon(0 0,100% 0,calc(100% - var(--r)) 50%,100% 100%,0 100%); }
Код должен быть понятен, а clip-pathзначение должно быть легко понять. Мы использовали более сложные полигоны первой формы.
Обратите внимание на использование color-mix(), которое позволяет мне создать темную версию основного цвета. Я также использую 3D-преобразование с отрицательным значением по оси Z, чтобы расположить псевдоэлементы позади основного элемента.
Теперь, если мы повернём элемент в противоположном направлении, мы получим форму ленты CSS.
Как и в предыдущем примере, я позволю вам проанализировать код зеленой ленты и посмотреть, какие изменения я внес, чтобы получить противоположную форму.
Заключение
Это было забавное упражнение, вам не кажется? Мы изучили некоторые современные функции CSS, такие как переменные CSS calc()и тригонометрические функции, и объединили их для создания причудливых форм ленты.