fix: rewrite gradient border with @property CSS angle animation

Pure CSS approach: @property --border-angle + conic-gradient on border-box.
No extra elements, no overflow issues, no JS animation.
Smooth rotation via CSS Houdini custom property animation.
This commit is contained in:
Fringg
2026-02-25 08:48:48 +03:00
parent e95db23573
commit d8b83ccdb8
3 changed files with 39 additions and 22 deletions

View File

@@ -17,28 +17,14 @@ export function HoverBorderGradient({
return (
<Tag
className={cn(
'group relative flex items-center justify-center overflow-hidden rounded-xl p-[1.5px]',
'hover-border-gradient group flex items-center justify-center rounded-xl text-sm font-medium text-white',
containerClassName,
)}
{...props}
>
{/* Rotating conic gradient — pure CSS transform, always smooth */}
<div
className="absolute inset-[-50%] z-0 animate-border-spin"
style={{
background:
'conic-gradient(from 0deg, transparent 0%, transparent 40%, rgb(var(--color-accent-400)) 50%, transparent 60%, transparent 100%)',
}}
/>
{/* Inner content */}
<div
className={cn(
'relative z-10 w-auto rounded-[inherit] bg-dark-900 px-4 py-2.5 text-sm font-medium text-white transition-colors duration-300 group-hover:bg-dark-850',
className,
)}
>
<span className={cn('relative z-10 flex items-center justify-center', className)}>
{children}
</div>
</span>
</Tag>
);
}

View File

@@ -2,6 +2,42 @@
@tailwind components;
@tailwind utilities;
/* Animated gradient border — @property enables CSS-only angle animation */
@property --border-angle {
syntax: '<angle>';
initial-value: 0deg;
inherits: false;
}
.hover-border-gradient {
--_bg: rgb(var(--color-dark-900));
--_accent: rgb(var(--color-accent-400));
border: 1.5px solid transparent;
padding: 10px 16px;
background:
linear-gradient(var(--_bg), var(--_bg)) padding-box,
conic-gradient(
from var(--border-angle),
var(--_accent) 0%,
transparent 25%,
transparent 75%,
var(--_accent) 100%
)
border-box;
animation: border-rotate 3s linear infinite;
transition: box-shadow 0.3s ease;
}
.hover-border-gradient:hover {
box-shadow: 0 0 16px rgba(var(--color-accent-400), 0.3);
}
@keyframes border-rotate {
to {
--border-angle: 360deg;
}
}
/* Aceternity UI background CSS variables */
:root {
--blue-500: #3b82f6;

View File

@@ -173,13 +173,8 @@ export default {
'move-horizontal': 'moveHorizontal 40s ease infinite',
'move-in-circle-fast': 'moveInCircle 20s ease infinite',
'spotlight-ace': 'spotlightAce 2s ease 0.75s 1 forwards',
'border-spin': 'borderSpin 3s linear infinite',
},
keyframes: {
borderSpin: {
'0%': { transform: 'rotate(0deg)' },
'100%': { transform: 'rotate(360deg)' },
},
fadeIn: {
'0%': { opacity: '0' },
'100%': { opacity: '1' },