✅ Common Pseudo-class Selectors
Selector | Description |
|---|---|
| Selects when the user hovers over an element |
| Selects when an element is being clicked |
| Selects when an element (like input) is focused |
| Selects the first child of its parent |
| Selects the last child of its parent |
| Selects the nth child of its parent |
| Selects checked form elements (like radio/checkbox) |
| Selects disabled form elements |
| Selects everything except what's passed in |
✅ Example: Hover, Active, and First Child
Here’s a complete working example using separate HTML and CSS:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Pseudo-class Anatomy</title>
<style>
.infographic-pseudo {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
box-sizing: border-box;
margin: 0 auto;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
background: var(--paper);
color: var(--ink);
border-radius: 14px;
overflow: hidden;
}
.infographic-pseudo[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.ha-layout { display: flex; flex-direction: column; gap: 1.5rem; }
.ha-code-wrap {
background: #0b0b0b;
border: 1px solid #2a2a2a;
border-radius: 10px;
overflow: hidden;
}
.ha-filetabs {
display: flex;
background: #161616;
border-bottom: 1px solid #2a2a2a;
}
.ha-filetab {
border: none;
background: transparent;
color: #8a8a8a;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.78rem;
font-weight: 700;
padding: 0.6rem 1rem;
cursor: pointer;
border-bottom: 2px solid transparent;
transition: color 0.15s ease, border-color 0.15s ease, background 0.15s ease;
}
.ha-filetab:hover { color: #e5e5e5; }
.ha-filetab.ha-tab-on {
color: #ffffff;
border-bottom-color: #5b8def;
background: #0b0b0b;
}
.ha-code {
padding: 1rem 1.8rem 1rem 0.9rem;
font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
font-size: 0.76rem;
line-height: 1.8;
overflow-x: auto;
}
.ha-codepane { display: none; }
.ha-codepane.ha-pane-on { display: block; }
.ha-line { display: block; white-space: pre; color: #8a8a8a; padding: 0.05rem 0.4rem; }
.ha-tag { color: #60a5fa; font-weight: 700; }
.ha-attr { color: #f2b96b; }
.ha-str { color: #9ece6a; }
.ha-sel { color: #f472b6; font-weight: 700; }
.ha-pseudo { color: #ffd166; font-weight: 800; }
.ha-prop { color: #c586c0; }
.ha-val { color: #ce9178; }
.ha-comment { color: #5c6370; font-style: italic; }
.ha-browser {
border: 1px solid var(--line);
border-radius: 10px;
overflow: hidden;
background: var(--paper);
}
.ha-browser-bar {
background: var(--paper-alt);
padding: 0.5rem 0.7rem;
display: flex;
align-items: center;
gap: 0.5rem;
border-bottom: 1px solid var(--line);
}
.ha-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--line); }
.ha-tab {
background: var(--paper);
border: 1px solid var(--line);
border-bottom: none;
border-radius: 6px 6px 0 0;
font-size: 0.72rem;
color: var(--ink-soft);
padding: 0.25rem 0.6rem;
}
.ha-urlrow {
background: var(--paper-alt);
padding: 0.35rem 0.7rem 0.6rem;
font-size: 0.72rem;
color: var(--ink-soft);
font-family: "SFMono-Regular", Consolas, monospace;
}
/* ---- live demo screen (real pseudo-classes, actually functional) ---- */
.ha-screen {
background: #ffffff;
color: #111;
padding: 1.2rem 1.4rem 1.4rem;
font-family: Georgia, "Times New Roman", serif;
}
.ha-screen h1 { font-size: 1.15rem; margin: 0 0 0.9rem; }
.ha-row { display: flex; align-items: center; gap: 0.6rem; margin-bottom: 0.9rem; flex-wrap: wrap; }
.ha-hint { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; font-size: 0.72rem; color: var(--ink-soft); }
.ha-screen a {
color: #111;
text-decoration: none;
font-size: 0.9rem;
}
.ha-screen a:hover { color: red; text-decoration: underline; }
.ha-screen a:active { color: green; }
.ha-screen input[type="text"] {
font-family: inherit;
font-size: 0.85rem;
padding: 0.35rem 0.5rem;
border: 1px solid #ccc;
border-radius: 4px;
outline: none;
}
.ha-screen input[type="text"]:focus {
border: 2px solid blue;
}
.ha-screen ul { margin: 0; padding-left: 1.3rem; font-size: 0.88rem; }
.ha-screen li:first-child { font-weight: bold; color: orange; }
.ha-screen input[type="checkbox"] { accent-color: #999; }
.ha-screen input[type="checkbox"]:checked { accent-color: green; }
</style>
</head>
<body>
<div class="infographic-pseudo" id="ha-root">
<div class="ha-inner">
<div class="ha-layout">
<div class="ha-code-wrap">
<div class="ha-filetabs">
<button class="ha-filetab ha-tab-on" id="tab-html">index.html</button>
<button class="ha-filetab" id="tab-css">style.css</button>
</div>
<div class="ha-code">
<div class="ha-codepane ha-pane-on" id="pane-html">
<span class="ha-line"><<span class="ha-tag">body</span>></span>
<span class="ha-line"> <<span class="ha-tag">h1</span>>CSS Pseudo-classes Demo</<span class="ha-tag">h1</span>></span>
<span class="ha-line"> <<span class="ha-tag">a</span> <span class="ha-attr">href</span>=<span class="ha-str">"#"</span>>Hover over this link</<span class="ha-tag">a</span>></span>
<span class="ha-line"> <<span class="ha-tag">input</span> <span class="ha-attr">type</span>=<span class="ha-str">"text"</span> <span class="ha-attr">placeholder</span>=<span class="ha-str">"Click or tab here"</span> /></span>
<span class="ha-line"> <<span class="ha-tag">ul</span>></span>
<span class="ha-line"> <<span class="ha-tag">li</span>>First item</<span class="ha-tag">li</span>></span>
<span class="ha-line"> <<span class="ha-tag">li</span>>Second item</<span class="ha-tag">li</span>></span>
<span class="ha-line"> <<span class="ha-tag">li</span>>Third item</<span class="ha-tag">li</span>></span>
<span class="ha-line"> </<span class="ha-tag">ul</span>></span>
<span class="ha-line"> <<span class="ha-tag">input</span> <span class="ha-attr">type</span>=<span class="ha-str">"checkbox"</span> <span class="ha-attr">checked</span> /> Checked checkbox</span>
<span class="ha-line"> <<span class="ha-tag">input</span> <span class="ha-attr">type</span>=<span class="ha-str">"checkbox"</span> /> Unchecked checkbox</span>
<span class="ha-line"></<span class="ha-tag">body</span>></span>
</div>
<div class="ha-codepane" id="pane-css">
<span class="ha-line ha-comment">/* Hover state */</span>
<span class="ha-line"><span class="ha-sel">a</span><span class="ha-pseudo">:hover</span> {</span>
<span class="ha-line"> <span class="ha-prop">color</span>: <span class="ha-val">red</span>;</span>
<span class="ha-line"> <span class="ha-prop">text-decoration</span>: <span class="ha-val">underline</span>;</span>
<span class="ha-line">}</span>
<span class="ha-line ha-comment">/* Active (clicked) state */</span>
<span class="ha-line"><span class="ha-sel">a</span><span class="ha-pseudo">:active</span> {</span>
<span class="ha-line"> <span class="ha-prop">color</span>: <span class="ha-val">green</span>;</span>
<span class="ha-line">}</span>
<span class="ha-line ha-comment">/* Focus state */</span>
<span class="ha-line"><span class="ha-sel">input</span><span class="ha-pseudo">:focus</span> {</span>
<span class="ha-line"> <span class="ha-prop">border</span>: <span class="ha-val">2px solid blue</span>;</span>
<span class="ha-line">}</span>
<span class="ha-line ha-comment">/* First child of a list */</span>
<span class="ha-line"><span class="ha-sel">li</span><span class="ha-pseudo">:first-child</span> {</span>
<span class="ha-line"> <span class="ha-prop">font-weight</span>: <span class="ha-val">bold</span>;</span>
<span class="ha-line"> <span class="ha-prop">color</span>: <span class="ha-val">orange</span>;</span>
<span class="ha-line">}</span>
<span class="ha-line ha-comment">/* Checked checkbox */</span>
<span class="ha-line"><span class="ha-sel">input</span><span class="ha-pseudo">:checked</span> {</span>
<span class="ha-line"> <span class="ha-prop">accent-color</span>: <span class="ha-val">green</span>;</span>
<span class="ha-line">}</span>
</div>
</div>
</div>
<div class="ha-browser">
<div class="ha-browser-bar">
<span class="ha-dot"></span><span class="ha-dot"></span><span class="ha-dot"></span>
<div class="ha-tab">🌐 CSS Pseudo-classes Demo</div>
</div>
<div class="ha-urlrow">127.0.0.1:5500/html</div>
<div class="ha-screen">
<h1>CSS Pseudo-classes Demo</h1>
<div class="ha-row">
<a href="#" onclick="return false;">Hover over this link</a>
<span class="ha-hint">← try hovering, then clicking and holding</span>
</div>
<div class="ha-row">
<input type="text" placeholder="Click or tab here">
<span class="ha-hint">← focus it</span>
</div>
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>
<div class="ha-row" style="margin-top: 0.9rem;">
<label><input type="checkbox" checked> Checked checkbox</label>
</div>
<div class="ha-row">
<label><input type="checkbox"> Unchecked checkbox</label>
<span class="ha-hint">← check it</span>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.getElementById('ha-root');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function () {
const tabHtml = document.getElementById('tab-html');
const tabCss = document.getElementById('tab-css');
const paneHtml = document.getElementById('pane-html');
const paneCss = document.getElementById('pane-css');
tabHtml.addEventListener('click', () => {
tabHtml.classList.add('ha-tab-on');
tabCss.classList.remove('ha-tab-on');
paneHtml.classList.add('ha-pane-on');
paneCss.classList.remove('ha-pane-on');
});
tabCss.addEventListener('click', () => {
tabCss.classList.add('ha-tab-on');
tabHtml.classList.remove('ha-tab-on');
paneCss.classList.add('ha-pane-on');
paneHtml.classList.remove('ha-pane-on');
});
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});🖥️ Output Highlights
Hovering the link turns it red and underlined.
Clicking it turns it green (active).
Focusing on the input highlights it with a blue border.
The first
<li>becomes orange and bold.The checked checkbox has a green accent color.
🚀 Try and Play Around
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CSS Pseudo-Class Selectors</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Newsreader:ital,wght@0,500;0,600;1,500&family=Inter:wght@400;500;600&family=IBM+Plex+Mono:wght@500&display=swap" rel="stylesheet">
<style>
.pseudo-infographic {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #faf8f4;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-deep:#1741a6;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--disabled-text: #b0a99c;
--display-font: "Newsreader", serif;
--body-font: "Inter", sans-serif;
--mono-font: "IBM Plex Mono", monospace;
color: var(--ink);
font-family: var(--body-font);
max-width: 880px;
margin: 0 auto;
box-sizing: border-box;
line-height: 1.5;
background: transparent;
}
.pseudo-infographic[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-deep:#8fb3ff;
--accent-soft:#202942;
--line: #2c313d;
--disabled-text: #5c5850;
}
.pseudo-infographic * { box-sizing: border-box; }
.pseudo-infographic .head { margin-bottom: 2rem; }
.pseudo-infographic .head h1 {
font-family: var(--display-font);
font-weight: 600;
font-size: clamp(1.7rem, 4.5vw, 2.4rem);
margin: 0 0 0.4rem;
color: var(--ink);
}
.pseudo-infographic .head .sub {
color: var(--ink-soft);
font-size: 0.95rem;
margin: 0;
text-align: center;
}
.pseudo-infographic .head .sub em {
font-style: italic;
color: var(--accent-deep);
}
/* grid of cards */
.pseudo-infographic .grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 1px;
background: var(--line);
border: 1px solid var(--line);
}
@media (max-width: 760px) {
.pseudo-infographic .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 500px) {
.pseudo-infographic .grid { grid-template-columns: 1fr; }
}
.pseudo-infographic .card {
background: var(--paper);
padding: 1.1rem 1.1rem 1.3rem;
display: flex;
flex-direction: column;
gap: 0.7rem;
transition: background 0.15s;
}
.pseudo-infographic .card.is-fired {
background: var(--accent-soft);
}
.pseudo-infographic .card .label-row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 0.5rem;
}
.pseudo-infographic .card code.selector {
font-family: var(--mono-font);
font-size: 0.92rem;
color: var(--accent-deep);
font-weight: 500;
}
.pseudo-infographic .card .status {
font-size: 0.68rem;
letter-spacing: 0.03em;
text-transform: uppercase;
color: var(--ink-soft);
opacity: 0;
transition: opacity 0.15s;
white-space: nowrap;
}
.pseudo-infographic .card.is-fired .status {
opacity: 1;
color: var(--accent-deep);
font-weight: 600;
}
.pseudo-infographic .card .desc {
font-size: 0.82rem;
color: var(--ink-soft);
margin: 0;
min-height: 2.4em;
}
/* the live demo zone */
.pseudo-infographic .demo {
margin-top: auto;
display: flex;
align-items: center;
justify-content: center;
min-height: 64px;
padding: 0.5rem;
background: var(--paper-alt);
border: 1px dashed var(--line);
transition: background 0.2s ease, border-color 0.2s ease;
}
/* --- demo widget styling --- */
.pseudo-infographic .demo-btn {
font: inherit;
font-size: 0.85rem;
font-weight: 500;
padding: 0.5rem 1.1rem;
border: 1px solid var(--accent);
background: var(--paper);
color: var(--accent-deep);
cursor: pointer;
border-radius: 3px;
transition: background 0.15s, transform 0.08s, box-shadow 0.15s;
}
.pseudo-infographic .demo-hover:hover {
background: var(--accent-soft);
}
.pseudo-infographic .demo-active:active {
background: var(--accent);
color: #fff;
transform: translateY(1px);
}
.pseudo-infographic .demo-focus {
width: 100%;
max-width: 160px;
font: inherit;
font-size: 0.85rem;
padding: 0.45rem 0.6rem;
border: 1px solid var(--line);
background: var(--paper);
color: var(--ink);
border-radius: 3px;
outline: none;
}
.pseudo-infographic .demo-focus:focus {
border-color: var(--accent);
box-shadow: 0 0 0 3px var(--accent-soft);
}
.pseudo-infographic .demo-list {
list-style: none;
margin: 0;
padding: 0;
width: 100%;
font-size: 0.78rem;
font-family: var(--mono-font);
display: flex;
flex-direction: column;
gap: 2px;
}
.pseudo-infographic .demo-list li {
padding: 0.3rem 0.5rem;
background: var(--paper);
border: 1px solid var(--line);
color: var(--ink-soft);
transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.pseudo-infographic .demo-list.show-first li:first-child,
.pseudo-infographic .demo-list.show-last li:last-child,
.pseudo-infographic .demo-list.show-nth li:nth-child(3) {
background: var(--accent-soft);
border-color: var(--accent);
color: var(--accent-deep);
font-weight: 600;
}
.pseudo-infographic .demo-check-row {
display: flex;
align-items: center;
gap: 0.5rem;
font-size: 0.82rem;
}
.pseudo-infographic .demo-check-row input[type="checkbox"] {
accent-color: var(--accent);
width: 16px;
height: 16px;
cursor: pointer;
}
.pseudo-infographic .demo-check-row label {
cursor: pointer;
color: var(--ink-soft);
transition: color 0.15s;
}
.pseudo-infographic .demo-check-row input:checked + label {
color: var(--accent-deep);
font-weight: 600;
}
.pseudo-infographic .demo-disabled-row {
display: flex;
gap: 0.5rem;
}
.pseudo-infographic .demo-disabled-btn {
font: inherit;
font-size: 0.8rem;
padding: 0.45rem 0.85rem;
border: 1px solid var(--line);
border-radius: 3px;
background: var(--paper-alt);
color: var(--disabled-text);
cursor: not-allowed;
}
.pseudo-infographic .demo-disabled-btn:disabled {
background: var(--paper-alt);
color: var(--disabled-text);
border-style: dashed;
}
.pseudo-infographic .demo-not-grid {
display: flex;
gap: 0.4rem;
flex-wrap: wrap;
justify-content: center;
}
.pseudo-infographic .demo-not-grid .chip {
font-family: var(--mono-font);
font-size: 0.72rem;
padding: 0.3rem 0.55rem;
background: var(--paper);
border: 1px solid var(--line);
color: var(--ink-soft);
border-radius: 3px;
}
.pseudo-infographic .demo-not-grid.is-not-active .chip:not(.exclude) {
background: var(--accent-soft);
border-color: var(--accent);
color: var(--accent-deep);
}
.pseudo-infographic .demo-not-grid .chip.exclude {
opacity: 0.5;
text-decoration: line-through;
}
.pseudo-infographic .hint {
font-size: 0.7rem;
color: var(--ink-soft);
text-align: center;
margin-top: 0.35rem;
font-style: italic;
}
.pseudo-infographic .footer-note {
margin-top: 1.5rem;
font-size: 0.85rem;
color: var(--ink-soft);
text-align: center;
}
@media (prefers-reduced-motion: reduce) {
.pseudo-infographic *, .pseudo-infographic *::before, .pseudo-infographic *::after {
transition-duration: 0.001ms !important;
animation-duration: 0.001ms !important;
}
}
</style>
</head>
<body>
<div class="pseudo-infographic">
<div class="head">
<p class="sub">Interact with each demo below to trigger the rule — watch the <em>status</em> light up.</p>
</div>
<div class="grid">
<!-- :hover -->
<div class="card" data-card="hover">
<div class="label-row"><code class="selector">:hover</code><span class="status">firing</span></div>
<p class="desc">When the cursor sits over an element.</p>
<div class="demo">
<button class="demo-btn demo-hover" data-fire="hover">Hover me</button>
</div>
</div>
<!-- :active -->
<div class="card" data-card="active">
<div class="label-row"><code class="selector">:active</code><span class="status">firing</span></div>
<p class="desc">While an element is being clicked/pressed.</p>
<div class="demo">
<button class="demo-btn demo-active" data-fire="active">Press me</button>
</div>
</div>
<!-- :focus -->
<div class="card" data-card="focus">
<div class="label-row"><code class="selector">:focus</code><span class="status">firing</span></div>
<p class="desc">When an input/element receives keyboard or click focus.</p>
<div class="demo">
<input class="demo-focus" type="text" placeholder="Click here" data-fire="focus">
</div>
</div>
<!-- :first-child -->
<div class="card" data-card="first-child">
<div class="label-row"><code class="selector">:first-child</code><span class="status">match</span></div>
<p class="desc">The first child inside its parent.</p>
<div class="demo">
<ul class="demo-list" data-list="first-child">
<li>item one</li>
<li>item two</li>
<li>item three</li>
</ul>
</div>
<button class="reveal-toggle-btn" data-toggle-list="first-child">Show match →</button>
</div>
<!-- :last-child -->
<div class="card" data-card="last-child">
<div class="label-row"><code class="selector">:last-child</code><span class="status">match</span></div>
<p class="desc">The last child inside its parent.</p>
<div class="demo">
<ul class="demo-list" data-list="last-child">
<li>item one</li>
<li>item two</li>
<li>item three</li>
</ul>
</div>
<button class="reveal-toggle-btn" data-toggle-list="last-child">Show match →</button>
</div>
<!-- :nth-child(n) -->
<div class="card" data-card="nth-child">
<div class="label-row"><code class="selector">:nth-child(3)</code><span class="status">match</span></div>
<p class="desc">The nth child — here, the 3rd item.</p>
<div class="demo">
<ul class="demo-list" data-list="nth-child">
<li>item one</li>
<li>item two</li>
<li>item three</li>
</ul>
</div>
<button class="reveal-toggle-btn" data-toggle-list="nth-child">Show match →</button>
</div>
<!-- :checked -->
<div class="card" data-card="checked">
<div class="label-row"><code class="selector">:checked</code><span class="status">checked</span></div>
<p class="desc">Checked radio or checkbox form elements.</p>
<div class="demo">
<div class="demo-check-row">
<input type="checkbox" id="demo-checkbox" data-fire="checked">
<label for="demo-checkbox">Check me</label>
</div>
</div>
</div>
<!-- :disabled -->
<div class="card" data-card="disabled">
<div class="label-row"><code class="selector">:disabled</code><span class="status">disabled</span></div>
<p class="desc">Form elements that can't be interacted with.</p>
<div class="demo">
<div class="demo-disabled-row">
<button class="demo-disabled-btn" disabled>Can't click</button>
</div>
</div>
</div>
<!-- :not(selector) -->
<div class="card" data-card="not">
<div class="label-row"><code class="selector">:not(.exclude)</code><span class="status">match</span></div>
<p class="desc">Everything except what's passed in.</p>
<div class="demo">
<div class="demo-not-grid" data-not-grid>
<span class="chip">A</span>
<span class="chip">B</span>
<span class="chip exclude">C</span>
<span class="chip">D</span>
</div>
</div>
<button class="reveal-toggle-btn" data-toggle-not>Apply :not(.exclude) →</button>
</div>
</div>
</div>
<style>
.pseudo-infographic .reveal-toggle-btn {
font: inherit;
font-size: 0.72rem;
background: none;
border: none;
color: var(--accent-deep);
cursor: pointer;
padding: 0;
text-align: left;
text-decoration: underline dotted;
margin-top: -0.3rem;
}
</style>
<script>
(function () {
var wrapper = document.currentScript.closest('.pseudo-infographic')
|| document.querySelector('.pseudo-infographic');
var bodyAttr = document.body.getAttribute('data-darkmode');
var dark;
if (bodyAttr === 'true') {
dark = true;
} else if (bodyAttr === 'false') {
dark = false;
} else {
var match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
})();
(function() {
var scope = document.querySelector('.pseudo-infographic');
if (!scope) return;
function card(name) { return scope.querySelector('[data-card="' + name + '"]'); }
// :hover
var hoverBtn = scope.querySelector('[data-fire="hover"]');
if (hoverBtn) {
hoverBtn.addEventListener('mouseenter', function() { card('hover').classList.add('is-fired'); });
hoverBtn.addEventListener('mouseleave', function() { card('hover').classList.remove('is-fired'); });
}
// :active
var activeBtn = scope.querySelector('[data-fire="active"]');
if (activeBtn) {
var fireActive = function() { card('active').classList.add('is-fired'); };
var unfireActive = function() { card('active').classList.remove('is-fired'); };
activeBtn.addEventListener('mousedown', fireActive);
activeBtn.addEventListener('mouseup', unfireActive);
activeBtn.addEventListener('mouseleave', unfireActive);
activeBtn.addEventListener('touchstart', fireActive, {passive: true});
activeBtn.addEventListener('touchend', unfireActive);
}
// :focus
var focusInput = scope.querySelector('[data-fire="focus"]');
if (focusInput) {
focusInput.addEventListener('focus', function() { card('focus').classList.add('is-fired'); });
focusInput.addEventListener('blur', function() { card('focus').classList.remove('is-fired'); });
}
// :checked
var checkbox = scope.querySelector('[data-fire="checked"]');
if (checkbox) {
checkbox.addEventListener('change', function() {
card('checked').classList.toggle('is-fired', checkbox.checked);
});
}
// :first-child / :last-child / :nth-child toggles
scope.querySelectorAll('[data-toggle-list]').forEach(function(btn) {
btn.addEventListener('click', function() {
var key = btn.getAttribute('data-toggle-list');
var list = scope.querySelector('[data-list="' + key + '"]');
var cardEl = card(key);
var cls = key === 'first-child' ? 'show-first' : key === 'last-child' ? 'show-last' : 'show-nth';
var isOn = list.classList.contains(cls);
list.classList.toggle(cls, !isOn);
cardEl.classList.toggle('is-fired', !isOn);
btn.textContent = !isOn ? 'Hide match' : 'Show match →';
});
});
// :not(.exclude)
var notBtn = scope.querySelector('[data-toggle-not]');
if (notBtn) {
notBtn.addEventListener('click', function() {
var grid = scope.querySelector('[data-not-grid]');
var isOn = grid.classList.contains('is-not-active');
grid.classList.toggle('is-not-active', !isOn);
card('not').classList.toggle('is-fired', !isOn);
notBtn.textContent = !isOn ? 'Reset' : 'Apply :not(.exclude) →';
});
}
})();
</script>
</body>
</html>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});