Transitions✨ Premium

Card Theme

A profile card that switches theme on its own, piece by piece: background, avatar, name, text, toggle button and two action buttons each carry their light color under .active and their own 0.5 s transition. The rest of the page does not move and the card reads no site variable; 0.45 KB of JavaScript, 150 ms when the user reduces motion.

CSSCardTransition

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Transitions has 52 effects, including 9 free. Explore the category →

3 usage examples

Customer reviews widget that follows the host site — a car repair shop — Card Theme example 1

① Customer reviews widget that follows the host site — a car repair shop

WhenOn the shop's website, the visitor switches to 'Light site': the page changes, and Patrice B.'s review card (five stars, timing belt replaced in a day) goes from dark to light with it.
WhyThe card manages itself, element by element: it switches without depending on the host site's variables, and the shop only has one class to set from its own toggle.
SettingsNo button in the card: the site's toggle sets active on the card while it changes the page; 276 px card; amber #f59e0b stars in place of the toggle button; 'Read the 312 reviews' and 'Leave a review' action labels.
A speaker's card — a trade show app — Card Theme example 2

② A speaker's card — a trade show app

WhenTwelve minutes before the talk in the Rhône room, Inès Morel's card switches to 'room' mode, dark, then back to 'aisles' mode, light, when the visitor walks out.
WhyEach piece of the card — photo, name, time box, buttons — has its own transition: the switch stays inside the component, and the show map next to it does not move.
Settings284 px card; violet-to-pink gradient avatar that lightens; added time box with its own .active rule and 0.5 s transition; the card's button kept.
A teacher's card — a middle school's online portal — Card Theme example 3

③ A teacher's card — a middle school's online portal

WhenOn the grade 8 B teachers page, Ms. Duval's card (math, office hours Thursday at 4:30 pm) is dark in the evening and light during the day, while the page itself stays light.
WhyWhen a single component must switch, you set its elements directly, without touching the rest of the page: the menu and the other cards do not change.
Settings242 px card placed in a light page; second line under the name added with its own color transition; 'Write' and 'Book a meeting' buttons.

How it works

The card .th-card-wrap (260 px, 20 px padding, 16 px corners) starts dark: #1e293b background, 8% white border. It holds a header (36 px round avatar, name, 30 px toggle button pushed right by margin-left: auto), a paragraph and two action buttons, 'Follow' in violet #8b5cf6 and 'Message' in 6% white. Nothing is inherited from elsewhere: each piece declares its dark color, then a .th-card-wrap.active … rule giving its light color — #fff and a light shadow for the card, #0f172a for the name, #64748b for the text, #6366f1 for the main action, #f1f5f9 for the secondary one.

Each piece also carries its own transition, limited to the properties that change: background-color .5s, border-color .5s, box-shadow .5s on the card, background-color .5s on the avatar and toggle button, color .5s on the name and text, background-color .5s, color .5s on the actions. Everything starts at the same moment and arrives together. Measured 300 ms after the click: card background rgb(229, 231, 233) in Chromium 151, rgb(223, 225, 227) in Firefox 153, rgb(228, 229, 231) in WebKit 26, exact white at 1.5 s; the second click plays the path backwards. The button icon (sun on dark, moon on light) swaps at once: it is a state marker, not a color.

The script (0.45 KB) arms every .th-card-toggle on the page and toggles .active on the .th-card-wrap that contains it (closest()), with aria-pressed: several cards coexist, each with its own state. The action buttons are real <button>s with no behavior, ready for yours, and use the page font (font-family: inherit). This piece-by-piece split is the choice of a self-contained component: the card drops into any site without depending on its variables or changing them. It does not read prefers-color-scheme and remembers nothing; a host site can also set .active itself so the card follows its theme.

