Формошлёп
3.93K subscribers
200 photos
151 videos
247 links
Шлёпаем формы и красим кнопки...

Блог про фронтенд — просто, понятно и с юмором. Всех обнял, приподнял, пошел пилить для вас годноту)

Связь: @advertos
Download Telegram
Так вот кто забирает все офферы)
😁294
This media is not supported in your browser
VIEW IN TELEGRAM
Адаптивные разделители для меню

Давайте сегодня разберем, как сделать адаптивные разделители, чтобы, когда у нас широкий контейнер (горизонтальное меню) — разделители были вертикальными, а когда контейнер узкий (вертикальное меню) — разделители горизонтальные.

HTML:
<div class="demo-container">
<nav>
<ul>
<li>Первый</li>
<li>Второй</li>
<li>Третий</li>
<li>Четвертый</li>
</ul>
</nav>
</div>


Базовые стили списка:
nav ul {
list-style: none;
margin: 0;
padding: 0;
display: grid;
grid-auto-flow: row;
}

■ Убираем маркеры списка и сбрасываем стандартные отступы.
■ По умолчанию элементы располагаются вертикально.

Вертикальное меню (по умолчанию):
nav li:not(:first-child) {
border-top: 1px solid white;
}

Добавляем границу сверху всем элементам, кроме первого.

Горизонтальное меню (при широком контейнере):
@container (width > 600px) {
nav ul {
grid-auto-flow: column;
}

nav li:not(:first-child) {
border-top: none;
border-left: 1px solid white;
}
}

■ Меняем направление Grid, элементы выстраиваются в ряд.
■ Убираем горизонтальную границу.
■ Добавляем вертикальную границу, у всех элементов кроме первого.

В целом всё, получаем то, что нам требовалось — адаптивные разделители)

Код можно потестить здесь.
1👍25🔥94
Переключатель размера шрифта на CSS

Видели на сайтах кнопки или ссылки для изменения размера шрифта? Давайте сегодня разберем, как сделать нечто подобное, используя "трюк с радиокнопками".

HTML:
<input id="size-small" type="radio" name="size">
<label for="size-small">Small</label>
<!-- + medium, large... -->
<section>
<p>Ваш текст...</p>
</section>


Чтобы переключатель выглядел как меню, а не как формы для опроса, скрываем сами радиокнопки:
input[name="size"] {
display: none;
}

input[name="size"]:checked + label {
border-bottom: 2px solid #3498db;
}


Переключение:
#size-small:checked ~ section {
font-size: 0.9rem;
}

#size-large:checked ~ section {
font-size: 1.1rem;
}

Это самая суть нашего метода. Мы говорим браузеру: "Если выбрана радиокнопка с таким-то ID, найди любой следующий соседний элемент section и измени его шрифт".

Такое вот CSS-only решение)

Потестить код можно здесь.
1👍19🔥74
Монументальный учебник по фронтенду и не только

Если вы уже подустали от многочасовых обучающих видосов по фронтенду, то у меня есть для вас кое-что)

Очень крутой учебник от Дмитрия Трепачёва — https://code.mu/ru/

Не просто ещё один сайт с уроками. Это структурированный учебный портал, от самых основ вёрстки до фреймворков React, Vue и Angular.

Весь материал разделён на учебники, справочники и задачники, можно изучать теорию и сразу закреплять её на практике.

В общем — крайне советую)
1👍255🔥4🤝1
Декоративные линии в заголовках на CSS

Для выделения заголовков иногда используется прием с декоративными линиями слева, справа или с обеих сторон. Давайте рассмотрим, как это можно реализовать.

HTML:
<h1>Title #1</h1>
<p>Lorem ipsum dolor sit amet</p>

<h1>Title #2</h1>
<p>Lorem ipsum dolor sit amet</p>

<h1>Title #3</h1>
<p>Lorem ipsum dolor sit amet</p>


CSS:
h1 {
display: flex;
align-items: center;
gap: 0.5em;
}

h1::before,
h1::after {
content: '';
flex: 1;
height: 2px;
background: #000;
}


display: flex превращает заголовок в flex-контейнер.
gap: 0.5em создаёт отступ между текстом и линиями.
■ Псевдоэлементы ::before и ::after создают линии.
flex: 1 растягивает линии на всё доступное пространство.

Таким образом мы получаем заголовок по центру и линии с обеих сторон.

