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.
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



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' witharia-pressed; its icons arearia-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 atrgb(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
#8b5cf6at 4.2:1,#64748bon#f1f5f9at 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.
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):
<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>
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 / property | Default | Effect |
|---|---|---|
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
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.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..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.