Accessibility

  • Toggle button: a <button type="button"> named 'Light card theme' with aria-pressed; its icons are aria-hidden. Measured: reached with the Tab key in Chromium, toggled by Enter and Space in Chromium, Firefox and WebKit; a 2 px violet outline on keyboard focus, as on the two action buttons.
  • Reduced motion: nothing moves; under prefers-reduced-motion: reduce, all of the card's transitions drop to 150 ms. Measured: background already at rgb(180, 183, 190) at 60 ms in Chromium, final at 300 ms.
  • Contrast: text at 4.8:1 on both dark and light. The button labels, 11.5 px bold, sit just under 4.5:1 (white on #8b5cf6 at 4.2:1, #64748b on #f1f5f9 at 4.3:1): for important text, move the main action to #7c3aed (5.7:1) and the light secondary text to #475569 (6.9:1).

Browser compatibility

CSS (color and shadow transitions, :focus-visible) + 0.45 KB of JavaScript (closest()), no dependency, no CSS variable. Measured in Chromium 151, Firefox 153 and WebKit 26: the same intermediate colors within a few units, same way back, same keys. closest() exists since Chrome 41, Firefox 35 and Safari 6; before Chrome 86, Firefox 85 and Safari 15.4, the focus outline is the browser's own. The minimum versions come from gap in flex boxes: Chrome and Edge 84, Firefox 63, Safari 14.1 (iOS 14.5); before that, the items touch.

Chrome 84+✓ Full
Firefox 63+✓ Full
Safari 14.1+✓ Full
Edge 84+✓ Full
Mobile iOS 14.5+✓ Full
Android Chrome 84+✓ Full

Without JavaScript, the card stays dark and the toggle button does nothing; setting active in the HTML serves it light directly.

The code

HTML structure to paste into your page (the CSS + JS come with Premium):

index.html — structure
<div class="th-card-root">
  <div class="th-card-scene">
    <div class="th-card-wrap">
      <div class="th-card-header">
        <div class="th-card-avatar"></div>
        <span class="th-card-name">…</span>
        <button class="th-card-toggle" type="button" aria-pressed="false" aria-label="Light card theme">…</button>
      </div>
      <p class="th-card-text">…</p>
      <div class="th-card-actions">
        <button class="th-card-action th-card-action--primary" type="button">…</button>
        <button class="th-card-action th-card-action--secondary" type="button">…</button>
      </div>
    </div>
  </div>
</div>
Unlock the full code — $9.90/mo incl. tax

The full HTML + CSS + JS of Card Theme, ready to paste — plus all 840 effects. Or $299 once, lifetime access.

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Light colors (CSS — each .th-card-wrap.active … rule) card #fff, name #0f172a, text #64748b, action #6366f1 One rule per piece: change them together. Any piece added to the card needs its dark color, its .active rule and its transition, otherwise it does not change or it jumps.
Duration (CSS — .5s on each transition) 0.5 s Keep the same duration everywhere so text and background arrive together; 0.3 s for a discreet widget.
Toggle button (HTML — .th-card-toggle) 30 px, top right Remove it if the card follows its host, and set .active from the site; the script does nothing when there is no button.
Light theme shadow (CSS — box-shadow of .th-card-wrap.active) 0 4px 16px black at 8% On a light page, the shadow lifts the white card; go up to 12% on pure white.
Reduced motion (CSS — transition-duration: .15s) 150 ms 0s for an instant change.

FAQ

Set the class from your own toggle: document.querySelectorAll('.th-card-wrap').forEach(function (c) { c.classList.toggle('active', siteIsLight); }); and remove the card's button. The card does not read prefers-color-scheme and remembers nothing; if your site does, it only needs to set active on load, before the first paint, otherwise the transition plays when the page opens.
So the component depends on nothing: a card reading var(--text) would pick up the colors of a site that already defines --text, or impose its own. Here every color is written into the card, which makes it safe to paste anywhere. The price is upkeep: seven pieces, seven pairs of rules. For a theme shared across several components, CSS Variables (fx-0708) is leaner.
Yes: the script arms every .th-card-toggle and only switches the card that contains it, with no id. A list of profiles can mix dark and light cards; each button announces its card's state with aria-pressed.