Управление видимостью:
/* Линия только справа */
h1:first-of-type::before {
display: none;
}

/* Линия только слева */
h1:nth-of-type(2)::after {
display: none;
}


Здесь мы убираем левую линию у первого заголовка и правую у второго, создавая разнообразные варианты оформления.

Можно легко кастомизировать, поменять цвет, добавить градиент, изменить толщину или стиль линии)

Потестить код можно здесь.
👍18🔥105
Друзья, год подходит к концу, и хочу сказать спасибо, что вы здесь. Спасибо за ваши вопросы, обсуждения и поддержку)

Желаю всем в Новом году крепкого здоровья, денег нескончаемый поток и проектов, в которые хочется возвращаться по понедельникам)

Отличных праздников и до встречи в 2026-м!
43🔥18👍171
Стилизация списка точками с линией

Всем привет! Надеюсь, удалось хорошенько отдохнуть на праздниках) Будем потихоньку возвращаться в рабочий режим.

Сегодня рассмотрим нестандартный подход к оформлению списков. Вместо обычных точек создадим визуально связанную цепочку пунктов.

HTML:
<ul>
<li>Первый пункт</li>
<li>Второй пункт</li>
</ul>


Базовые стили списка:
ul {
list-style: none;
padding: 0;
}

li {
padding-left: 2em;
padding-bottom: 1em;
position: relative;
}


Заменим стандартные маркеры списка на два псевдоэлемента:
:before — для цветных точек:
li:before {
content: "";
position: absolute;
left: 0.5em;
top: 0.5em;
width: 10px;
height: 10px;
background: #f09;
border-radius: 50%;
}


:after — для вертикальных соединительных линий между пунктами:
li:not(:last-child):after {
content: "";
position: absolute;
left: 0.5em;
top: 0.5em;
width: 2px;
height: 100%;
background: #f09;
transform: translateX(4px);
}


■ Центрирование линии: transform: translateX(4px) смещает линию шириной 2px на 4px вправо, чтобы она прошла точно по центру точки 10px. Формула: (10 - 2) / 2 = 4.
■ Скрытие стыка: Линия начинается с top: 0.5em (как и точка), но визуально точка перекрывает её начало. Поэтому кажется, что линия выходит из-под точки.
■ Последний элемент: :not(:last-child) убирает линию у последнего пункта.

Отлично подходит для таймлайнов, списков шагов и любых случаев, где нужно визуально связать пункты между собой)

Пример можно посмотреть тут.
1👍23🔥204🤝1
Эффектное выделение слов в тексте

Иногда нужно сделать акцент на каком-нибудь слове. Давайте разберём технику с декоративным SVG-подчеркиванием.

HTML:
<p>Эффектное <span class="fancy">выделение</span> слов</p>


Позиционирование:
.fancy {
position: relative;
white-space: nowrap;
}


position: relative привязывает подчёркивание к слову, white-space: nowrap запрещает перенос.

Псевдоэлемент с декором:
.fancy::after {
content: "";
position: absolute;
inset: auto 0 -0.2em;
height: 0.3125em;
background: url("data:image/svg+xml,%3Csvg...") 0 / auto 100% round;
}


inset: auto 0 -0.2em — растягивает подчёркивание на всю ширину и опускает ниже текста.
height: 0.3125em — высота линии в em, масштабируется с текстом.
■ SVG-подчёркивание: берем волнистую кривую Безье в SVG, цвет задаём в stroke='%2300FDCF'. Можно использовать и другие формы — волны, зигзаги, пунктиры.

Неплохо подойдет, для акцентов в заголовках)

Пример кода здесь.
👍27🔥86
Генератор бесшовных паттернов

Если фон блока или страницы нужно сделать "повеселее", чем просто однотонный цвет или градиент. В таких ситуациях отлично подходят паттерны.

Есть простой и бесплатный инструмент Patternico, который генерирует бесшовные паттерны онлайн прямо в браузере.

Принцип работы очень прост:
■ выбираем фон и элементы;
■ настраиваем размеры, прозрачность, цвета;
■ загружаем свои изображения, иконки или Emoji;
■ получаем готовый паттерн в формате изображения.

После генерации скачиваем паттерн и добавляем его как фон через CSS:
body {
background-image: url("pattern.png");
background-repeat: repeat;
}


