Underline Expand
A 3 px indigo-to-violet gradient line grows from the centre of the element to 60% width in 0.3s on hover — pure CSS, ::after pseudo-element.
Updated
This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Hover has 48 effects, including 5 free. Explore the category →
3 usage examples



How it works
The .fx-0347-root wrapper centres a 200 px button. An absolutely-positioned ::after pseudo-element carries the line: height: 3px, width: 0 at rest, bottom: 1rem (the --space-4 variable). left: 50% with transform: translateX(-50%) ensures the line always starts exactly at the centre, regardless of element width. On hover, width: 60% animates over 0.3 s. The gradient (--gradient-primary: indigo 0%, violet 50%, pink 100%) stays proportional so its full range is visible even at a narrow width.
:focus-visible triggers the same line expansion as hover, with an indigo outline added. Pure CSS, no JavaScript. Under reduced motion, the transition is disabled but the line appears at its final width instantly — state feedback guaranteed. The effect suits links, tabs and short labels; for a line that starts from one side rather than the centre, remove left: 50% and transform and use left: 0.
Accessibility
- Reduced motion: under
prefers-reduced-motion: reduce, the transition is disabled. The line appears at 60% width instantly on hover and focus. - Keyboard: the element is a natively focusable
<button>.:focus-visibleexpands the line and adds a 2 px outline to signal keyboard focus. - Touch: a tap generally activates the CSS hover state on mobile. The effect clears on the next focus change.
- Legibility: the line is positioned at
bottom: 1remof the element, not under the text. On a tall element (e.g. 200 px), there is a gap between text and line — adjustbottomto bring it closer to the text if needed.
Browser compatibility
Pure CSS. Properties: ::after, width (transition), transform: translateX, linear gradient, :focus-visible. Verified in Chromium and Firefox: centred line, expansion visible, two independent copies, 0 errors.
Without :focus-visible (before 2021), keyboard focus does not trigger the line expansion.
The code
HTML structure to paste into your page (the CSS + JS come with your purchase):
<div class="fx-0347-root">
<button class="uln-box uln-line" type="button">
<span>Your text</span>
</button>
</div>
One-time payment, no subscription — the code is yours forever
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
Final line width (CSS — 60%) |
60% of element | 80% or 100% for a bolder line; 40% for a more subtle one. calc(100% - 2rem) leaves a margin on both sides. |
Line thickness (CSS — height: 3px) |
3 px | 1 px for a hairline; 4–5 px for a bold underline. |
Gradient (CSS — --gradient-primary) |
indigo → violet → pink | Replace with a solid colour (background: #6366f1) for maximum restraint, or with another gradient. |
Vertical position (CSS — bottom: var(--space-4)) |
1 rem from bottom | bottom: 4px pins the line to the bottom edge; bottom: 50% centres it vertically (typographic underline style). |
Direction (CSS — remove left: 50% and transform) |
grows from centre | Replacing with left: 0 gives a line that grows from the left edge — more conventional for navigation links. |
FAQ
left: 50% and transform: translateX(-50%) from ::after, and add left: 0. The line will grow from the left edge toward the right.bottom on ::after. To align the line precisely under the text baseline, use bottom: auto; top: calc(50% + 0.7em), adjusting the offset for your font size.background alongside width and change the gradient in the :hover/:focus-visible rule. Browsers interpolate gradients from Chrome 128 / Firefox 128 — on older versions, use two solid colours instead.