30 CSS Hover Effects 28 / 30
CSS Inline Word Swap Hover Effect
Text elements where hovering swaps out a word or phrase with an alternate, animated via clip-path, translateY, or opacity transitions — six swap styles.
This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.
The code
<div class="hv-28">
<p class="hv-28__label">Inline Word Swap — 6 Styles</p>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--slide-up" href="#" aria-label="Design Systems">
<span class="hv-28__word hv-28__word--out">Design</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Systems</span>
</a>
<span class="hv-28__style">Slide Up</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--clip" href="#" aria-label="Make it Work">
<span class="hv-28__word hv-28__word--out">Make it</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Work</span>
</a>
<span class="hv-28__style">Clip Reveal</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--fade" href="#" aria-label="Start Now">
<span class="hv-28__word hv-28__word--out">Start</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Now</span>
</a>
<span class="hv-28__style">Fade Cross</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--scale" href="#" aria-label="Build Fast">
<span class="hv-28__word hv-28__word--out">Build</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Fast</span>
</a>
<span class="hv-28__style">Scale In</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--blur" href="#" aria-label="Ship Ship">
<span class="hv-28__word hv-28__word--out">Ship</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Ship</span>
</a>
<span class="hv-28__style">Blur Swap</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--rotate" href="#" aria-label="Create Iterate">
<span class="hv-28__word hv-28__word--out">Create</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Iterate</span>
</a>
<span class="hv-28__style">Flip Down</span>
</div>
</div> <div class="hv-28">
<p class="hv-28__label">Inline Word Swap — 6 Styles</p>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--slide-up" href="#" aria-label="Design Systems">
<span class="hv-28__word hv-28__word--out">Design</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Systems</span>
</a>
<span class="hv-28__style">Slide Up</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--clip" href="#" aria-label="Make it Work">
<span class="hv-28__word hv-28__word--out">Make it</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Work</span>
</a>
<span class="hv-28__style">Clip Reveal</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--fade" href="#" aria-label="Start Now">
<span class="hv-28__word hv-28__word--out">Start</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Now</span>
</a>
<span class="hv-28__style">Fade Cross</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--scale" href="#" aria-label="Build Fast">
<span class="hv-28__word hv-28__word--out">Build</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Fast</span>
</a>
<span class="hv-28__style">Scale In</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--blur" href="#" aria-label="Ship Ship">
<span class="hv-28__word hv-28__word--out">Ship</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Ship</span>
</a>
<span class="hv-28__style">Blur Swap</span>
</div>
<div class="hv-28__row">
<a class="hv-28__link hv-28__link--rotate" href="#" aria-label="Create Iterate">
<span class="hv-28__word hv-28__word--out">Create</span>
<span class="hv-28__word hv-28__word--in" aria-hidden="true">Iterate</span>
</a>
<span class="hv-28__style">Flip Down</span>
</div>
</div>.hv-28,
.hv-28 *,
.hv-28 *::before,
.hv-28 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.hv-28 {
--swap-color: #7c6af7;
font-family: system-ui, sans-serif;
background: #0b0b0e;
padding: 3rem 2rem;
min-height: 100vh;
display: flex;
flex-direction: column;
gap: 2rem;
align-items: flex-start;
max-width: 600px;
margin: 0 auto;
}
.hv-28__label {
color: #444;
font-size: .72rem;
letter-spacing: .15em;
text-transform: uppercase;
align-self: center;
}
.hv-28__row {
display: flex;
align-items: center;
gap: 1.5rem;
}
.hv-28__style {
color: #3a3a50;
font-size: .68rem;
letter-spacing: .1em;
text-transform: uppercase;
min-width: 90px;
}
.hv-28__link {
text-decoration: none;
font-size: 1.6rem;
font-weight: 700;
position: relative;
display: inline-block;
overflow: hidden;
min-width: 8ch;
height: 1.2em;
line-height: 1.2;
vertical-align: bottom;
}
.hv-28__word {
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
white-space: nowrap;
line-height: inherit;
}
/* ── 1. Slide Up ── */
.hv-28__link--slide-up .hv-28__word--out { color: #ccc; transition: transform .3s cubic-bezier(.4,0,.2,1); }
.hv-28__link--slide-up .hv-28__word--in { color: var(--swap-color); transform: translateY(100%); transition: transform .3s cubic-bezier(.4,0,.2,1); }
.hv-28__link--slide-up:hover .hv-28__word--out { transform: translateY(-100%); }
.hv-28__link--slide-up:hover .hv-28__word--in { transform: translateY(0); }
/* ── 2. Clip Reveal ── */
.hv-28__link--clip .hv-28__word--out { color: #ccc; transition: clip-path .3s cubic-bezier(.4,0,.2,1); clip-path: inset(0 0 0 0); }
.hv-28__link--clip .hv-28__word--in { color: var(--swap-color); clip-path: inset(0 100% 0 0); transition: clip-path .3s cubic-bezier(.4,0,.2,1); }
.hv-28__link--clip:hover .hv-28__word--out { clip-path: inset(0 0 0 100%); }
.hv-28__link--clip:hover .hv-28__word--in { clip-path: inset(0 0 0 0); }
/* ── 3. Fade Cross ── */
.hv-28__link--fade .hv-28__word--out { color: #ccc; transition: opacity .25s; }
.hv-28__link--fade .hv-28__word--in { color: var(--swap-color); opacity: 0; transition: opacity .25s .1s; }
.hv-28__link--fade:hover .hv-28__word--out { opacity: 0; }
.hv-28__link--fade:hover .hv-28__word--in { opacity: 1; }
/* ── 4. Scale In ── */
.hv-28__link--scale .hv-28__word--out { color: #ccc; transition: opacity .25s, transform .25s; }
.hv-28__link--scale .hv-28__word--in { color: var(--swap-color); opacity: 0; transform: scale(.6); transition: opacity .3s .05s, transform .3s .05s cubic-bezier(.34,1.56,.64,1); }
.hv-28__link--scale:hover .hv-28__word--out { opacity: 0; transform: scale(1.3); }
.hv-28__link--scale:hover .hv-28__word--in { opacity: 1; transform: scale(1); }
/* ── 5. Blur Swap ── */
.hv-28__link--blur .hv-28__word--out { color: #ccc; transition: filter .3s, opacity .3s; }
.hv-28__link--blur .hv-28__word--in { color: var(--swap-color); filter: blur(8px); opacity: 0; transition: filter .3s .05s, opacity .3s .05s; }
.hv-28__link--blur:hover .hv-28__word--out { filter: blur(8px); opacity: 0; }
.hv-28__link--blur:hover .hv-28__word--in { filter: blur(0); opacity: 1; }
/* ── 6. Flip Down ── */
.hv-28__link--rotate { perspective: 300px; }
.hv-28__link--rotate .hv-28__word--out { color: #ccc; transition: transform .35s cubic-bezier(.4,0,.2,1), opacity .25s; transform-origin: bottom; }
.hv-28__link--rotate .hv-28__word--in { color: var(--swap-color); transform: rotateX(-90deg); transform-origin: top; opacity: 0; transition: transform .35s cubic-bezier(.4,0,.2,1) .05s, opacity .2s .05s; }
.hv-28__link--rotate:hover .hv-28__word--out { transform: rotateX(90deg); opacity: 0; }
.hv-28__link--rotate:hover .hv-28__word--in { transform: rotateX(0); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
.hv-28__word { transition: none !important; }
} .hv-28,
.hv-28 *,
.hv-28 *::before,
.hv-28 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.hv-28 {
--swap-color: #7c6af7;
font-family: system-ui, sans-serif;
background: #0b0b0e;
padding: 3rem 2rem;
min-height: 100vh;
display: flex;
flex-direction: column;
gap: 2rem;
align-items: flex-start;
max-width: 600px;
margin: 0 auto;
}
.hv-28__label {
color: #444;
font-size: .72rem;
letter-spacing: .15em;
text-transform: uppercase;
align-self: center;
}
.hv-28__row {
display: flex;
align-items: center;
gap: 1.5rem;
}
.hv-28__style {
color: #3a3a50;
font-size: .68rem;
letter-spacing: .1em;
text-transform: uppercase;
min-width: 90px;
}
.hv-28__link {
text-decoration: none;
font-size: 1.6rem;
font-weight: 700;
position: relative;
display: inline-block;
overflow: hidden;
min-width: 8ch;
height: 1.2em;
line-height: 1.2;
vertical-align: bottom;
}
.hv-28__word {
display: block;
position: absolute;
left: 0;
top: 0;
width: 100%;
white-space: nowrap;
line-height: inherit;
}
/* ── 1. Slide Up ── */
.hv-28__link--slide-up .hv-28__word--out { color: #ccc; transition: transform .3s cubic-bezier(.4,0,.2,1); }
.hv-28__link--slide-up .hv-28__word--in { color: var(--swap-color); transform: translateY(100%); transition: transform .3s cubic-bezier(.4,0,.2,1); }
.hv-28__link--slide-up:hover .hv-28__word--out { transform: translateY(-100%); }
.hv-28__link--slide-up:hover .hv-28__word--in { transform: translateY(0); }
/* ── 2. Clip Reveal ── */
.hv-28__link--clip .hv-28__word--out { color: #ccc; transition: clip-path .3s cubic-bezier(.4,0,.2,1); clip-path: inset(0 0 0 0); }
.hv-28__link--clip .hv-28__word--in { color: var(--swap-color); clip-path: inset(0 100% 0 0); transition: clip-path .3s cubic-bezier(.4,0,.2,1); }
.hv-28__link--clip:hover .hv-28__word--out { clip-path: inset(0 0 0 100%); }
.hv-28__link--clip:hover .hv-28__word--in { clip-path: inset(0 0 0 0); }
/* ── 3. Fade Cross ── */
.hv-28__link--fade .hv-28__word--out { color: #ccc; transition: opacity .25s; }
.hv-28__link--fade .hv-28__word--in { color: var(--swap-color); opacity: 0; transition: opacity .25s .1s; }
.hv-28__link--fade:hover .hv-28__word--out { opacity: 0; }
.hv-28__link--fade:hover .hv-28__word--in { opacity: 1; }
/* ── 4. Scale In ── */
.hv-28__link--scale .hv-28__word--out { color: #ccc; transition: opacity .25s, transform .25s; }
.hv-28__link--scale .hv-28__word--in { color: var(--swap-color); opacity: 0; transform: scale(.6); transition: opacity .3s .05s, transform .3s .05s cubic-bezier(.34,1.56,.64,1); }
.hv-28__link--scale:hover .hv-28__word--out { opacity: 0; transform: scale(1.3); }
.hv-28__link--scale:hover .hv-28__word--in { opacity: 1; transform: scale(1); }
/* ── 5. Blur Swap ── */
.hv-28__link--blur .hv-28__word--out { color: #ccc; transition: filter .3s, opacity .3s; }
.hv-28__link--blur .hv-28__word--in { color: var(--swap-color); filter: blur(8px); opacity: 0; transition: filter .3s .05s, opacity .3s .05s; }
.hv-28__link--blur:hover .hv-28__word--out { filter: blur(8px); opacity: 0; }
.hv-28__link--blur:hover .hv-28__word--in { filter: blur(0); opacity: 1; }
/* ── 6. Flip Down ── */
.hv-28__link--rotate { perspective: 300px; }
.hv-28__link--rotate .hv-28__word--out { color: #ccc; transition: transform .35s cubic-bezier(.4,0,.2,1), opacity .25s; transform-origin: bottom; }
.hv-28__link--rotate .hv-28__word--in { color: var(--swap-color); transform: rotateX(-90deg); transform-origin: top; opacity: 0; transition: transform .35s cubic-bezier(.4,0,.2,1) .05s, opacity .2s .05s; }
.hv-28__link--rotate:hover .hv-28__word--out { transform: rotateX(90deg); opacity: 0; }
.hv-28__link--rotate:hover .hv-28__word--in { transform: rotateX(0); opacity: 1; }
@media (prefers-reduced-motion: reduce) {
.hv-28__word { transition: none !important; }
}How this works
Each link wraps two elements: the original word and the swap word. Both are stacked with position:absolute. CSS transitions on clip-path or translateY animate the outgoing word away and the incoming word in on hover. No JavaScript needed.
Customize
- Swap the content in data-swap spans, change --swap-color for the replacement word accent, adjust transition-duration for faster or slower swap. Combine with letter-spacing transitions for a "slot machine" feel.
Watch out for
- The link needs a fixed min-width (or width from the longest word) to prevent layout shift between short and long swap words.
- clip-path: inset(0 0 100% 0) is the cleanest way to hide inline text — height: 0 causes layout reflow.
- Both spans need aria-hidden on the swap span, and the original span needs aria-label on the link for screen reader parity.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| ✅ | ✅ | ✅ | ✅ |
clip-path on inline elements requires display:block or inline-block.
More from 30 CSS Hover Effects
CSS Spotlight Card Hover EffectCSS Slide Reveal Card Hover EffectCSS Stack Lift Card Hover EffectCSS Zoom Pan Image Hover EffectCSS Color Channel Split Hover EffectCSS Duotone Image Hover EffectCSS Curtain Reveal Image Hover EffectCSS Ken Burns Image Hover EffectCSS Image Tilt Depth Hover EffectCSS Underline Slide Nav Hover EffectCSS Highlight Fill Nav Hover EffectCSS Strikethrough Hover Link Effect
View the full collection →