В общем, если что, вот — https://patternico.com/, вдруг пригодится)
🔥23👍171
This media is not supported in your browser
VIEW IN TELEGRAM
Выезжающее fullscreen-модальное окно на Popover

Давайте сегодня разберем, как с помощью Popover API создать модальное окно, которое плавно выезжает и закрывается по клику на кнопку или по клавише Esc.

HTML:
<div class="panel--home">
<button class="btn" popovertarget="slice">Открыть</button>
</div>

<div id="slice" class="panel--slice" popover>
<button class="btn btn--light" popovertarget="slice" popovertargetaction="hide">
Закрыть
</button>
</div>

popover атрибут превращает div в popover-элемент.
popovertarget="slice" связывает кнопку с popover'ом.
popovertargetaction="hide" указывает, что кнопка закрывает popover.

Позиционирование popover:
.panel--slice {
position: fixed;
inset: 0;
width: 100vw;
height: 100vh;
max-width: none;
max-height: none;
}

Растягиваем на весь экран и сбрасываем дефолтные ограничения popover.

Анимация появления:
.panel--slice {
transform: translateY(-100%); /* начальное положение за экраном */
transition: transform 800ms ease;
}

.panel--slice:popover-open {
transform: translateY(0); /* конечное положение */
}

■ Начальное состояние: панель сдвинута вверх на 100% своей высоты (за экран).
■ При активации: возвращаем панель на место (сдвиг = 0).

В результате при клике на кнопку браузер открывает popover, применяется :popover-open, и панель плавно выезжает сверху)

Потестить код можно здесь.
👍26🔥1132
This media is not supported in your browser
VIEW IN TELEGRAM
Глитч-эффект для изображения

Мы уже разбирали, как сделать простой глитч-эффект для текста, давайте теперь рассмотрим, как сделать это для изображения.

HTML:
<div class="container">
<div class="glitch-image"></div>
</div>


Изображение:
.glitch-image {
position: relative;
width: 100%;
height: 100%;
background: url('...') no-repeat center / cover;
filter: brightness(1.2);
}


Клонируем изображение:
.glitch-image::before,
.glitch-image::after {
content: '';
background: inherit; /* копируем ту же картинку */
position: absolute;
inset: 0; /* растягиваем на весь блок */
}

Теперь у нас 3 одинаковых слоя друг на друге.

Первый слой дергается:
.glitch-image::after {
animation: glitch-clip 1s infinite;
}

@keyframes glitch-clip {
12% {
left: -5px; /* сдвинули влево */
clip-path: inset(32% 0 41% 0); /* обрезали сверху/снизу */
}
17% {
left: 0; /* вернули обратно */
clip-path: none; /* убрали обрезку */
}
/* ... и так далее */
}

Слой дергается влево-вправо и показывается кусками.

Второй слой меняет цвета:
.glitch-image::before {
animation: glitch-hue 1s infinite;
}

@keyframes glitch-hue {
13% {
filter: hue-rotate(280deg); /* красный → синий */
}
18% {
filter: none; /* обратно */
}
/* ... и так далее */
}

Циклически сдвигает все цвета изображения.

Суть: берем картинку, клонируем её 2 раза через ::before и ::after, двигаем клоны и меняем им цвета)

Полный код можно глянуть здесь.
1🔥21👍1031
Генератор blob-фигур

Наверняка вы видели такие абстрактные фигуры с плавными формами — так называемые "блобы". Если вам нужно быстро создать такую фигуру для добавления в какой-нибудь блок страницы, советую Blobmaker.

Интерфейс максимально простой — два основных параметра:
■ Complexity (сложность) — определяет количество опорных точек, из которых строится форма.
■ Contrast (контраст) — задает разницу между точками, влияя на «дикость» формы.

Нажимаете на кнопку с кубиком 🎲, пока не найдете нужную форму, и скачиваете её, как SVG или копируете код прямо в буфер обмена.

Еще один годный сервис в нашу копилку)
👍24🔥742
Современный способ задавать цвета с прозрачностью в CSS

Раньше для прозрачности приходилось использовать rgba(), добавляя альфа-канал:
/* зеленый с 50 % прозрачности */
.green-50 {
color: rgba(0, 128, 0, 0.5);
}


Но rgb() давно умеет работать с альфа-каналом:
/* зеленый с 50 % прозрачности */
.green-50 {
color: rgb(0, 128, 0, 0.5);
}


