SolutionsCase StudiesAI ToolsResourcesAboutContact
Get Your Free AI Automation Audit Book a Free 30-Minute Strategy Call
Playground~/frontend Open editor

~/css/card-hover-effects

7 CSS Card Hover Effects

7 Pure CSSPublished 2026-10-05Free · no sign-up

Seven hover effects for clickable cards: a blog card whose image zooms and title underlines, a gradient border that fades in, an arrow that slides into the corner, a description that expands, paper layers that spread behind the card, a background that shifts tone and an option card that dips when pressed.

01. Blog Card: Image Zoom, Title Underline

CardHover

A blog card where hover zooms the cover image and underlines the title, two cues that the whole card is clickable. The title is the link, stretched over the card, and the underline is a native text-decoration so it wraps across lines.

View code
<article class="chv1"><div class="fr"><div class="im" aria-hidden="true"></div></div><p class="k">Guides · 6 min</p><h3><a href="#post">How to price handmade products</a></h3></article>
.chv1 { position: relative; width: 260px; max-width: 100%; font-family: Inter, system-ui, sans-serif; }
.chv1 .fr { overflow: hidden; border-radius: 14px; }
.chv1 .im { aspect-ratio: 16 / 10; background: linear-gradient(135deg, #fef3c7, #fdba74 50%, #ea580c); transition: transform .5s ease; }
.chv1 .k { margin: 10px 0 4px; color: #b54708; font-size: 12px; font-weight: 700; }
.chv1 h3 { margin: 0; font-size: 17px; line-height: 1.3; }
.chv1 a { color: #101828; text-decoration: underline transparent; text-underline-offset: 3px; transition: text-decoration-color .25s; }
.chv1 a::after { content: ""; position: absolute; inset: 0; }
.chv1:hover .im, .chv1:has(a:focus-visible) .im { transform: scale(1.06); }
.chv1:hover a, .chv1 a:focus-visible { text-decoration-color: #101828; }
.chv1 a:focus-visible { outline: none; } .chv1:has(a:focus-visible) { outline: 3px solid #84adff; outline-offset: 6px; border-radius: 14px; }
@media (prefers-reduced-motion: reduce) { .chv1 .im { transition: none; } }

02. Gradient Border Reveal

CardBorder

A plain dark card whose border fades into a gradient on hover. The gradient border is always there, on a masked pseudo-element at zero opacity; hover only changes opacity, which is far cheaper than swapping backgrounds.

View code
<a class="chv2" href="#api"><b>API access</b><span>Build on top of your store data.</span></a>
.chv2 { position: relative; display: grid; gap: 4px; width: 260px; max-width: 100%; box-sizing: border-box; padding: 20px; border: 1px solid #263048; border-radius: 16px; background: #111727; color: #94a3b8; font: 14px Inter, system-ui, sans-serif; text-decoration: none; }
.chv2 b { color: #f1f5f9; font-size: 16px; }
.chv2::before { content: ""; position: absolute; inset: -1px; padding: 1px; border-radius: inherit; background: linear-gradient(135deg, #22d3ee, #a855f7, #f43f5e); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask: linear-gradient(#000 0 0) content-box exclude, linear-gradient(#000 0 0); opacity: 0; transition: opacity .3s; pointer-events: none; }
.chv2:hover::before, .chv2:focus-visible::before { opacity: 1; }
.chv2:focus-visible { outline: 2px solid #a855f7; outline-offset: 4px; }

03. Corner Arrow Appears

CardIcon

A small arrow slides in diagonally from the top right corner on hover, a modern cue for cards that link elsewhere. The arrow is aria-hidden decoration and the card's text is the link name.

View code
<a class="chv3" href="#case"><span class="ar" aria-hidden="true">↗</span><b>Case study</b><span>How Linea doubled repeat orders.</span></a>
.chv3 { position: relative; display: grid; gap: 4px; width: 260px; max-width: 100%; box-sizing: border-box; padding: 20px 46px 20px 20px; border: 1px solid #e4e7ec; border-radius: 16px; background: #fff; color: #475467; font: 14px Inter, system-ui, sans-serif; text-decoration: none; overflow: hidden; transition: border-color .25s; }
.chv3 b { color: #101828; font-size: 16px; }
.chv3 .ar { position: absolute; top: 14px; right: 14px; display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%; background: #101828; color: #fff; font-size: 14px; transform: translate(14px, -14px); opacity: 0; transition: transform .3s ease, opacity .3s; }
.chv3:hover, .chv3:focus-visible { border-color: #101828; }
.chv3:hover .ar, .chv3:focus-visible .ar { transform: none; opacity: 1; }
.chv3:focus-visible { outline: 3px solid #84adff; outline-offset: 3px; }
@media (hover: none) { .chv3 .ar { transform: none; opacity: 1; } }

04. Description Expands on Hover

CardReveal

The card shows a title and a teaser; hover or focus reveals a longer description by animating grid rows from 0fr to 1fr. The full text is always in the DOM, so screen readers get it whatever the visual state.

View code
<a class="chv4" href="#course"><b>CSS layout course</b><span class="tz">Six lessons, one weekend.</span><span class="more"><span>Grid, flexbox, container queries and subgrid, each with exercises and a final project.</span></span></a>
.chv4 { display: grid; gap: 4px; width: 260px; max-width: 100%; box-sizing: border-box; padding: 20px; border-radius: 16px; background: linear-gradient(160deg, #1e3a8a, #0f172a); color: #bfdbfe; font: 14px/1.5 Inter, system-ui, sans-serif; text-decoration: none; }
.chv4 b { color: #fff; font-size: 17px; }
.chv4 .more { display: grid; grid-template-rows: 0fr; transition: grid-template-rows .35s ease; }
.chv4 .more span { min-height: 0; overflow: hidden; color: #dbeafe; }
.chv4:hover .more, .chv4:focus-visible .more { grid-template-rows: 1fr; }
.chv4:focus-visible { outline: 3px solid #93c5fd; outline-offset: 3px; }
@media (hover: none) { .chv4 .more { grid-template-rows: 1fr; } }
@media (prefers-reduced-motion: reduce) { .chv4 .more { transition: none; } }

05. Shadow Layers Spread

CardDepth

On hover, two paper-like layers spread out from behind the card, as if a stack of pages fanned slightly. They are pseudo-elements that sit behind the card through isolation and move with small rotations and offsets.

View code
<a class="chv5" href="#notes"><b>Meeting notes</b><span>12 documents</span></a>
.chv5 { position: relative; isolation: isolate; display: grid; gap: 4px; width: 220px; max-width: 100%; box-sizing: border-box; padding: 20px; border: 1px solid #e4e7ec; border-radius: 14px; background: #fff; color: #475467; font: 14px Inter, system-ui, sans-serif; text-decoration: none; }
.chv5 b { color: #101828; font-size: 16px; }
.chv5::before, .chv5::after { content: ""; position: absolute; inset: 0; z-index: -1; border: 1px solid #e4e7ec; border-radius: inherit; background: #f9fafb; transition: transform .3s ease; }
.chv5:hover::before, .chv5:focus-visible::before { transform: translate(8px, 6px) rotate(3deg); }
.chv5:hover::after, .chv5:focus-visible::after { transform: translate(-6px, 8px) rotate(-3deg); }
.chv5:focus-visible { outline: 3px solid #84adff; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .chv5::before, .chv5::after { transition: none; } }

06. Background Shift and Icon Lift

CardColour

A feature card whose background gradient slides to reveal a brighter tone while its icon lifts and turns slightly. Both changes are on hover and focus, and the card's contrast passes in both states because the text is white on dark tones throughout.

View code
<a class="chv6" href="#automation"><span class="ic" aria-hidden="true">⚙</span><b>Automation</b><span>Rules that run while you sleep.</span></a>
.chv6 { display: grid; gap: 6px; width: 250px; max-width: 100%; box-sizing: border-box; padding: 20px; border-radius: 18px; background: linear-gradient(135deg, #1e1b4b 0 50%, #4338ca) 0 0 / 200% 200%; color: #c7d2fe; font: 14px Inter, system-ui, sans-serif; text-decoration: none; transition: background-position .5s ease; }
.chv6 b { color: #fff; font-size: 17px; }
.chv6 .ic { display: inline-grid; place-items: center; width: 40px; height: 40px; border-radius: 12px; background: rgba(255,255,255,.12); color: #fff; font-size: 20px; transition: transform .4s cubic-bezier(.2,.8,.2,1); }
.chv6:hover, .chv6:focus-visible { background-position: 100% 100%; }
.chv6:hover .ic, .chv6:focus-visible .ic { transform: translateY(-4px) rotate(-12deg); }
.chv6:focus-visible { outline: 3px solid #a5b4fc; outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .chv6, .chv6 .ic { transition: none; } }

07. Pressable Card

CardActive

A selectable option card that dips slightly when pressed and lifts back on release, giving tactile feedback on touch screens where hover does not exist. It is a label for a radio button, so selection works with the keyboard too.

View code
<fieldset class="chv7"><legend>Delivery</legend><label><input type="radio" name="chv7" checked><b>Standard</b><span>3-5 days · Free</span></label><label><input type="radio" name="chv7"><b>Express</b><span>Next day · $9</span></label></fieldset>
.chv7 { display: grid; gap: 8px; width: 260px; max-width: 100%; min-inline-size: 0; margin: 0; padding: 0; border: 0; font: 14px Inter, system-ui, sans-serif; }
.chv7 legend { margin-bottom: 6px; padding: 0; color: #101828; font-weight: 800; }
.chv7 label { display: grid; grid-template-columns: auto 1fr; column-gap: 10px; padding: 14px; border: 1px solid #d0d5dd; border-radius: 12px; background: #fff; color: #475467; cursor: pointer; transition: transform .12s ease, box-shadow .2s; }
.chv7 input { grid-row: span 2; align-self: center; margin: 0; accent-color: #101828; }
.chv7 b { color: #101828; }
.chv7 label:hover { box-shadow: 0 6px 14px -8px rgba(16,24,40,.35); }
.chv7 label:active { transform: scale(.98); }
.chv7 label:has(:checked) { border-color: #101828; box-shadow: 0 0 0 1px #101828; }
.chv7 label:has(:focus-visible) { outline: 3px solid #84adff; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .chv7 label { transition: none; } .chv7 label:active { transform: none; } }

About these CSS Card Hover Effects

One link per card

Make the card's title the link and stretch it with a pseudo-element, or make the whole card a single link if it has no other controls. Never nest links or buttons inside another link.

Show focus on the card

When the title link is focused, use :has(a:focus-visible) on the card to outline the whole card, so keyboard users see the same target that mouse users hover.

Prepare the effect, toggle opacity

Expensive styling such as a masked gradient border can sit on a pseudo-element at zero opacity and fade in on hover. Toggling opacity is cheaper than recalculating backgrounds.

Touch needs feedback too

Without hover, a pressed state matters. A slight scale on :active confirms the tap on phones.

Frequently asked questions

How is this page different from animated cards?

Animated cards covers entrances and reveals; this page is about the hover and press response of link cards.

Will the stretched link break text selection?

It covers the card, so text cannot be selected by dragging. That is usually fine for short card text.

Can I combine two effects?

Yes, for example zoom and arrow. Keep the total motion small.