Hover Weight
Pure CSS transition from light to black on hover — weight, spacing, and color animate simultaneously, with zero JavaScript.
You'll get access to the interactive demo with a free account.
This effect is part of Effect.Labs — 811 vanilla effects, some free, some premium. Text has 56 effects, including 4 free. Explore the category →
3 usage examples



How it works
The effect relies entirely on the :hover pseudo-class and the CSS transition property. No JavaScript is needed: each .vf-hover-word declares transition: font-weight .3s, letter-spacing .3s, color .3s, letting the browser interpolate all three properties simultaneously as the pointer enters the element.
The weight transition from 300 (Light) to 900 (Black) exploits the wght axis of the Inter variable font. With a static font, font-weight would snap to the nearest threshold; with Inter (a variable font), the browser continuously interpolates along the weight axis for a smooth animation.
Letter-spacing simultaneously shifts from 4px (expanded) to -1px (tight). This visually compensates for the extra horizontal width that heavier weights introduce in a variable font — condensing the spacing keeps the word's perceived footprint balanced. Color switches from white #fff to violet #8b5cf6, marking the active state without relying on underlines or highlights.
All three properties animate at the same .3s duration, producing a unified visual movement. The structure is minimal: a .vf-hover-scene centered flex column and <span class="vf-hover-word"> elements for each interactive word.
Accessibility
- prefers-reduced-motion: not implemented — no
@media (prefers-reduced-motion)rule is present; transitions always run, including for users who have enabled motion reduction in their OS. Add the rule if the effect is used on a large surface or many words. - The effect uses
:hoveronly — no:focusor:focus-visiblestate is styled in the code. Keyboard-navigating users will not see the weight change. If the effect carries meaning (not purely decorative), add:focus-visiblealongside:hover. - Color contrast: white
#fffon dark background#0a0a0f→ ratio ≈ 19.8:1 (WCAG AAA). Violet#8b5cf6on#0a0a0f→ ratio ≈ 4.7:1 (WCAG AA). Both states pass AA. - No ARIA attributes are present in the base code. If the words form a navigation or menu, wrap them in a semantic
<nav aria-label="…">or<ul>. - The effect is purely visual and decorative in its base form — no modal, no focus trap, no JavaScript focus management.
Browser compatibility
Requires CSS Transitions (universal) and a variable font for smooth weight animation. Inter is available via Google Fonts or locally.
Without a variable font loaded, the <code>font-weight</code> transition snaps to available thresholds (300 → 400 → 700 → 900) instead of animating continuously. The effect still works — weight changes on hover, only the interpolation smoothness is absent. Without CSS Transitions (IE 9 and earlier), the style change is instant but still visible.
The code
HTML structure to paste into your page (CSS + JS available with a premium account):
<div class="vf-hover-scene">
<span class="vf-hover-word">WORD 1</span>
<span class="vf-hover-word">WORD 2</span>
<span class="vf-hover-word">WORD 3</span>
<!-- Optional: -->
<span class="vf-hover-label">Hover the words</span>
</div>
Full HTML + CSS + JS, copy-paste ready — with hundreds of premium effects.
Customize
Options passed to the API or data-* attributes:
| Option / property | Default | Effect |
|---|---|---|
| font-weight (normal state) | 300 | Starting weight. 100–300 = very light, creates strong contrast with 900. 400 = regular, moderate contrast. |
| font-weight (:hover state) | 900 | Target weight on hover. 700 = classic Bold, 900 = maximum Black. Only visible with a variable font loaded. |
| letter-spacing (normal state) | 4px | Initial spacing. The wider it is, the more the hover compression feels dramatic. |
| letter-spacing (:hover state) | -1px | Spacing on hover. -1px to -3px visually condenses the heavy word; stay above -3px for readability. |
| color (:hover state) | #8b5cf6 | Word color on hover. Replace with your accent color to match your design system. |
| transition | .3s | Duration for all 3 simultaneous transitions (weight, spacing, color). 0.2s = dry and snappy, 0.5s = slow and smooth. |
| font-size (on .vf-hover-word) | 2rem | Base size. The larger the size, the more perceivable the weight animation. Go 4–5rem for poster use. |
| gap (on .vf-hover-scene) | 12px | Vertical spacing between words. Increase for breathing room, reduce for a dense list. |
FAQ
wght axis of the typeface. With a static font (legacy Google Fonts or a non-variable custom font), the transition snaps to available thresholds (400, 700…). To guarantee smooth animation, load Inter as a variable font: @import url('https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap').vf-hover-word class to each target <a>, <span>, or <li>. The effect only touches elements with that class. For smaller nav items, override font-size and the letter-spacing / font-weight values via a more specific selector (nav .vf-hover-word).display:flex; flex-direction:column container to avoid the issue.