И еще удобнее синтаксис через пробелы:
.green-50 {
color: rgb(0 128 0 / 0.5);
/* или */
color: rgb(0 128 0 / 50%);
}


Читается легче и отлично сочетается с CSS-переменными:
:root {
--primary: 0 128 0;
}

.green-50 {
color: rgb(var(--primary) / 50%);
}

.green-30 {
color: rgb(var(--primary) / 30%);
}


Если у вас есть цвет в формате #008000, то прозрачность можно добавить так:
.rgb-green-50 {
color: rgb(from #008000 r g b / 0.5);
}


Поддержку CSS Relative color syntax можно глянуть здесь - https://caniuse.com/css-relative-colors
👍24🔥731
Градиентный разделитель между секциями

При создании лендингов, часто нужно как-то красиво отделить один блок (секцию) от другого. Давайте сегодня разберем, как сделать плавный переход с полосами затухающих цветов.

HTML:
<section class="section-red">
<!-- Контент первой секции -->
</section>

<!-- Разделитель -->
<div class="section-divider"></div>

<section class="section-white">
<!-- Контент второй секции -->
</section>

Здесь две секции и пустой div для разделителя.

Стили блоков разбирать не будем, перейдем сразу к разделителю:
.section-divider {
position: relative;
height: 54px; /* Высота градиентной зоны */
overflow: hidden;
}


Фиксированная высота (3 полосы по 18px) и относительное позиционирование для работы с псевдоэлементами.

Создаём полосы:
.section-divider::before {
content: "";
position: absolute;
inset: 0;
background: linear-gradient(
to bottom,
#f87171 0px, /* светло-красная полоса */
#f87171 18px,
#fecaca 18px, /* ещё светлее */
#fecaca 36px,
#fef2f2 36px, /* почти белая */
#fef2f2 54px
);
}

linear-gradient создаёт градиент сверху вниз.
■ Каждая пара значений задаёт одну полосу (начало и конец).
■ Полосы по 18px каждая, цвета от красного постепенно переходят к почти белому.
inset: 0 — псевдоэлемент растягивается на весь родитель.

Собственно, все, стильно, модно, молодежно)

Пример можно глянуть здесь.
👍16🔥82
Библиотека иконок на чистом CSS

Если вы ищете легкие и кастомизируемые решения для иконок, то обратите внимание на CSS*GG.

Это библиотека иконок (open-source), в которой более 700 иконок реализованных в основном на чистом CSS.

Иконки доступны в нескольких форматах: чистый CSS, SVG и даже готовые пакеты для React.

Простое подключение, для конкретной иконки (например search) копируем CSS:
.gg-search {
box-sizing: border-box;
position: relative;
display: block;
transform: scale(var(--ggs, 1));
width: 16px;
height: 16px;
border: 2px solid;
border-radius: 100%;
margin-left: -4px;
margin-top: -4px;
}
.gg-search::after {
content: "";
display: block;
box-sizing: border-box;
position: absolute;
border-radius: 3px;
width: 2px;
height: 8px;
background: currentColor;
transform: rotate(-45deg);
top: 10px;
left: 12px;
}


В HTML используем:
<i class="gg-search"></i>


Можно легко менять цвет, размер и т. п.

Неплохая альтернатива тяжёлым шрифтам вроде Font Awesome)
👍25🔥942
This media is not supported in your browser
VIEW IN TELEGRAM
Необычный hover-эффект для изображений

Нашел один любопытный ховер-эффект для карточек с изображениями — раньше вроде бы не встречал. Выглядит так, будто картинка начинает «рассыпаться» в стороны при наведении. Делается это, конечно, немного геморно и не сказать, что код самый изящный, но если нужен нестандартный визуальный эффект, то можно попробовать)

HTML:
<div class="card">
<img class="card-front-image" src="..." />
<div class="card-faders">
<img class="card-fader" src="..." />
<!-- ещё 7 копий -->
</div>
</div>

card-front-image — основная картинка (всегда видна). card-faders — контейнер со скрытыми копиями, которые активируются при :hover.

CSS:
.card-faders {
height: 100%;
width: 100%;
position: absolute;
left: 0px;
top: 0px;
z-index: 1;
opacity: 0;
transition: opacity 1500ms;
}

Контейнер .card-faders растянут на всю карточку, копии изначально невидимы.

