🧱 What Are Grid Lines, Tracks, and Cells?
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Grid Terminology Anatomy</title>
<style>
.infographic-gridterms {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
box-sizing: border-box;
width: 100%;
max-width: 700px;
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-gridterms[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.infographic-gridterms *,
.infographic-gridterms *::before,
.infographic-gridterms *::after { box-sizing: border-box; min-width: 0; }
.ha-inner { padding: 0.9rem 0.7rem; }
.ha-layout { display: flex; flex-direction: column; gap: 1.1rem; align-items: stretch; }
.ha-diagram-wrap {
width: 100%;
max-width: 400px;
margin: 0 auto;
display: grid;
grid-template-columns: 18px 1fr;
grid-template-rows: 18px auto;
gap: 4px;
}
.ha-col-labels {
grid-column: 2;
grid-row: 1;
display: flex;
justify-content: space-between;
}
.ha-col-labels span {
text-align: center;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: clamp(0.6rem, 2.3vw, 0.72rem);
color: var(--ink-soft);
flex: 0 0 auto;
}
.ha-row-labels {
grid-column: 1;
grid-row: 2;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
}
.ha-row-labels span {
display: flex;
align-items: center;
justify-content: center;
font-family: "SFMono-Regular", Consolas, monospace;
font-size: clamp(0.6rem, 2.3vw, 0.72rem);
color: var(--ink-soft);
flex: 0 0 auto;
line-height: 1;
}
.ha-grid-stage {
grid-column: 2;
grid-row: 2;
position: relative;
width: 100%;
aspect-ratio: 370 / 290;
min-height: 1px;
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 370 290' preserveAspectRatio='none'%3E%3Cg stroke='%23ddd6c9' stroke-width='1.5' stroke-dasharray='4,3'%3E%3Cline x1='0' y1='0' x2='370' y2='0'/%3E%3Cline x1='0' y1='58' x2='370' y2='58'/%3E%3Cline x1='0' y1='116' x2='370' y2='116'/%3E%3Cline x1='0' y1='174' x2='370' y2='174'/%3E%3Cline x1='0' y1='232' x2='370' y2='232'/%3E%3Cline x1='0' y1='290' x2='370' y2='290'/%3E%3Cline x1='0' y1='0' x2='0' y2='290'/%3E%3Cline x1='74' y1='0' x2='74' y2='290'/%3E%3Cline x1='148' y1='0' x2='148' y2='290'/%3E%3Cline x1='222' y1='0' x2='222' y2='290'/%3E%3Cline x1='296' y1='0' x2='296' y2='290'/%3E%3Cline x1='370' y1='0' x2='370' y2='290'/%3E%3C/g%3E%3C/svg%3E");
background-size: 100% 100%;
background-repeat: no-repeat;
}
.infographic-gridterms[data-theme="dark"] .ha-grid-stage {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 370 290' preserveAspectRatio='none'%3E%3Cg stroke='%232c313d' stroke-width='1.5' stroke-dasharray='4,3'%3E%3Cline x1='0' y1='0' x2='370' y2='0'/%3E%3Cline x1='0' y1='58' x2='370' y2='58'/%3E%3Cline x1='0' y1='116' x2='370' y2='116'/%3E%3Cline x1='0' y1='174' x2='370' y2='174'/%3E%3Cline x1='0' y1='232' x2='370' y2='232'/%3E%3Cline x1='0' y1='290' x2='370' y2='290'/%3E%3Cline x1='0' y1='0' x2='0' y2='290'/%3E%3Cline x1='74' y1='0' x2='74' y2='290'/%3E%3Cline x1='148' y1='0' x2='148' y2='290'/%3E%3Cline x1='222' y1='0' x2='222' y2='290'/%3E%3Cline x1='296' y1='0' x2='296' y2='290'/%3E%3Cline x1='370' y1='0' x2='370' y2='290'/%3E%3C/g%3E%3C/svg%3E");
}
.ha-hotspot {
position: absolute;
box-sizing: border-box;
border-radius: 8px;
border: 2px solid transparent;
background: transparent;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-weight: 700;
font-size: clamp(0.58rem, 2.4vw, 0.72rem);
line-height: 1.2;
color: var(--ink-soft);
padding: 0.25rem;
transition: background 0.25s ease, border-color 0.25s ease, color 0.25s ease;
}
.ha-hotspot:hover {
background: var(--accent-soft);
border-color: var(--line);
}
.ha-hotspot.ha-active {
background: var(--accent-soft);
border-color: var(--accent);
color: var(--accent);
z-index: 2;
}
.ha-hotspot.ha-line {
border-radius: 999px;
font-size: 0;
z-index: 3;
min-width: 4px;
}
.ha-hotspot.ha-line.ha-active,
.ha-hotspot.ha-line:hover {
background: var(--accent-soft);
border-color: var(--accent);
}
.ha-note {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 0.8rem;
color: var(--ink-soft);
text-align: center;
max-width: 480px;
margin: 0 auto;
min-height: 2.4em;
}
@media (max-width: 420px) {
.ha-diagram-wrap { grid-template-columns: 14px 1fr; }
.ha-hotspot { padding: 0.15rem; }
}
</style>
</head>
<body>
<div class="infographic-gridterms" id="ha-root">
<div class="ha-inner">
<div class="ha-layout">
<div class="ha-diagram-wrap">
<div class="ha-col-labels">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span>
</div>
<div class="ha-row-labels">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span>
</div>
<div class="ha-grid-stage" id="stage">
<div class="ha-hotspot" id="hot-line" data-val="line"></div>
<div class="ha-hotspot" id="hot-cell" data-val="cell">Grid Cell</div>
<div class="ha-hotspot" id="hot-track-row" data-val="track-row">Grid Track (Row)</div>
<div class="ha-hotspot" id="hot-track-col" data-val="track-col">Grid Track<br>(Column)</div>
<div class="ha-hotspot" id="hot-area" data-val="area">Grid Area</div>
</div>
</div>
<div class="ha-note" id="note-out">Click any highlighted zone on the grid above to learn what it's called.</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 () {
// regions expressed as grid line numbers (1-indexed), positioned in
// PERCENTAGES of the stage (5x5 tracks) so they scale at any screen width —
// no pixel math, no resize listener needed.
const regions = {
'line': { c1: 3, c2: 3, r1: 1, r2: 6 },
'cell': { c1: 5, c2: 6, r1: 1, r2: 2 },
'track-row': { c1: 1, c2: 6, r1: 2, r2: 3 },
'track-col': { c1: 2, c2: 3, r1: 1, r2: 6 },
'area': { c1: 4, c2: 6, r1: 4, r2: 6 }
};
const notes = {
'line': 'A grid line is one of the numbered dividers that make up the structure — vertical or horizontal — that tracks and cells are measured against. This is column line 3.',
'cell': 'A grid cell is the smallest unit — a single space where one column track meets one row track, like a spreadsheet cell.',
'track-row': 'A row track is the horizontal space between two adjacent row lines — everything between row line 2 and row line 3.',
'track-col': 'A column track is the vertical space between two adjacent column lines — everything between column line 2 and column line 3.',
'area': 'A grid area is a rectangular block spanning multiple cells, columns, and rows — defined by its four bounding lines (here: columns 4-6, rows 4-6).'
};
const ids = { 'line': 'hot-line', 'cell': 'hot-cell', 'track-row': 'hot-track-row', 'track-col': 'hot-track-col', 'area': 'hot-area' };
Object.keys(regions).forEach(key => {
const r = regions[key];
const el = document.getElementById(ids[key]);
const leftPct = ((r.c1 - 1) / 5) * 100;
const topPct = ((r.r1 - 1) / 5) * 100;
const widthPct = ((r.c2 - r.c1) / 5) * 100;
const heightPct = ((r.r2 - r.r1) / 5) * 100;
if (key === 'line') {
el.style.left = `calc(${leftPct}% - 2px)`;
el.style.top = '0';
el.style.width = '4px';
el.style.height = '100%';
el.classList.add('ha-line');
} else {
el.style.left = leftPct + '%';
el.style.top = topPct + '%';
el.style.width = widthPct + '%';
el.style.height = heightPct + '%';
}
});
const note = document.getElementById('note-out');
const hotspots = Object.values(ids).map(id => document.getElementById(id));
hotspots.forEach(el => {
el.addEventListener('click', () => {
hotspots.forEach(h => h.classList.remove('ha-active'));
el.classList.add('ha-active');
note.textContent = notes[el.getAttribute('data-val')];
});
});
// Explicit pixel height, recalculated on resize — some mobile browsers
// don't reliably resolve `aspect-ratio` when the element sits in a CSS
// Grid row sized `auto`, which was collapsing the stage's height (and
// with it, every vertical border) down to almost nothing.
const stage = document.getElementById('stage');
function sizeStage() {
const w = stage.getBoundingClientRect().width;
if (w > 0) stage.style.height = (w * (290 / 370)) + 'px';
}
sizeStage();
window.addEventListener('resize', sizeStage);
window.addEventListener('orientationchange', sizeStage);
})();
</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!');
});In CSS Grid, the layout is made up of:
Term | Meaning |
|---|---|
Grid Line | The line between grid tracks (columns or rows) |
Grid Track | A single row or column (between two grid lines) |
Grid Cell | A single box where a row and column intersect |
🎯 Think of grid lines like the lines on graph paper, and grid tracks as the space between those lines.
🗂️ Explicit vs. Implicit Grids
🔹 Explicit Grid
You define it manually using:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Grid Basic Anatomy</title>
<style>
.infographic-gridbasic {
--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-gridbasic[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.ha-inner { padding: 0.5rem; }
.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.8rem;
line-height: 1.85;
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; border-radius: 5px; }
.ha-line.ha-clickable { cursor: pointer; color: #e5e5e5; transition: background 0.15s ease, box-shadow 0.15s ease; }
.ha-line.ha-clickable:hover { background: #1c2333; }
.ha-line.ha-active { background: #1c2333; box-shadow: inset 3px 0 0 #5b8def; color: #ffffff; }
.ha-tag { color: #60a5fa; font-weight: 700; }
.ha-attr { color: #f2b96b; }
.ha-str { color: #9ece6a; }
.ha-sel { color: #f472b6; font-weight: 700; }
.ha-prop { color: #c586c0; }
.ha-val { color: #ce9178; }
.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;
}
.ha-screen {
background: #ffffff;
padding: 1.2rem 1.4rem 1.4rem;
}
.ha-out-grid {
display: grid;
grid-template-columns: 100px 100px;
grid-template-rows: 50px 50px;
gap: 10px;
transition: outline 0.2s ease;
}
.ha-out-item {
background: steelblue;
color: white;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
font-family: Georgia, "Times New Roman", serif;
font-size: 1.1rem;
border-radius: 2px;
box-sizing: border-box;
transition: outline 0.2s ease;
}
.ha-out-lit { outline: 2px solid var(--accent); outline-offset: 2px; }
</style>
</head>
<body>
<div class="infographic-gridbasic" 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 ha-clickable ha-active" data-part="grid"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"container"</span>></span>
<span class="ha-line ha-clickable" data-part="item1"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>1</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable" data-part="item2"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>2</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable" data-part="item3"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>3</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable" data-part="item4"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>4</<span class="ha-tag">div</span>></span>
<span class="ha-line"> </<span class="ha-tag">div</span>></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-clickable ha-active" data-part="grid"><span class="ha-sel">.container</span> {</span>
<span class="ha-line ha-clickable ha-active" data-part="grid"> <span class="ha-prop">display</span>: <span class="ha-val">grid</span>;</span>
<span class="ha-line ha-clickable ha-active" data-part="grid"> <span class="ha-prop">grid-template-columns</span>: <span class="ha-val">100px 100px</span>;</span>
<span class="ha-line ha-clickable ha-active" data-part="grid"> <span class="ha-prop">grid-template-rows</span>: <span class="ha-val">50px 50px</span>;</span>
<span class="ha-line ha-clickable ha-active" data-part="grid"> <span class="ha-prop">gap</span>: <span class="ha-val">10px</span>;</span>
<span class="ha-line ha-clickable ha-active" data-part="grid">}</span>
<span class="ha-line"><span class="ha-sel">.item</span> {</span>
<span class="ha-line"> <span class="ha-prop">background</span>: <span class="ha-val">steelblue</span>;</span>
<span class="ha-line"> <span class="ha-prop">color</span>: <span class="ha-val">white</span>;</span>
<span class="ha-line"> <span class="ha-prop">padding</span>: <span class="ha-val">20px</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 Grid Basic</div>
</div>
<div class="ha-urlrow">127.0.0.1:5500/basicstructure.html</div>
<div class="ha-screen">
<div class="ha-out-grid ha-out-lit" id="out-grid">
<div class="ha-out-item" id="out-item1">1</div>
<div class="ha-out-item" id="out-item2">2</div>
<div class="ha-out-item" id="out-item3">3</div>
<div class="ha-out-item" id="out-item4">4</div>
</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');
});
const outMap = { grid: ['out-grid'], item1: ['out-item1'], item2: ['out-item2'], item3: ['out-item3'], item4: ['out-item4'] };
document.querySelectorAll('.ha-line.ha-clickable').forEach(line => {
line.addEventListener('click', () => {
const part = line.getAttribute('data-part');
document.querySelectorAll('.ha-line').forEach(l => {
l.classList.toggle('ha-active', l.getAttribute('data-part') === part);
});
document.querySelectorAll('.ha-out-grid, .ha-out-item').forEach(el => el.classList.remove('ha-out-lit'));
outMap[part].forEach(id => document.getElementById(id).classList.add('ha-out-lit'));
});
});
})();
</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!');
});🔹 Implicit Grid
If you place more items than defined rows/columns, Grid automatically adds rows or columns.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>CSS Grid Basic (5 Items) Anatomy</title>
<style>
.infographic-gridbasic5 {
--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-gridbasic5[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
}
.ha-inner { padding: 0.5rem; }
.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.8rem;
line-height: 1.85;
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; border-radius: 5px; }
.ha-line.ha-clickable { cursor: pointer; color: #e5e5e5; transition: background 0.15s ease, box-shadow 0.15s ease; }
.ha-line.ha-clickable:hover { background: #1c2333; }
.ha-line.ha-active { background: #1c2333; box-shadow: inset 3px 0 0 #5b8def; color: #ffffff; }
.ha-tag { color: #60a5fa; font-weight: 700; }
.ha-attr { color: #f2b96b; }
.ha-str { color: #9ece6a; }
.ha-sel { color: #f472b6; font-weight: 700; }
.ha-prop { color: #c586c0; }
.ha-val { color: #ce9178; }
.ha-implicit-hl { color: #ffd166; font-weight: 800; }
.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;
}
.ha-screen {
background: #ffffff;
padding: 1.2rem 1.4rem 1.4rem;
}
.ha-out-grid {
display: grid;
grid-template-columns: 100px 100px;
gap: 10px;
transition: outline 0.2s ease;
}
.ha-out-item {
background: steelblue;
color: white;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
font-family: Georgia, "Times New Roman", serif;
font-size: 1.1rem;
border-radius: 2px;
box-sizing: border-box;
padding: 20px 0;
transition: outline 0.2s ease;
}
.ha-out-lit { outline: 2px solid var(--accent); outline-offset: 2px; }
.ha-out-implicit { outline: 2px dashed #ffd166; outline-offset: 2px; }
.ha-note {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
font-size: 0.78rem;
color: var(--ink-soft);
}
</style>
</head>
<body>
<div class="infographic-gridbasic5" 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">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"container"</span>></span>
<span class="ha-line ha-clickable" data-part="item1"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>1</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable" data-part="item2"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>2</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable" data-part="item3"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>3</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable" data-part="item4"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>4</<span class="ha-tag">div</span>></span>
<span class="ha-line ha-clickable ha-active" data-part="item5"> <<span class="ha-tag">div</span> <span class="ha-attr">class</span>=<span class="ha-str">"item"</span>>5</<span class="ha-tag">div</span>></span>
<span class="ha-line"> </<span class="ha-tag">div</span>></span>
<span class="ha-line"></<span class="ha-tag">body</span>></span>
</div>
<div class="ha-codepane" id="pane-css">
<span class="ha-line"><span class="ha-sel">.container</span> {</span>
<span class="ha-line"> <span class="ha-prop">display</span>: <span class="ha-val">grid</span>;</span>
<span class="ha-line"> <span class="ha-prop">grid-template-columns</span>: <span class="ha-val">100px 100px</span>;</span>
<span class="ha-line"> <span class="ha-prop">gap</span>: <span class="ha-val">10px</span>;</span>
<span class="ha-line ha-clickable ha-active" data-part="item5"> <span class="ha-implicit-hl">/* no grid-template-rows — row 3 is implicit */</span></span>
<span class="ha-line">}</span>
<span class="ha-line"><span class="ha-sel">.item</span> {</span>
<span class="ha-line"> <span class="ha-prop">background</span>: <span class="ha-val">steelblue</span>;</span>
<span class="ha-line"> <span class="ha-prop">color</span>: <span class="ha-val">white</span>;</span>
<span class="ha-line"> <span class="ha-prop">padding</span>: <span class="ha-val">20px</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 Grid Basic</div>
</div>
<div class="ha-urlrow">127.0.0.1:5500/basicstructure.html</div>
<div class="ha-screen">
<div class="ha-out-grid" id="out-grid">
<div class="ha-out-item" id="out-item1">1</div>
<div class="ha-out-item" id="out-item2">2</div>
<div class="ha-out-item" id="out-item3">3</div>
<div class="ha-out-item" id="out-item4">4</div>
<div class="ha-out-item ha-out-implicit" id="out-item5">5</div>
</div>
</div>
</div>
<div class="ha-note" id="note-out">Only 2 columns are explicitly defined, and no grid-template-rows at all — with 5 items, the grid auto-creates a 3rd row (implicit) to fit item 5, sized to the content's natural height.</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');
});
const outMap = { item1: 'out-item1', item2: 'out-item2', item3: 'out-item3', item4: 'out-item4', item5: 'out-item5' };
const notes = {
item1: null, item2: null, item3: null, item4: null,
item5: "Only 2 columns are explicitly defined, and no grid-template-rows at all — with 5 items, the grid auto-creates a 3rd row (implicit) to fit item 5, sized to the content's natural height."
};
const note = document.getElementById('note-out');
document.querySelectorAll('.ha-line.ha-clickable').forEach(line => {
line.addEventListener('click', () => {
const part = line.getAttribute('data-part');
document.querySelectorAll('.ha-line').forEach(l => {
l.classList.toggle('ha-active', l.getAttribute('data-part') === part);
});
document.querySelectorAll('.ha-out-item').forEach(el => el.classList.remove('ha-out-lit'));
document.getElementById(outMap[part]).classList.add('ha-out-lit');
if (notes[part]) note.textContent = notes[part];
});
});
})();
</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!');
});