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

~/css/cards

8 CSS Cards

7 Pure CSS1 with JSPublished 2026-10-03Free · no sign-up

Card layouts for the places cards actually get used: a product card for a store, a pricing plan, a team profile, a blog teaser, a dashboard metric, a flip card and a dismissible notice. Each one is plain HTML and CSS, built to sit in a grid without breaking when the text gets longer.

01. Product Card with Quick Add

Pure CSS

An e-commerce product card with an image area, a sale badge, price with the old price struck through, and a full-width add-to-cart button. The image keeps a fixed aspect ratio so the grid does not jump while photos load, and the whole card lifts slightly on hover.

View code
<article class="ttc-product">
  <div class="ttc-product-img"><span class="ttc-badge">-20%</span></div>
  <div class="ttc-product-body">
    <p class="ttc-product-cat">Home office</p>
    <h3>Oak Desk Organiser</h3>
    <p class="ttc-price"><strong>$39.00</strong> <s>$49.00</s></p>
    <button type="button">Add to cart</button>
  </div>
</article>
.ttc-product {
  width: 260px;
  overflow: hidden;
  border-radius: 16px;
  background: #fff;
  box-shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 12px 32px -16px rgba(15, 23, 42, .25);
  font-family: Inter, system-ui, sans-serif;
  transition: transform .25s ease, box-shadow .25s ease;
}
.ttc-product:hover { transform: translateY(-4px); box-shadow: 0 1px 2px rgba(15, 23, 42, .06), 0 22px 40px -18px rgba(15, 23, 42, .35); }
.ttc-product-img {
  position: relative;
  aspect-ratio: 4 / 3;
  background: linear-gradient(135deg, #e8edf8, #cfd9f0);
}
.ttc-badge {
  position: absolute;
  top: 12px; left: 12px;
  padding: 5px 9px;
  border-radius: 999px;
  background: #ef4444;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
}
.ttc-product-body { padding: 16px 18px 18px; }
.ttc-product-cat { margin: 0 0 4px; color: #64748b; font-size: 12px; text-transform: uppercase; letter-spacing: .08em; }
.ttc-product h3 { margin: 0 0 8px; color: #0f172a; font-size: 17px; }
.ttc-price { margin: 0 0 14px; color: #0f172a; }
.ttc-price s { margin-left: 6px; color: #94a3b8; font-size: 14px; }
.ttc-product button {
  width: 100%;
  padding: 11px;
  border: 0;
  border-radius: 10px;
  background: #0f172a;
  color: #fff;
  font: 600 14px Inter, system-ui, sans-serif;
  cursor: pointer;
}
.ttc-product button:hover { background: #5B8CFF; }
.ttc-product button:focus-visible { outline: 2px solid #5B8CFF; outline-offset: 2px; }

02. Profile Card

Pure CSS

A team or author card with an initials avatar, name, role, a short bio and two actions. The avatar uses initials on a gradient instead of a photo, so it works before anyone uploads a picture. Text sizes follow a clear hierarchy: name first, role second, bio last.

View code
<article class="ttc-profile">
  <div class="ttc-avatar" aria-hidden="true">AK</div>
  <h3>Ayesha Khan</h3>
  <p class="ttc-role">Product Designer</p>
  <p class="ttc-bio">Designs checkout flows that people finish. Ten years in ecommerce, mostly Shopify.</p>
  <div class="ttc-actions">
    <a href="#" class="is-primary">Message</a>
    <a href="#">View work</a>
  </div>
</article>
.ttc-profile {
  width: 280px;
  padding: 28px 24px 24px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 20px;
  background: #121722;
  color: #F5F7FA;
  text-align: center;
  font-family: Inter, system-ui, sans-serif;
}
.ttc-avatar {
  display: grid;
  place-items: center;
  width: 72px; height: 72px;
  margin: 0 auto 14px;
  border-radius: 50%;
  background: linear-gradient(135deg, #7DA3FF, #8B5CF6);
  color: #080A0F;
  font-size: 24px;
  font-weight: 800;
}
.ttc-profile h3 { margin: 0; font-size: 19px; }
.ttc-role { margin: 4px 0 12px; color: #7DA3FF; font-size: 14px; font-weight: 600; }
.ttc-bio { margin: 0 0 20px; color: #A7AFBD; font-size: 14px; line-height: 1.55; }
.ttc-actions { display: flex; gap: 8px; }
.ttc-actions a {
  flex: 1;
  padding: 10px;
  border: 1px solid rgba(255, 255, 255, .16);
  border-radius: 10px;
  color: #F5F7FA;
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
}
.ttc-actions a.is-primary { border-color: transparent; background: #5B8CFF; color: #080A0F; }
.ttc-actions a:focus-visible { outline: 2px solid #7DA3FF; outline-offset: 2px; }

03. Pricing Plan Card

Pure CSS

A highlighted pricing card with a 'Most popular' ribbon, the price set large with the billing period small beside it, a feature list with check marks and a full-width button. The check marks are drawn with CSS, so there are no icon files to load.

View code
<article class="ttc-plan">
  <span class="ttc-plan-tag">Most popular</span>
  <h3>Growth</h3>
  <p class="ttc-plan-price"><strong>$29</strong>/month</p>
  <ul>
    <li>Unlimited projects</li>
    <li>Priority email support</li>
    <li>Custom domain</li>
    <li>Weekly backups</li>
  </ul>
  <a href="#">Choose Growth</a>
</article>
.ttc-plan {
  position: relative;
  width: 280px;
  padding: 30px 26px 26px;
  border: 1px solid rgba(91, 140, 255, .45);
  border-radius: 20px;
  background: linear-gradient(180deg, rgba(91, 140, 255, .12), #121722 45%);
  color: #F5F7FA;
  font-family: Inter, system-ui, sans-serif;
}
.ttc-plan-tag {
  position: absolute;
  top: -12px; left: 50%;
  transform: translateX(-50%);
  padding: 5px 12px;
  border-radius: 999px;
  background: #5B8CFF;
  color: #080A0F;
  font-size: 12px;
  font-weight: 700;
  white-space: nowrap;
}
.ttc-plan h3 { margin: 0 0 6px; font-size: 18px; }
.ttc-plan-price { margin: 0 0 20px; color: #A7AFBD; }
.ttc-plan-price strong { color: #F5F7FA; font-size: 40px; letter-spacing: -.02em; }
.ttc-plan ul { margin: 0 0 24px; padding: 0; list-style: none; }
.ttc-plan li { position: relative; margin-bottom: 10px; padding-left: 26px; color: #D7DCE6; font-size: 14px; }
.ttc-plan li::before {
  content: "";
  position: absolute;
  left: 4px; top: 3px;
  width: 6px; height: 11px;
  border: solid #22C55E;
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}
.ttc-plan a {
  display: block;
  padding: 12px;
  border-radius: 10px;
  background: linear-gradient(120deg, #7DA3FF, #5B8CFF);
  color: #080A0F;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
}
.ttc-plan a:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

04. Frosted Glass Card

Pure CSS

A card with a frosted-glass surface: a translucent fill, a background blur and a thin light border. It only reads as glass over a colourful background, so the demo includes one. A solid fallback colour keeps the text readable in browsers without backdrop-filter.

View code
<div class="ttc-glass-stage">
  <article class="ttc-glass">
    <p class="ttc-glass-k">Monthly revenue</p>
    <p class="ttc-glass-v">$48,210</p>
    <p class="ttc-glass-d">+12.4% vs last month</p>
  </article>
</div>
.ttc-glass-stage { box-sizing: border-box; max-width: 100%;
  display: grid;
  place-items: center;
  padding: clamp(16px, 6vw, 40px);
  border-radius: 24px;
  background:
    radial-gradient(circle at 20% 25%, #7DA3FF 0, transparent 40%),
    radial-gradient(circle at 80% 70%, #8B5CF6 0, transparent 45%),
    #0E1118;
}
.ttc-glass { box-sizing: border-box; max-width: 100%;
  width: 260px;
  padding: 24px;
  border: 1px solid rgba(255, 255, 255, .25);
  border-radius: 18px;
  background: rgba(18, 23, 34, .7);
  color: #fff;
  font-family: Inter, system-ui, sans-serif;
}
@supports (backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px)) {
  .ttc-glass {
    background: rgba(255, 255, 255, .12);
    -webkit-backdrop-filter: blur(16px) saturate(160%);
    backdrop-filter: blur(16px) saturate(160%);
  }
}
.ttc-glass-k { margin: 0; font-size: 13px; opacity: .8; }
.ttc-glass-v { margin: 6px 0; font-size: 32px; font-weight: 800; letter-spacing: -.02em; }
.ttc-glass-d { margin: 0; color: #86efac; font-size: 13px; font-weight: 600; }

05. Blog Post Card

Pure CSS

An article teaser with a cover area, category, title, a two-line excerpt and author line. The whole card is clickable through a stretched link on the title, which keeps one link per card for screen readers instead of wrapping the entire card in an anchor.

View code
<article class="ttc-post">
  <div class="ttc-post-cover"></div>
  <div class="ttc-post-body">
    <p class="ttc-post-cat">Guides</p>
    <h3><a href="#">How to cut checkout steps without losing data</a></h3>
    <p class="ttc-post-ex">Every extra field costs you buyers. Here is how to keep the data you need while asking for less of it up front.</p>
    <p class="ttc-post-meta">Taimur · 6 min read</p>
  </div>
</article>
.ttc-post {
  position: relative;
  width: 300px;
  overflow: hidden;
  border: 1px solid #e2e8f0;
  border-radius: 16px;
  background: #fff;
  font-family: Inter, system-ui, sans-serif;
  transition: border-color .2s ease;
}
.ttc-post:hover { border-color: #5B8CFF; }
.ttc-post-cover { aspect-ratio: 16 / 9; background: linear-gradient(120deg, #7DA3FF, #5B8CFF 60%, #8B5CF6); }
.ttc-post-body { padding: 16px 18px 18px; }
.ttc-post-cat { margin: 0 0 6px; color: #3B6FE6; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .08em; }
.ttc-post h3 { margin: 0 0 8px; font-size: 17px; line-height: 1.35; }
.ttc-post h3 a { color: #0f172a; text-decoration: none; }
.ttc-post h3 a::after { content: ""; position: absolute; inset: 0; }
.ttc-post h3 a:focus-visible { outline: none; }
.ttc-post:focus-within { outline: 2px solid #5B8CFF; outline-offset: 2px; }
.ttc-post-ex {
  display: -webkit-box;
  margin: 0 0 12px;
  overflow: hidden;
  color: #475569;
  font-size: 14px;
  line-height: 1.55;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
}
.ttc-post-meta { margin: 0; color: #64748b; font-size: 13px; }

06. Stat Card with Sparkline

Pure CSS

A dashboard metric card: label, big number, change pill and a tiny trend line. The sparkline is an inline SVG polyline, so it scales crisply and needs no chart library. The change pill pairs colour with an arrow, so the direction is clear without relying on colour alone.

View code
<article class="ttc-stat">
  <p class="ttc-stat-k">Orders today</p>
  <div class="ttc-stat-row">
    <p class="ttc-stat-v">1,284</p>
    <span class="ttc-stat-up">▲ 8.1%</span>
  </div>
  <svg viewBox="0 0 120 32" aria-hidden="true"><polyline points="0,26 15,22 30,24 45,15 60,18 75,10 90,12 105,5 120,7"/></svg>
</article>
.ttc-stat {
  width: 240px;
  padding: 20px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-radius: 16px;
  background: #121722;
  color: #F5F7FA;
  font-family: Inter, system-ui, sans-serif;
}
.ttc-stat-k { margin: 0 0 8px; color: #A7AFBD; font-size: 13px; }
.ttc-stat-row { display: flex; align-items: center; justify-content: space-between; }
.ttc-stat-v { margin: 0; font-size: 30px; font-weight: 800; letter-spacing: -.02em; }
.ttc-stat-up {
  padding: 4px 8px;
  border-radius: 999px;
  background: rgba(34, 197, 94, .14);
  color: #4ade80;
  font-size: 12px;
  font-weight: 700;
}
.ttc-stat svg { display: block; width: 100%; height: 36px; margin-top: 12px; }
.ttc-stat polyline { fill: none; stroke: #7DA3FF; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }

07. Flip Card

Pure CSS

A card that turns over on hover or keyboard focus to show a second face, useful for flashcards, team bios and before-and-after reveals. It is a button, so it can be reached with Tab. Visitors who prefer reduced motion get a fade between the faces instead of a 3D turn.

View code
<button class="ttc-flip" type="button" aria-label="Flip card: what does CSS stand for?">
  <span class="ttc-flip-in">
    <span class="ttc-face">What does CSS stand for?</span>
    <span class="ttc-face ttc-back">Cascading Style Sheets</span>
  </span>
</button>
.ttc-flip {
  width: 260px;
  height: 160px;
  padding: 0;
  border: 0;
  background: none;
  perspective: 900px;
  cursor: pointer;
  font: 700 18px/1.35 Inter, system-ui, sans-serif;
}
.ttc-flip-in {
  position: relative;
  display: block;
  width: 100%; height: 100%;
  transform-style: preserve-3d;
  transition: transform .6s cubic-bezier(.2,.7,.2,1);
}
.ttc-face {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 20px;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: 18px;
  background: #121722;
  color: #F5F7FA;
  backface-visibility: hidden;
}
.ttc-back { background: linear-gradient(120deg, #7DA3FF, #5B8CFF); color: #080A0F; transform: rotateY(180deg); }
.ttc-flip:hover .ttc-flip-in,
.ttc-flip:focus-visible .ttc-flip-in { transform: rotateY(180deg); }
.ttc-flip:focus-visible { outline: 2px solid #7DA3FF; outline-offset: 4px; border-radius: 18px; }
@media (prefers-reduced-motion: reduce) {
  .ttc-flip-in { transition: none; transform: none !important; }
  .ttc-face { transition: opacity .3s ease; }
  .ttc-back { transform: none; opacity: 0; }
  .ttc-flip:hover .ttc-back, .ttc-flip:focus-visible .ttc-back { opacity: 1; }
}

08. Dismissible Notification Card

CSS + JS

An in-app notice with an icon, title, message, an action link and a close button. Closing it plays a short slide-and-fade, then removes it from the page so screen readers no longer reach it. The close button has a real label and a 40px hit area.

View code
<div class="ttc-note" role="status">
  <span class="ttc-note-ic" aria-hidden="true">i</span>
  <div class="ttc-note-txt">
    <p class="ttc-note-t">New invoice ready</p>
    <p class="ttc-note-m">Invoice #1042 for March is ready to download.</p>
    <a href="#">View invoice</a>
  </div>
  <button type="button" class="ttc-note-x" aria-label="Dismiss notification">×</button>
</div>
.ttc-note { box-sizing: border-box; max-width: 100%;
  display: flex;
  gap: 14px;
  width: 340px;
  padding: 16px 12px 16px 16px;
  border: 1px solid rgba(255, 255, 255, .1);
  border-left: 3px solid #5B8CFF;
  border-radius: 14px;
  background: #121722;
  color: #F5F7FA;
  font-family: Inter, system-ui, sans-serif;
  transition: opacity .25s ease, transform .25s ease;
}
.ttc-note.is-leaving { opacity: 0; transform: translateX(16px); }
.ttc-note-ic {
  display: grid;
  place-items: center;
  flex: 0 0 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(91, 140, 255, .18);
  color: #7DA3FF;
  font-weight: 800;
  font-style: italic;
}
.ttc-note-txt { flex: 1; }
.ttc-note-t { margin: 2px 0 4px; font-size: 15px; font-weight: 700; }
.ttc-note-m { margin: 0 0 8px; color: #A7AFBD; font-size: 14px; line-height: 1.5; }
.ttc-note a { color: #7DA3FF; font-size: 14px; font-weight: 600; }
.ttc-note-x {
  flex: 0 0 40px;
  height: 40px;
  margin: -8px -2px 0 0;
  border: 0;
  border-radius: 10px;
  background: none;
  color: #7F8899;
  font-size: 22px;
  cursor: pointer;
}
.ttc-note-x:hover { background: rgba(255, 255, 255, .06); color: #F5F7FA; }
.ttc-note-x:focus-visible { outline: 2px solid #7DA3FF; }
document.querySelectorAll('.ttc-note-x').forEach(function (x) {
  x.addEventListener('click', function () {
    var card = x.closest('.ttc-note');
    card.classList.add('is-leaving');
    setTimeout(function () { card.remove(); }, 260);
  });
});

About these CSS Cards

Designing cards that survive real content

Demo text is always the perfect length; real product names and blog titles are not. Give images a fixed aspect-ratio so the grid does not jump while they load, clamp long excerpts to a set number of lines, and let titles wrap instead of truncating the words people need to read.

Making a whole card clickable

Wrapping an entire card in a link makes screen readers read everything inside it as one long link. The blog card here uses a better pattern: a single link on the title, stretched over the card with a pseudo-element. The whole card is clickable, but there is still only one link with a short, clear name.

Glass, shadows and depth

Depth comes from contrast between the card and the page. On a light page a soft, wide shadow is enough. On a dark page a thin light border reads better than a shadow. Frosted glass only works over a colourful background, and it needs a solid fallback colour for browsers without backdrop-filter so the text stays readable.

How to use these demos

Each card is scoped with a .ttc- class prefix and has a fixed demo width. In a real layout, remove the width and let a CSS grid decide it, for example grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)). Open any card in the editor to try your own text and colours.

Frequently asked questions

Can I use these cards in a Shopify or WordPress theme?

Yes. Paste the CSS into your theme stylesheet and the HTML into a section or block. Rename the class prefix if it clashes with your theme.

Why do some cards use a light background?

Cards are shown on the background they were designed for. Product and blog cards usually live on light store and blog pages, so their demos use one.

Do the cards need JavaScript?

Only the notification card, for its close button. Everything else, including the flip card, is CSS only.