Активация при наведении:
.card:hover .card-faders {
opacity: 1;
}

При наведении на .card контейнер с копиями плавно проявляется за 1.5 секунды.

Распределение анимаций:
.card-fader:nth-child(odd) {
animation: fade-left 3s linear infinite;
}
.card-fader:nth-child(even) {
animation: fade-right 3s linear infinite;
}


Разделяем копии на две группы:
■ Нечётные (1-я, 3-я, 5-я, 7-я) получают анимацию fade-left — будут уходить влево.
■ Чётные (2-я, 4-я, 6-я, 8-я) получают анимацию fade-right — будут уходить вправо.

Волновой эффект:
.card-fader:is(:nth-child(3), :nth-child(4)) {
animation-delay: 750ms;
}
.card-fader:is(:nth-child(5), :nth-child(6)) {
animation-delay: 1500ms;
}
.card-fader:is(:nth-child(7), :nth-child(8)) {
animation-delay: 2250ms;
}

1-я и 2-я копии — стартуют сразу (задержки нет). 1-я идёт влево, 2-я вправо.
3-я и 4-я копии — стартуют через 750ms.
5-я и 6-я копии — стартуют через 1500ms.
7-я и 8-я копии — стартуют через 2250ms.

Анимация:
@keyframes fade-left {
from {
scale: 1;
translate: 0%;
opacity: 1;
}
to {
scale: 0.8;
translate: -30%;
opacity: 0;
}
}

И тоже самое для fade-right, только translate: 30%;

В итоге мы получаем эффект, который сложно назвать «чистым» или универсальным, но он точно выглядит необычно)

Упростить его можно с помощью JS, чтобы генерировать копии динамически и гибко настраивать параметры.

Результат можно найти здесь.
🔥18👍1254
This media is not supported in your browser
VIEW IN TELEGRAM
Flip-карточка на чистом CSS

Давайте сегодня разберём, как создать интерактивную flip-карточку, с переворотом по клику без JS.

HTML:
<label class="flip-card">
<input type="checkbox" class="flip-checkbox">
<div class="flip-inner">
<div class="card front">
Hello
</div>
<div class="card back">
Привет
</div>
</div>
</label>

Оборачиваем всё в label, чтобы при клике в любое место карточки checkbox менял своё состояние.

Сам checkbox скрываем:
.flip-checkbox {
display: none;
}


3D-контекст:
.flip-card {
perspective: 1000px;
}

perspective создаёт глубину для 3D-преобразований.

Основной механизм flip:
.flip-inner {
transform-style: preserve-3d;
transition: transform 0.6s;
}

.flip-checkbox:checked + .flip-inner {
transform: rotateY(180deg);
}

При клике на checkbox (через label) контейнер поворачивается на 180 градусов по оси Y.

Две стороны одной карточки:
.card {
position: absolute;
backface-visibility: hidden;
}

.card.back {
transform: rotateY(180deg);
}

Обе стороны абсолютно позиционированы. backface-visibility: hidden скрывает обратную сторону элемента. Задняя сторона изначально развёрнута на 180 градусов.

Идеально подходит для карточек с вопросами/ответами, изучения языков или просто интерактивных элементов)

Результат можно глянуть здесь.
1👍29🔥92🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
Интерактивная галерея без JS

Давайте сегодня разберем, как создать интерактивную галерею изображений с эффектом раскрытия по клику на чистом CSS.

HTML:
<input type="radio" name="slider" id="c1" checked>
<label class="card" for="c1"></label>

Основа галереи — группа радиокнопок, где каждая кнопка соответствует своему изображению. Атрибут name="slider" объединяет их в группу, позволяя выбрать только один элемент.

CSS:
input {
display: none;
}

.card {
width: 90px;
height: 420px;
transition: 0.6s cubic-bezier(.25,.8,.25,1);
}

■ Скрываем сами радиокнопки.
■ Задаем базовые размеры.
■ Применяем transition для плавности.

Изменение состояния:
input:checked + .card {
width: 520px;
filter: grayscale(0);
}

Когда радиокнопка активна, соседний лейбл (+) расширяется до 520px и становится цветным. Остальные карточки автоматически сжимаются.

Фоновые изображения:
[for="c1"] { background-image: url("..."); }

Селектор по атрибуту назначает каждой карточке своё изображение.

В итоге, радиокнопки управляют состоянием, псевдокласс :checked применяет стили, а transition делает всё плавным.

