Как с помощью CSS реализовать градиентную рамку (border) для кнопки, которая плавно переливается?
Реализовать градиентную рамку (border) для кнопки в CSS можно несколькими способами. Рассмотрим наиболее популярные и гибкие подходы.
## Способ 1: border-image с градиентом
Самый простой способ — использовать свойство `border-image`:
css
.button {
border: 3px solid transparent;
border-image: linear-gradient(45deg, #ff6ec4, #7873f5, #4adede) 1;
padding: 10px 24px;
font-size: 16px;
cursor: pointer;
}
Однако у этого метода есть ограничение: `border-image` не совместим с `border-radius`, то есть скруглённые углы работать не будут.
## Способ 2: Псевдоэлемент ::before (рекомендуемый)
Этот метод позволяет сочетать градиентную рамку со скруглёнными углами:
css
.button {
position: relative;
background: #fff;
border: none;
border-radius: 12px;
padding: 12px 28px;
font-size: 16px;
cursor: pointer;
z-index: 0;
}
.button::before {
content: »;
position: absolute;
inset: -3px;
border-radius: 14px;
background: linear-gradient(45deg, #ff6ec4, #7873f5, #4adede, #ff6ec4);
background-size: 300% 300%;
z-index: -1;
animation: gradientShift 3s linear infinite;
}
@keyframes gradientShift {
0% { background-position: 0% 50%; }
50% { background-position: 100% 50%; }
100% { background-position: 0% 50%; }
}
Здесь псевдоэлемент `::before` создаёт фон чуть больше кнопки (через `inset: -3px`), имитируя рамку. Анимация `background-position` заставляет градиент «переливаться».
## Способ 3: Анимация через @property (современный подход)
С помощью CSS Houdini и `@property` можно анимировать угол градиента напрямую:
css
@property —angle {
syntax: »;
initial-value: 0deg;
inherits: false;
}
.button::before {
background: conic-gradient(from var(—angle), #ff6ec4, #7873f5, #4adede, #ff6ec4);
animation: rotate 3s linear infinite;
}
@keyframes rotate {
to { —angle: 360deg; }
}
Этот способ создаёт эффект вращающегося градиента вокруг кнопки — очень эффектно.
## Советы по оптимизации
— Используйте `will-change: background-position` или `will-change: transform` для плавной анимации на GPU.
— Убедитесь, что `z-index` псевдоэлемента ниже содержимого кнопки.
— Для тёмного фона задайте `background` кнопки в тот же цвет, что и страница.
— Проверяйте поддержку `@property` через caniuse.com — на старых браузерах нужен фолбэк.
Таким образом, наиболее универсальный и красивый способ — метод с псевдоэлементом `::before` и анимацией `background-position`, который работает во всех современных браузерах и поддерживает `border-radius`.