Пример можно найти здесь.
👍31🔥1211🗿2
This media is not supported in your browser
VIEW IN TELEGRAM
Hover-эффект карточек с выезжающим контентом

Сегодня разберем, как создать стильную карточку с контентом, который проявляется при наведении. Главная фишка здесь — игра с позиционированием и трансформацией.

HTML:
<div class="card">
<div class="img-box"><img src="..."></div>
<div class="content">
<h2>Leafs</h2>
<p>Lorem ipsum...</p>
<a href="#">Read More</a>
</div>
</div>

Карточка содержит блок с изображением и блок с контентом.

Базовые стили карточки:
.card {
position: relative;
width: 350px;
height: 300px;
transition: 0.5s;
}

.card:hover {
height: 400px;
}

position: relative нужен, чтобы абсолютно позиционировать картинку и контент внутри карточки.
■ При ховере карточка увеличивается на 100px, освобождая место под текст.

Блок с изображением:
.img-box {
position: absolute;
top: 20px;
width: 300px;
height: 220px;
overflow: hidden;
transition: 0.5s;
}
.card:hover .img-box {
top: -100px;
scale: 0.75;
}

■ Картинка вынесена в position: absolute, чтобы она могла выходить за границы карточки.
■ При наведении - картинка уезжает вверх за границы карточки и уменьшается до 75% размера.

Контент карточки:
.content {
position: absolute;
top: 252px;
overflow: hidden;
transition: 0.5s;
}

.card:hover .content {
top: 130px;
height: 250px;
}

Контент изначально обрезан overflow: hidden. При наведении поднимается вверх и раскрывается на полную высоту.

Весь эффект получается за счет абсолютного позиционирования блоков внутри карточки, изменения top и scale при наведении и плавный transition: 0.5s для анимации.

Простой, но эффектный способ оживить карточки на сайте)

Результат можно посмотреть здесь.
🔥40👍16
Интерактивная карта с 500 000+ телеграм-каналов

На днях товарищ скинул интересную карту телеграм-каналов, которую создали ребята из TGPages.

Я конечно, сразу пошел проверять,есть там наш "Формошлёп" или нет)

Все в порядке, канал на месте. Правда, его почему-то отнесли к тематике «Дизайн и креатив», странновато, конечно, но мб из-за того, что в описании указано, что мы здесь "шлёпаем формы и красим кнопки") Ну да ладно.

В общем, карта интересная и залипательная, выполнена в виде звездного неба, со своими галактиками и созвездиями, разбитыми по тематикам. Каждая звезда — отдельный канал с описанием и т.п.

Если интересно посмотреть на масштабы телеграм-каналов и найти что-нибудь новое — вот ссылка: https://tgpages.com/atlas/map/
🔥22👍64
This media is not supported in your browser
VIEW IN TELEGRAM
Анимированная градиентная рамка на CSS

Сегодня разберем красивый и модный визуальный эффект — анимированную градиентную рамку, которая красиво переливается.

HTML:
<div class="rainbow"></div>

Контейнер для карточки.

CSS для карточки:
.rainbow {
position: relative;
width: 400px;
height: 300px;
border-radius: 12px;
overflow: hidden;
}

Задаем размеры и скругляем углы. overflow: hidden — обрезаем все, что выходит за пределы контейнера.

Вращающийся слой:
.rainbow::before {
content: "";
position: absolute;
width: 200%;
height: 200%;
top: -50%;
left: -50%;
background: conic-gradient(red, orange, yellow, red);
animation: rotate 4s linear infinite;
}

Создаем градиент, который в 2 раза шире и выше самого родителя. Сдвигая его на top: -50%; left: -50%;, мы центрируем его относительно нашего .rainbow, а animation заставляет этот слой бесконечно вращаться.

Белый внутренний слой:
.rainbow::after {
content: "";
position: absolute;
inset: 10px;
background: white;
border-radius: 8px;
}

Накрываем вращающийся градиент почти полностью, оставляем видимыми только 10 пикселей по периметру — это и есть наша рамка.

Анимация:
@keyframes rotate {
to {
transform: rotate(360deg);
}
}

Простая анимация, которая вращает ::before на 360 градусов.

Такой эффект отлично подойдет для привлечения внимания к важным элементам на странице)

Результат, как всегда, здесь.
🔥15👍76