Welcome to Your Quick Reference

A beginner-friendly guide to every common HTML tag and CSS property, plus how to use them well. Not sure where to start? Open Style by Element in the sidebar, pick the thing you are working with (text, a list, a link, an image…), and see exactly which tags and CSS properties apply.

How this guide is organised

Section Use it when…
Style by Element You know what you want to style (a heading, a table, a button) but not how. Start here.
All HTML Elements You want the full catalogue of tags grouped by purpose, with a one-line definition and example.
All CSS Properties You want the full catalogue of properties grouped by what they affect (text, box model, layout, animation…).
CSS Selectors & Cascade You need to target the right element — classes, IDs, combinators, pseudo-classes, specificity.
Units, Colors & Functions You are unsure whether to use px, rem, %, fr, or how to write a color.
Live Editor Type HTML + CSS and see it render instantly. Load a preset.

Golden Rules of Web Development

1. Semantic HTML over "div soup"
A common beginner mistake is using <div> for everything. <div> works visually, but screen readers and search engines rely on meaningful tags (<header>, <nav>, <main>, <article>, <button>) to understand the page. Reach for a <div> only when no semantic element fits and you just need a styling wrapper.
2. Separation of concerns
HTML is structure. CSS is presentation. JavaScript is behaviour. Keep CSS in a stylesheet (or one <style> block), not in style="…" attributes scattered through the markup. Style with classes so the same rule can be reused.
3. Accessibility is not optional
Every image needs alt text. Every form field needs a <label>. Keyboard focus must stay visible. Text needs enough contrast against its background (aim for a 4.5:1 ratio). Use headings <h1>–<h6> in order without skipping levels.
4. Build mobile-first and responsive
Include <meta name="viewport" content="width=device-width, initial-scale=1">. Prefer relative units (rem, %, fr, ch) over fixed px for layout. Let content reflow; add @media queries to adjust at larger sizes.
5. Keep CSS maintainable
  • Set box-sizing: border-box once, globally, so padding and borders don't inflate widths.
  • Store repeated values (colors, spacing) in custom properties: --brand: #2563eb; then color: var(--brand);
  • Avoid !important. If you need it, your selectors are probably fighting each other.
  • Use gap for spacing between flex/grid items instead of margins on each child.
Things to avoid
  • Don't use <br> to create space between paragraphs — use CSS margin.
  • Don't use deprecated tags: <center>, <font>, <big>, <marquee>, <blink>, <strike>, <tt>, <frame>. They are obsolete.
  • Don't make a <div> or <span> clickable when you mean a <button> or <a>.
  • Don't remove focus outlines (outline: none) without providing a visible replacement.
  • Don't rely on color alone to convey meaning (e.g. red = error). Add text or an icon.

Style by Element

Pick what you are working with. You'll get the HTML tags involved, every CSS property that meaningfully styles it, best practices, and a runnable example you can open in the Live Editor.

All HTML Elements

Grouped by purpose. "Void" elements have no closing tag and no content (e.g. <img>, <br>).

Document & Metadata

TagDefinitionExample
<!DOCTYPE html>First line of every page; tells the browser to use standards mode.<!DOCTYPE html>
<html>Root element. Put lang on it for accessibility.<html lang="en">
<head>Container for metadata: title, links, scripts, styles. Not visible.<head>…</head>
<body>Contains everything visible on the page.<body>…</body>
<title>Text shown in the browser tab and search results.<title>My Site</title>
<meta>Metadata: charset, viewport, description, social cards. Void.<meta name="description" content="…">
<link>Links an external resource, most often a stylesheet or favicon. Void.<link rel="stylesheet" href="style.css">
<style>Internal CSS.<style>body{margin:0}</style>
<base>Sets a base URL/target for all relative links on the page. Void.<base href="/app/">
<script>Runs or links JavaScript. Add defer to load without blocking.<script src="app.js" defer></script>
<noscript>Content shown only when JavaScript is disabled.<noscript>Enable JS</noscript>

Sectioning & Semantic Structure

TagDefinitionExample
<header>Introductory content for the page or a section (logo, site nav, section heading).<header>…</header>
<nav>A block of major navigation links.<nav>…</nav>
<main>The unique primary content. Exactly one per page, not nested in article/aside.<main>…</main>
<section>A thematic grouping, normally with its own heading.<section>…</section>
<article>Self-contained content that would still make sense on its own (post, card, comment).<article>…</article>
<aside>Content tangential to the main content (sidebar, pull quote, related links).<aside>…</aside>
<footer>Closing content for a page or section (credits, links, copyright).<footer>…</footer>
<h1>–<h6>Headings, most to least important. One <h1> per page; never skip levels.<h2>Section title</h2>
<hgroup>Groups a heading with an adjacent subheading/tagline.<hgroup><h1>…</h1><p>…</p></hgroup>
<address>Contact information for the nearest article/page.<address>hi@site.com</address>
<search>Wraps a search/filter form (newer element).<search><form>…</form></search>

Grouping & Block Text

TagDefinitionExample
<p>A paragraph of text.<p>Hello.</p>
<div>Generic block container with no meaning. Use only for styling/layout grouping.<div class="row">…</div>
<hr>A thematic break between paragraph-level content. Void.<hr>
<pre>Preformatted text; whitespace and line breaks are preserved. Monospaced.<pre> kept spacing</pre>
<blockquote>A longer quotation from another source. cite attribute holds the URL.<blockquote cite="…">…</blockquote>
<figure>Self-contained media (image, diagram, code) referenced from the main text.<figure><img…><figcaption>…</figcaption></figure>
<figcaption>Caption for its parent <figure>.<figcaption>Fig 1</figcaption>
<ul> <ol> <li>Unordered list, ordered list, and list item. See the Lists section.<ul><li>A</li></ul>
<dl> <dt> <dd>Description list: wrapper, term, and its description. Good for key/value pairs.<dl><dt>HTML</dt><dd>markup</dd></dl>
<menu>A semantic unordered list of commands/toolbar items (behaves like <ul>).<menu><li><button>Copy</button></li></menu>

Inline Text Semantics

Meaning vs. looks. <strong> and <em> carry importance and emphasis (announced by screen readers). <b> and <i> are purely visual (bold / italic) with no added meaning. Prefer the semantic pair.
TagDefinitionExample
<a>Hyperlink. href is the destination. For links that open a new tab add rel="noopener".<a href="/about">About</a>
<span>Generic inline container with no meaning; a hook for styling part of a line.<span class="hl">word</span>
<strong>Strong importance / seriousness / urgency. Bold by default.<strong>Warning</strong>
<em>Stress emphasis that changes sentence meaning. Italic by default.<em>really</em>
<b>Draw attention without extra importance (keywords, product names). Bold.<b>Note</b>
<i>Alternate voice/mood: technical terms, foreign phrases, thoughts. Italic.<i>persona non grata</i>
<u>Non-textual annotation (e.g. misspelling). Rare — avoid confusing with links.<u>teh</u>
<s>Content no longer accurate/relevant (struck through).<s>$50</s> $40
<small>Side comments and fine print (disclaimers, copyright).<small>© 2026</small>
<mark>Text highlighted for reference (search hits, "look here").<mark>match</mark>
<abbr>Abbreviation. title gives the expansion on hover.<abbr title="Cascading Style Sheets">CSS</abbr>
<cite>Title of a cited work (book, film, article).<cite>Dune</cite>
<q>A short inline quotation; browser adds quotation marks.She said <q>hi</q>.
<dfn>The defining instance of a term.<dfn>API</dfn> is…
<code>An inline fragment of computer code. Monospaced.<code>array.map()</code>
<kbd>Keyboard (or other) user input.<kbd>Ctrl</kbd>+<kbd>C</kbd>
<samp>Sample output from a program.<samp>404 Not Found</samp>
<var>A variable in math or code.<var>x</var> + 1
<sub> / <sup>Subscript / superscript.H<sub>2</sub>O, x<sup>2</sup>
<time>A date/time in machine-readable form via datetime.<time datetime="2026-09-01">today</time>
<data>Content with a machine-readable value.<data value="42">forty-two</data>
<br>A line break where it is meaningful (poems, addresses). Void. Not for spacing.221B Baker St<br>London
<wbr>A suggested line-break opportunity inside a long word/URL. Void.super<wbr>longword
<bdi> / <bdo>Isolate / override text direction (for right-to-left scripts).<bdo dir="rtl">…</bdo>
<ruby> <rt> <rp>Ruby annotations (pronunciation guides above characters).<ruby>漢<rt>kan</rt></ruby>
<ins> / <del>Content that has been inserted / deleted (edit tracking).<del>old</del><ins>new</ins>

Images & Multimedia

TagDefinitionExample
<img>An image. Always give alt; give width/height to reserve space. Void.<img src="cat.jpg" alt="A grey cat" width="400" height="300">
<picture>Wraps <source> options + one <img> fallback for art direction / formats.<picture><source srcset="a.webp" type="image/webp"><img src="a.jpg" alt=""></picture>
<source>A candidate media file for <picture>, <audio>, <video>. Void.<source src="v.webm" type="video/webm">
<audio>Sound. Add controls for a player UI.<audio src="s.mp3" controls></audio>
<video>Video. Common attrs: controls, poster, muted, loop, playsinline.<video src="v.mp4" controls></video>
<track>Captions/subtitles for <video>/<audio>. Void.<track kind="captions" src="en.vtt" srclang="en">
<map> / <area>Defines clickable regions ("image map") over an image.<map name="m"><area shape="rect" coords="…" href="…"></map>
<svg>Inline vector graphics; can be styled/animated with CSS.<svg viewBox="0 0 10 10"><circle…/></svg>
<canvas>A bitmap drawing surface controlled by JavaScript.<canvas width="300" height="150"></canvas>

Embedded Content

TagDefinitionExample
<iframe>Embeds another HTML page (maps, videos, widgets). Add title; consider loading="lazy", sandbox.<iframe src="https://…" title="Map"></iframe>
<embed>External application/media via a plugin. Void. Rarely needed today.<embed src="f.pdf" type="application/pdf">
<object>Embeds a resource (PDF, image, another page) with a fallback.<object data="f.pdf" type="application/pdf"></object>
<param>Parameter for a parent <object>. Void. Deprecated.<param name="x" value="1">

Tables

TagDefinitionExample
<table>A table of data (rows and columns). Not for page layout.<table>…</table>
<caption>The table's title. First child of <table>.<caption>Q3 sales</caption>
<thead> <tbody> <tfoot>Groups the header rows, body rows, and footer/summary rows.<thead><tr>…</tr></thead>
<tr>A table row.<tr>…</tr>
<th>A header cell. Add scope="col" or scope="row".<th scope="col">Name</th>
<td>A data cell. colspan/rowspan merge cells.<td colspan="2">…</td>
<colgroup> / <col>Targets whole columns for styling (e.g. a background on column 2).<colgroup><col><col class="hi"></colgroup>

Forms & Input

TagDefinitionExample
<form>Groups controls for submission. action = where to send, method = get/post.<form action="/save" method="post">…</form>
<label>A caption bound to a control via for="id" (or by wrapping it). Required for accessibility.<label for="email">Email</label>
<input>A control. The type changes everything: text, email, password, number, tel, url, search, date, time, checkbox, radio, range, color, file, hidden, submit. Void.<input type="email" id="email" required>
<textarea>Multi-line text input.<textarea rows="4"></textarea>
<button>A button. Always set type: submit, reset, or button.<button type="submit">Send</button>
<select> <option> <optgroup>A drop-down, its choices, and grouped choices.<select><option value="1">One</option></select>
<datalist>Autocomplete suggestions for an <input> via list="id".<datalist id="cities"><option value="Paris"></datalist>
<fieldset> / <legend>Groups related controls with a visible caption (e.g. a set of radios).<fieldset><legend>Size</legend>…</fieldset>
<output>The result of a calculation or user action.<output name="sum">0</output>
<progress>Completion of a task (a loading/progress bar).<progress value="0.7"></progress>
<meter>A scalar measurement within a known range (disk usage, score).<meter value="6" max="10"></meter>

Interactive Elements

TagDefinitionExample
<details>A disclosure widget the user can open/close. No JavaScript needed.<details><summary>More</summary>…</details>
<summary>The always-visible label/heading for its <details>.<summary>FAQ</summary>
<dialog>A modal or non-modal dialog box. Open with .showModal().<dialog open>Hi</dialog>

Scripting & Templates

TagDefinitionExample
<template>Inert markup that is not rendered; cloned by JavaScript to build UI.<template id="row">…</template>
<slot>A placeholder inside a Web Component for projected content.<slot name="title"></slot>

Global Attributes (work on almost every tag)

AttributePurpose
idUnique name for one element; target for CSS #id, JS, and <label for>.
classOne or more reusable names for CSS/JS. The main styling hook.
styleInline CSS. Avoid — use classes instead.
titleAdvisory tooltip text on hover.
lang / dirLanguage and text direction (ltr/rtl).
hiddenHides the element (like display:none) until removed.
tabindex0 makes a non-focusable element focusable; -1 only via script. Avoid positive values.
data-*Custom data you define, e.g. data-user-id="7"; read in JS via dataset.
role, aria-*Accessibility hints for assistive tech when semantics aren't enough.
contenteditableMakes the element's text editable in place.

All CSS Properties

Grouped by what they affect. Many are shorthands (e.g. font, border, background, flex, grid, transition, animation) that set several longhand properties at once.

Typography & Text

PropertyDefinitionExample
colorText (foreground) color.color: #1e293b;
font-familyOrdered list of fonts; end with a generic (sans-serif).font-family: "Inter", system-ui, sans-serif;
font-sizeText size. Prefer rem so it respects user settings.font-size: 1.125rem;
font-weightThickness: 100–900, or normal/bold.font-weight: 600;
font-stylenormal, italic, or oblique.font-style: italic;
font-variantAlternate glyphs, e.g. small-caps.font-variant: small-caps;
fontShorthand: style, weight, size/line-height, family (in that order).font: italic 600 1rem/1.5 sans-serif;
line-heightVertical space per line. Unitless 1.4–1.7 for body text.line-height: 1.6;
letter-spacingSpace between characters (tracking).letter-spacing: 0.02em;
word-spacingExtra space between words.word-spacing: 4px;
text-alignleft, right, center, justify.text-align: center;
text-indentIndent of the first line of a block.text-indent: 2em;
text-decorationUnderline/overline/line-through + its color, style, thickness.text-decoration: underline dotted 2px;
text-transformuppercase, lowercase, capitalize.text-transform: uppercase;
text-shadowx, y, blur, color.text-shadow: 0 1px 2px rgba(0,0,0,.4);
text-overflowHow clipped text ends; use ellipsis with overflow:hidden;white-space:nowrap.text-overflow: ellipsis;
white-spaceHow whitespace/wrapping behave: normal, nowrap, pre, pre-wrap.white-space: nowrap;
word-break / overflow-wrapBreak long unbreakable strings (URLs) so they don't overflow.overflow-wrap: anywhere;
hyphensAllow automatic hyphenation (needs lang).hyphens: auto;
text-wrapbalance evens out short headings; pretty avoids orphans.text-wrap: balance;
writing-mode / directionVertical text; right-to-left flow.direction: rtl;
vertical-alignVertical alignment of inline/inline-block/table-cell content.vertical-align: middle;
tab-sizeWidth of a tab character inside <pre>.tab-size: 2;

Lists

PropertyDefinitionExample
list-style-typeMarker shape: disc, circle, square, decimal, lower-alpha, none…list-style-type: square;
list-style-positionoutside (default) or inside the content box.list-style-position: inside;
list-style-imageUse an image as the marker.list-style-image: url(dot.svg);
list-styleShorthand for the three above.list-style: none;
::markerPseudo-element to style just the bullet/number (color, size).li::marker { color: red; }

Color, Backgrounds & Opacity

PropertyDefinitionExample
opacityWhole-element transparency, 0–1 (affects children too).opacity: 0.6;
background-colorSolid fill behind the element.background-color: #f8fafc;
background-imageOne or more images / gradients (comma-separated, first on top).background-image: linear-gradient(#fff, #eee);
background-repeatno-repeat, repeat, repeat-x, space, round.background-repeat: no-repeat;
background-positionWhere the image sits.background-position: center top;
background-sizecover, contain, or explicit sizes.background-size: cover;
background-attachmentscroll, local, or fixed (parallax-ish).background-attachment: fixed;
background-clipHow far the background extends: border-box, padding-box, text.background-clip: text;
backgroundShorthand for all background-* in one line.background: #fff url(x.png) center/cover no-repeat;
mix-blend-mode / background-blend-modeBlend an element (or its layers) with what's behind, like Photoshop modes.mix-blend-mode: multiply;
accent-colorBrand color for checkboxes, radios, range, progress.accent-color: #2563eb;
caret-colorColor of the text-input blinking cursor.caret-color: #2563eb;

Borders & Outline

PropertyDefinitionExample
borderShorthand: width, style, color. Style is required to see it.border: 1px solid #cbd5e1;
border-width / -style / -colorIndividual pieces; each accepts up to 4 side values.border-style: dashed;
border-top / -right / -bottom / -leftStyle one side only.border-bottom: 2px solid #000;
border-radiusRounds corners. 50% on a square = circle.border-radius: 8px;
outlineLike a border but doesn't take up space; used for focus rings. Don't remove without a replacement.outline: 2px solid #2563eb;
outline-offsetGap between the outline and the border edge.outline-offset: 2px;
box-shadowx, y, blur, spread, color. inset for inner shadow. Comma-separate for layers.box-shadow: 0 4px 12px rgba(0,0,0,.1);

Box Model: Sizing & Spacing

Margin vs. padding. margin is space outside the border that pushes neighbours away. padding is space inside the border between the edge and the content. Set box-sizing: border-box so width includes padding and border.
PropertyDefinitionExample
box-sizingborder-box = width/height include padding+border. Set it globally.box-sizing: border-box;
width / heightExplicit size. Often better to let content decide.width: 320px;
min-width / max-widthLower/upper bound. max-width is key for responsive containers.max-width: 65ch;
min-height / max-heightLower/upper bound on height.min-height: 100vh;
aspect-ratioKeeps a width:height ratio as the element scales.aspect-ratio: 16 / 9;
marginOuter space. 1–4 values (all / y x / top x bottom / T R B L). auto centers a fixed-width block.margin: 0 auto;
margin-block / margin-inlineLogical margins (vertical / horizontal, direction-aware).margin-block: 1rem;
paddingInner space. Same 1–4 value pattern as margin.padding: 12px 16px;

Display, Positioning & Overflow

PropertyDefinitionExample
displayBox type: block, inline, inline-block, flex, grid, none, contents.display: flex;
visibilityhidden hides but keeps the space (unlike display:none).visibility: hidden;
positionstatic (default), relative, absolute, fixed, sticky.position: sticky;
top right bottom left / insetOffsets for a positioned element. inset: 0 pins all four.inset: 0;
z-indexStacking order among positioned/flex/grid items. Higher = in front.z-index: 10;
float / clearLegacy wrap-text-around technique. Prefer flex/grid for layout.float: left;
overflow (-x, -y)Content too big for the box: visible, hidden, scroll, auto, clip.overflow-x: auto;
object-fitHow a replaced element (img/video) fills its box: cover, contain.object-fit: cover;
object-positionWhich part of the image stays visible when cropped.object-position: top;

Flexbox (1-D layout)

PropertyDefinitionExample
display: flexMakes the element a flex container; children become flex items.display: flex;
flex-directionMain axis: row (default), column, *-reverse.flex-direction: column;
flex-wrapAllow items onto multiple lines.flex-wrap: wrap;
justify-contentAlign along the main axis: flex-start, center, space-between…justify-content: space-between;
align-itemsAlign along the cross axis: stretch, center, flex-start…align-items: center;
align-contentDistributes wrapped lines (only with flex-wrap: wrap).align-content: center;
align-selfOverride align-items for one item.align-self: flex-end;
gap / row-gap / column-gapSpacing between items. Cleaner than margins.gap: 16px;
flexItem shorthand: grow shrink basis. flex: 1 = share space equally.flex: 1 1 200px;
flex-grow / -shrink / -basisHow much an item grows, shrinks, and its starting size.flex-grow: 2;
orderReorder items visually without changing the HTML.order: -1;

CSS Grid (2-D layout)

Flexbox vs. Grid. Use Flexbox for one direction — a row of buttons, a nav bar, centering one thing. Use Grid when you control rows and columns — a gallery, a dashboard, a page shell.
PropertyDefinitionExample
display: gridMakes a grid container.display: grid;
grid-template-columnsColumn tracks. fr = fraction of free space; repeat() and minmax() help.grid-template-columns: repeat(3, 1fr);
grid-template-rowsRow tracks.grid-template-rows: auto 1fr auto;
grid-template-areasName regions and place items by name.grid-template-areas: "head head" "nav main";
grid-auto-flow / grid-auto-rowsHow and how big implicitly-created tracks are.grid-auto-rows: 120px;
gapGutter between rows and columns.gap: 20px;
grid-column / grid-rowWhich lines an item spans.grid-column: 1 / 3;
grid-areaPlace an item into a named area (or all four lines at once).grid-area: main;
justify-items / align-items / place-itemsAlign items inside their cells (inline / block / both).place-items: center;
justify-content / align-contentAlign the whole grid within the container when it's smaller.justify-content: center;

Transforms, Transitions & Animation

PropertyDefinitionExample
transitionAnimate property changes: property duration timing-function delay.transition: background .2s ease, transform .2s;
transformtranslate(), scale(), rotate(), skew(). Cheap to animate.transform: translateY(-2px) scale(1.03);
transform-originThe pivot point for transforms.transform-origin: top left;
animationRuns a @keyframes sequence: name duration timing iteration…animation: spin 1s linear infinite;
@keyframesDefines the steps of a named animation.@keyframes spin { to { transform: rotate(360deg); } }
will-changeHint the browser to optimise an upcoming animation. Use sparingly.will-change: transform;
@media (prefers-reduced-motion)Respect users who ask for less motion — disable big animations inside it.@media (prefers-reduced-motion: reduce) { * { animation: none; } }

Visual Effects & UI Behaviour

PropertyDefinitionExample
filterblur(), brightness(), grayscale(), drop-shadow()…filter: grayscale(1);
backdrop-filterFilter what's behind the element (frosted-glass effect).backdrop-filter: blur(8px);
clip-pathClip the element to a shape (circle, polygon).clip-path: circle(50%);
cursorPointer shape on hover: pointer, text, not-allowed, grab…cursor: pointer;
pointer-eventsnone lets clicks pass through the element.pointer-events: none;
user-selectWhether text can be selected: none, text, all.user-select: none;
resizeLet the user resize an element (usually <textarea>).resize: vertical;
scroll-behaviorsmooth animates jumps to #anchors.scroll-behavior: smooth;
appearancenone strips native styling from form controls so you can restyle them.appearance: none;

Table-specific Properties

PropertyDefinitionExample
border-collapsecollapse merges adjacent cell borders into one line.border-collapse: collapse;
border-spacingGap between cells when borders are separate.border-spacing: 4px;
table-layoutfixed makes columns size from the first row — faster, predictable.table-layout: fixed;
caption-sidePut the <caption> above or below.caption-side: bottom;

Custom Properties & At-Rules

FeatureDefinitionExample
--name / var()Reusable custom properties ("CSS variables"), often declared on :root.:root{--gap:16px} .box{padding:var(--gap)}
@mediaApply rules conditionally by viewport, orientation, theme, motion.@media (min-width: 768px) { … }
@supportsApply rules only if the browser supports a feature.@supports (display: grid) { … }
@font-faceLoad a custom web font.@font-face { font-family: "X"; src: url(x.woff2); }
@importPull in another stylesheet. Slower than <link> — avoid for performance.@import url("base.css");
@layerGroup rules into ordered cascade layers to tame specificity.@layer base, components, utilities;

All JavaScript Basics

HTML is structure, CSS is presentation, and JavaScript is behaviour — it's what makes a page react to clicks, validate a form, or update itself without reloading. This covers the core language and the DOM APIs you'll use every day.

Where your JavaScript goes

WayDefinitionExample
External filePreferred. Keeps JS out of your markup, and the browser can cache it.<script src="app.js" defer></script>
Inline blockJS written directly in the page. Fine for small demos.<script>console.log("hi");</script>
deferDownloads in the background, runs after the HTML is parsed, in order. Use this for most scripts.<script src="a.js" defer></script>
asyncDownloads in the background, runs as soon as it's ready (order not guaranteed). Good for independent, analytics-style scripts.<script src="a.js" async></script>
No attribute, in <head>Blocks HTML parsing until it downloads and runs. Avoid — prefer defer or place before </body>.<script src="a.js"></script>

Variables & data types

Keyword / typeDefinitionExample
letA variable that can be reassigned later. Default choice for values that change.let count = 0; count = count + 1;
constA variable that can't be reassigned. Prefer this unless you know the value will change.const name = "Ada";
varThe old way to declare a variable. Avoid in new code — scoping rules are confusing.var x = 1; // legacy
StringText, in quotes. Template literals (backticks) let you embed variables.const s = `Hi, ${name}!`;
NumberAny numeric value — no separate "integer" type.const price = 19.99;
Booleantrue or false.const isOpen = true;
ArrayAn ordered, numbered list of values.const colors = ["red", "green", "blue"];
ObjectNamed key/value pairs.const user = { name: "Ada", age: 30 };
nullDeliberately "no value", set by you.let selected = null;
undefinedA variable that exists but hasn't been given a value yet.let x; // undefined
typeofReturns a string naming a value's type — useful for debugging.typeof "hi"; // "string"
Use const by default, let when a value must change, and skip var entirely. It signals intent to anyone reading your code and catches accidental reassignment as an error.

Operators

OperatorDefinitionExample
+ - * / %Add, subtract, multiply, divide, remainder. + also joins strings."Hi " + name; 7 % 2; // 1
=== / !==Strict equal / not equal — compares value and type. Use these, always."5" === 5; // false
== / !=Loose equal — converts types first, which causes surprising bugs. Avoid."5" == 5; // true (surprising)
&& / ||Logical AND / OR, for combining conditions.isOpen && hasStock
!Logical NOT — flips a boolean.!isOpen
?:Ternary — a compact one-line if/else that returns a value.const label = isOpen ? "Open" : "Closed";
??Nullish coalescing — falls back only for null/undefined (unlike ||, keeps 0 or "").const n = count ?? 0;
+= -= ++ --Update a variable in place.count += 1; count++;

Conditionals

FormDefinitionExample
if / else if / elseRun different code depending on a condition.if (score >= 90) grade = "A";
else if (score >= 80) grade = "B";
else grade = "C";
switchCompares one value against several exact cases. Don't forget break.switch (day) {
  case "Sat": case "Sun": isWeekend = true; break;
  default: isWeekend = false;
}

Loops

FormDefinitionExample
forRepeat a set number of times, with a counter you control.for (let i = 0; i < 5; i++) { console.log(i); }
for…ofLoop over the values of an array (or any iterable). The one you'll use most.for (const c of colors) { console.log(c); }
for…inLoop over the keys of an object. Rarely needed for arrays.for (const key in user) { console.log(key); }
whileRepeat while a condition stays true. Make sure something inside changes it.while (queue.length) { process(queue.shift()); }
break / continueExit a loop early, or skip to the next iteration.if (item === target) break;

Functions

FormDefinitionExample
Function declarationA named, reusable block of code. Can be called before it's defined ("hoisted").function add(a, b) {
  return a + b;
}
Arrow functionA shorter function syntax. Doesn't get its own this — convenient for callbacks.const add = (a, b) => a + b;
Parameters & default valuesInputs a function accepts; give one a fallback with =.function greet(name = "friend") { return `Hi ${name}`; }
returnSends a value back to the caller and exits the function immediately.return total;
Calling a functionRuns it. Forgetting the parentheses just refers to the function itself.add(2, 3); // 5

Arrays: the methods you'll actually use

Method / propertyDefinitionExample
.lengthHow many items are in the array.colors.length; // 3
arr[i]Read or set the item at index i (counting from 0).colors[0]; // "red"
.push(x) / .pop()Add to the end / remove from the end.colors.push("purple");
.includes(x)Does the array contain this value?colors.includes("red"); // true
.indexOf(x)Position of a value, or -1 if not found.colors.indexOf("green"); // 1
.forEach(fn)Run a function once per item. Doesn't return anything.colors.forEach(c => console.log(c));
.map(fn)Build a new array by transforming every item.const upper = colors.map(c => c.toUpperCase());
.filter(fn)Build a new array of only the items that pass a test.const long = colors.filter(c => c.length > 4);
.find(fn)The first item that passes a test, or undefined.colors.find(c => c.startsWith("g"));
.join(sep)Combine every item into one string.colors.join(", "); // "red, green, blue"
.sort()Sorts in place. For numbers, pass a compare function or you'll get string order.nums.sort((a, b) => a - b);

Objects

FormDefinitionExample
Dot notationRead/write a property when you know its name up front.user.name; user.age = 31;
Bracket notationRead/write a property using a variable or a name with special characters.const key = "name"; user[key];
MethodA function stored as a property.const user = { greet() { return "Hi " + this.name; } };
Object.keys(obj)An array of an object's property names.Object.keys(user); // ["name", "age"]
Spread { ...obj }Copy an object's properties into a new one, optionally overriding some.const updated = { ...user, age: 31 };
DestructuringUnpack properties into their own variables.const { name, age } = user;

Selecting elements from the page

MethodDefinitionExample
document.querySelector(sel)The first element matching any CSS selector, or null.const btn = document.querySelector(".save-btn");
document.querySelectorAll(sel)All matching elements, as a static list you can loop with for…of.document.querySelectorAll("li").forEach(li => …);
document.getElementById(id)The one element with that id (no #). Slightly faster than querySelector.document.getElementById("main-nav");
el.closest(sel)Walks up from el to the nearest ancestor (or itself) matching the selector.e.target.closest(".card");
el.children / el.parentElementAn element's direct child elements, or its parent.list.children.length;

Reading & changing content

PropertyDefinitionExample
el.textContentGet/set plain text. Always safe — never interpreted as HTML.el.textContent = "Saved!";
el.innerHTMLGet/set markup inside the element. Never assign untrusted/user-typed text this way.el.innerHTML = "<strong>Hi</strong>";
el.valueThe current value of a form control (input, textarea, select).const typed = document.querySelector("#email").value;
el.setAttribute(name, val) / getAttribute(name)Read or write any HTML attribute by name.img.setAttribute("alt", "A cat");
el.datasetRead/write data-* attributes as camelCase properties.<li data-id="7"> → li.dataset.id

Changing style & classes

Property / methodDefinitionExample
el.style.propertySet one inline CSS property (camelCase name). Fine for one-off dynamic values.el.style.backgroundColor = "gold";
el.classList.add(x)Add a class — the usual way to trigger a CSS-defined visual state.el.classList.add("open");
el.classList.remove(x)Remove a class.el.classList.remove("open");
el.classList.toggle(x)Add it if missing, remove it if present — perfect for on/off UI.el.classList.toggle("active");
el.classList.contains(x)Is that class currently applied?if (el.classList.contains("open")) …
Prefer classList over el.style. Define the look in CSS, then use JS only to flip a class on or off. It keeps behaviour and presentation separate and makes the state easy to find in your stylesheet.

Events

ConceptDefinitionExample
el.addEventListener(type, fn)Run fn whenever that event fires on el.btn.addEventListener("click", () => alert("Hi"));
"click"A mouse click (or tap) on the element.btn.addEventListener("click", handleClick);
"input"Fires immediately as a text field's value changes, keystroke by keystroke.field.addEventListener("input", handleInput);
"change"Fires once a value is committed (field loses focus, or a select/checkbox changes).select.addEventListener("change", handleChange);
"submit"Fires when a <form> is submitted. Almost always paired with preventDefault().form.addEventListener("submit", handleSubmit);
"keydown"A key is pressed. Check event.key for which one.input.addEventListener("keydown", e => { if (e.key === "Enter") … });
event.targetThe exact element the event happened on.btn.addEventListener("click", e => console.log(e.target));
event.preventDefault()Stops the browser's default action (following a link, submitting a form).form.addEventListener("submit", e => e.preventDefault());

Creating & removing elements

MethodDefinitionExample
document.createElement(tag)Makes a new element, not yet on the page.const li = document.createElement("li");
parent.appendChild(el)Adds el as the last child of parent.list.appendChild(li);
parent.append(el)Like appendChild, but also accepts plain text and multiple arguments.list.append(li, "some text");
el.remove()Removes the element from the page entirely.li.remove();
parent.insertBefore(new, ref)Inserts new right before the ref child.list.insertBefore(li, list.firstChild);

Console & debugging

ToolDefinitionExample
console.log()Print a value to the DevTools console — your main debugging tool.console.log("user is", user);
console.error() / console.warn()Like log, but styled as an error/warning in the console.console.error("Failed to save");
debugger;Pauses execution right there if DevTools is open, so you can step through code.function calc() { debugger; return total; }
Habits that save you time
  • Always use === / !==, never == / !=.
  • const by default; reach for let only when a value must change.
  • Name functions and variables for what they hold or do — isVisible, not flag.
  • Read the error message and the line number first — most bugs are exactly where it says.
  • Keep DOM lookups (querySelector) out of loops; look the element up once and reuse it.
Things to avoid
  • Don't assign user-typed text to innerHTML — it can inject markup/scripts. Use textContent.
  • Don't compare with ==; type coercion produces surprises like "" == 0 being true.
  • Don't forget break in a switch — execution "falls through" into the next case.
  • Don't rely on var — its function-wide scoping causes bugs let/const avoid.

CSS Selectors & the Cascade

A property does nothing until a selector aims it at elements. This is how you say "these ones".

Basic selectors

SelectorMatchesExample
*Every element. Handy for a reset; slow if overused.* { box-sizing: border-box; }
pAll elements of that type.p { margin-bottom: 1rem; }
.cardElements with class="card". The workhorse — prefer these..card { padding: 1rem; }
#heroThe one element with id="hero". High specificity — use sparingly.#hero { height: 80vh; }
[type="email"]Attribute match. Also [disabled], [href^="https"] (starts with), [href$=".pdf"] (ends with), [class*="col"] (contains).input[type="email"] { … }
h1, h2, h3Group — apply the same rule to several selectors.h1, h2, h3 { font-family: serif; }

Combinators (relationships)

SelectorMatchesExample
A BAny B inside an A (descendant, any depth).nav a { color: white; }
A > BB that is a direct child of A.ul > li { … }
A + BThe B immediately after an A (next sibling).h2 + p { margin-top: 0; }
A ~ BEvery B sibling that comes after an A.h2 ~ p { color: #555; }

Pseudo-classes (state & position)

A quick list is below. For the syntax, the nth formula, the -child vs -of-type families, and :is() / :where() / :has(), see Pseudo-Classes in Depth in the sidebar.

SelectorMatchesExample
:hoverPointer is over the element.a:hover { text-decoration: underline; }
:focus / :focus-visibleElement is focused / focused via keyboard. Style focus — don't hide it.button:focus-visible { outline: 2px solid; }
:activeBeing clicked/pressed.button:active { transform: translateY(1px); }
:visitedA link the user has been to.a:visited { color: purple; }
:first-child / :last-childFirst / last among its siblings.li:last-child { border-bottom: none; }
:nth-child(n)By position: 2, odd, even, 3n. Great for zebra striping.tr:nth-child(even) { background: #f8fafc; }
:not(sel)Everything except what matches sel.li:not(.active) { opacity: .6; }
:checked / :disabled / :requiredForm-control states.input:disabled { background: #eee; }
:rootThe <html> element — where custom properties usually live.:root { --brand: #2563eb; }
:is() / :where()Shorten grouped selectors. :where() adds zero specificity.:is(h1,h2,h3) code { font-size: .9em; }

Pseudo-elements (style a sub-part)

SelectorMatchesExample
::before / ::afterInserts generated content; needs a content value..req::after { content: " *"; color: red; }
::first-line / ::first-letterThe first line / first letter of a block (drop caps).p::first-letter { font-size: 2em; }
::placeholderPlaceholder text in an input.input::placeholder { color: #94a3b8; }
::selectionText the user has highlighted.::selection { background: #fde68a; }
::markerA list item's bullet or number.li::marker { color: #2563eb; }

Specificity & the cascade

When two rules set the same property on the same element, the winner is decided by, in order: 1) !important (avoid it), 2) specificity — inline style > #id > .class / [attr] / :pseudo-class > element / ::pseudo-element, 3) source order — the last matching rule wins.
Keep specificity low and flat. Favour single class selectors (.btn-primary) over long chains (header nav ul li a.link). Low, even specificity makes CSS predictable and easy to override later.

Pseudo-Classes in Depth

A pseudo-class targets an element that is in a certain state (hovered, checked, disabled…) or position (first, last, every third…). This page covers the syntax, the cryptic nth formula, the look-alike families, and the modern :is() / :where() / :not() / :has() group.

One colon or two? : is a pseudo-class — "match an element that is something" (:hover, :checked, :first-child). :: is a pseudo-element — "style a part of an element, or invent one" (::before, ::marker, ::selection). This page is only the one-colon kind.

1 · Reading the syntax

/* the pointer is over the button */
.btn:hover { background: #1d4ed8; }

/* a link that is BOTH not .active AND being hovered */
nav a:not(.active):hover { text-decoration: underline; }

/* the <a> inside the FIRST <li> of any nav list */
nav ul li:first-child > a { font-weight: 700; }

/* every checkbox that is checked and enabled */
input[type="checkbox"]:checked:enabled { accent-color: green; }

2 · The An + B formula

:nth-child(), :nth-of-type(), :nth-last-child() and :nth-last-of-type() all take a formula An + B. To read it, plug in n = 0, 1, 2, 3, … and every result that lands on a real position matches. A is the step, B is the offset.

    FormulaMatches (positions)Reads as
    3just the 3rda fixed position (same as 0n+3)
    odd = 2n+11, 3, 5, 7, …every 2nd, starting at 1
    even = 2n2, 4, 6, 8, …every 2nd, starting at 2
    3n3, 6, 9, …every 3rd (n=1→3, n=2→6…; n=0→0 is skipped)
    3n+11, 4, 7, 10, …every 3rd, starting at 1
    3n-1 = 3n+22, 5, 8, 11, …every 3rd, starting at 2
    n+33, 4, 5, 6, …the 3rd onward (A=1, so every one, offset by 3)
    -n+31, 2, 3the first 3 only (A is negative, so it counts down)
    2n+33, 5, 7, 9, …every 2nd, starting at 3
    nevery element1n+0 — matches all
    Select a range. Combine two nths: li:nth-child(n+3):nth-child(-n+7) matches items 3 through 7 (the 3rd onward and within the first 7).

    3 · -child vs -of-type

    The whole positional family comes in two flavours. :*-child counts every sibling regardless of tag. :*-of-type counts only siblings with the same tag.

    Counts all siblingsCounts same-tag siblingsMeaning
    :first-child:first-of-typethe first one
    :last-child:last-of-typethe last one
    :only-child:only-of-typethe only one (no siblings)
    :nth-child(…):nth-of-type(…)by position from the start
    :nth-last-child(…):nth-last-of-type(…)by position from the end
    The classic trap. p:first-child does not mean "the first <p>". It means "a <p> that is also the first child of its parent" — so it matches nothing here, because the first child is the <h2>:
    <section>
      <h2>Title</h2>
      <p>First paragraph.</p>   <!-- you want no top-margin here -->
      <p>Second paragraph.</p>
    </section>
    
    /* MISSES: the first child is the <h2>, not a <p> */
    p:first-child { margin-top: 0; }
    
    /* WORKS: the first <p> among the <p> siblings */
    p:first-of-type { margin-top: 0; }

    4 · Other structural pseudo-classes

    SelectorMatchesExample
    :rootThe top element — <html>. Higher priority than a plain html selector; the home of custom properties.:root { --brand: #2563eb; }
    :emptyAn element with no child elements and no text — not even a space. (A newline and indentation count as text, so it must be truly <div></div>.)p:empty { display: none; }
    :nth-child(2 of .card)The 2nd element that matches .card among its siblings (the "of S" syntax — newer, filters before counting).li:nth-child(odd of :not(.hidden))

    5 · Link & interaction states

    SelectorMatchesNotes
    :linkAn <a> with an href that has not been visited.Rarely needed; usually just style a.
    :visitedA link the browser has in history.Privacy-limited: only color, background-color, border-color, outline-color can change, and only to opaque colours.
    :hoverThe pointer is over the element (or a child).Doesn't exist on touch — never hide anything essential behind it.
    :activeBetween mouse-down and mouse-up — the "being pressed" moment.
    :focusThe element has keyboard/programmatic focus.
    :focus-visibleFocused and the browser thinks a focus ring should show (i.e. keyboard, not a mouse click).Use this for outlines so mouse users don't see a ring on click.
    :focus-withinThis element, or anything inside it, has focus.Great for highlighting a form row or an open dropdown's container.
    :targetThe element whose id matches the current URL #hash.:target { background: #fff3bf; } to flash a linked section.
    Order matters: "LoVe / HAte" — L V H A. :link, :visited, :hover, :active. They all have the same specificity, so the last matching rule wins. Put :hover before :visited and a visited link will never show its hover colour. (Add :focus just before :hover.)
    /* the safe link recipe, in the right order */
    a:link    { color: #2563eb; }
    a:visited { color: #7c3aed; }
    a:focus-visible { outline: 2px solid #2563eb; outline-offset: 2px; }
    a:hover   { color: #1d4ed8; }
    a:active  { color: #b91c1c; }
    
    /* light up a whole form row while any field inside it is focused */
    .field:focus-within { background: #eff6ff; }
    
    /* highlight the section you jumped to via a #link */
    :target { scroll-margin-top: 5rem; background: #fef9c3; }

    6 · Form & input states

    SelectorMatches
    :checkedA ticked checkbox / radio, or a selected <option>.
    :indeterminateA checkbox set to the "half" state via JavaScript, or a radio group with nothing chosen.
    :defaultThe control that is the default in its group (a pre-checked radio, the submit button).
    :disabled / :enabledHas / doesn't have the disabled attribute.
    :required / :optionalHas / doesn't have the required attribute.
    :read-only / :read-writeCan't / can be edited by the user.
    :placeholder-shownAn empty field that is currently showing its placeholder text.
    :valid / :invalidPasses / fails its built-in constraints (type, pattern, required…). Applies immediately, even before the user touches it.
    :user-valid / :user-invalidLike the above, but only after the user has interacted with the field. Usually what you actually want for error styling.
    :in-range / :out-of-rangeA numeric / date input inside or outside its min–max.
    :autofillA field the browser has auto-filled.
    /* show the error state only once the user has left an invalid field */
    input:user-invalid { border-color: #dc2626; }
    input:user-invalid + .error-msg { display: block; }
    
    /* style a checkbox's own label by targeting the next sibling */
    input[type="checkbox"]:checked + label { font-weight: 700; }
    
    /* …or the label WRAPPING the checkbox, with :has() */
    label:has(input:checked) { background: #dbeafe; }
    
    /* a "floating label" that lifts once the field has content */
    .float input:not(:placeholder-shown) + label { transform: translateY(-1.2em) scale(.85); }
    
    /* mark required fields with an asterisk, no extra markup */
    label:has(+ input:required)::after { content: " *"; color: #dc2626; }

    7 · The logical group: :is() :where() :not() :has()

    These four take a selector list as their argument and are how you build the "pre-defined combinations" — they replace long, repetitive selectors.

    SelectorMatchesSpecificity
    :not(X) Elements that do not match X. Takes a list: :not(h1, h2, h3) = "none of these". Adds the specificity of its most specific argument (:not(.x) counts as a class).
    :is(A, B, C) Matches if the element matches any of A/B/C. Factor out repetition. Takes the specificity of its most specific argument.
    :where(A, B, C) Identical to :is() in what it matches… …but always contributes zero specificity. Use it for base / reset styles you want to be trivially overridable.
    :has(Y) An element that contains something matching Y (the "parent selector"). Y is relative: :has(> img), :has(+ p), :has(h2). Most specific argument, like :is().
    /* :is() — one rule instead of three */
    :is(section, article, aside) > h2 { margin-top: 0; }
    /* …without :is() you'd write: */
    section > h2, article > h2, aside > h2 { margin-top: 0; }
    
    /* :where() — zero-specificity base styles, easy to override later */
    :where(ul, ol) { margin: 0; padding: 0; }
    
    /* :not() — every list item except the last gets a divider */
    li:not(:last-child) { border-bottom: 1px solid #e2e8f0; }
    
    /* :has() — style the container based on its contents */
    .card:has(img)            { padding-top: 0; }        /* cards WITH an image */
    article:has(> h2)          { border-left: 3px solid; } /* direct-child h2 */
    h2:has(+ p)               { margin-bottom: .3em; }   /* h2 right before a p */
    form:has(:invalid) button { opacity: .5; }           /* disable submit look */
    .gallery:has(img:hover) img:not(:hover) { opacity: .4; } /* dim the rest */
    Forgiving vs. strict. :is() and :where() quietly ignore any argument the browser doesn't understand, so one unknown selector won't kill the whole rule. :not() is strict — an invalid argument invalidates the selector.

    8 · Quick reference — every pseudo-class

    SelectorMatchesExample
    :hoverpointer over it.btn:hover
    :activebeing pressed.btn:active
    :focushas focusinput:focus
    :focus-visiblefocus that should show a ringa:focus-visible
    :focus-withinit or a descendant has focus.row:focus-within
    :link / :visitedunvisited / visited linka:visited
    :targetid matches the URL hash:target
    :rootthe <html> element:root{--x:1}
    :emptyno children, no texttd:empty
    :first-child / :last-childfirst / last of all siblingsli:last-child
    :only-childhas no siblingsp:only-child
    :nth-child(f) / :nth-last-child(f)by position from start / endtr:nth-child(even)
    :first-of-type / :last-of-typefirst / last of that tagp:first-of-type
    :only-of-typethe only one of that tagimg:only-of-type
    :nth-of-type(f) / :nth-last-of-type(f)by position among same tagp:nth-of-type(2)
    :not(S)does not match S:not(.active)
    :is(S, …)matches any of the list:is(h1,h2) a
    :where(S, …)like :is(), zero specificity:where(a) {}
    :has(S)contains something matching S.card:has(img)
    :checkedticked / selected controlinput:checked
    :indeterminatethe "mixed" checkbox stateinput:indeterminate
    :defaultthe default control in a groupoption:default
    :disabled / :enableddisabled / not disabledbutton:disabled
    :required / :optionalrequired / not required fieldinput:required
    :read-only / :read-writenot editable / editableinput:read-only
    :placeholder-shownempty field showing its placeholderinput:placeholder-shown
    :valid / :invalidpasses / fails constraints (immediately)input:invalid
    :user-valid / :user-invalid…but only after the user interactsinput:user-invalid
    :in-range / :out-of-rangenumeric value inside / outside min–maxinput:out-of-range
    :autofillbrowser-autofilled fieldinput:autofill
    :lang(xx) / :dir(rtl)content language / text direction:lang(fr) q
    :defineda defined element (built-in, or a registered custom element)my-widget:defined
    :modalan element in modal state (an open <dialog>.showModal())dialog:modal
    :popover-opena popover that is currently showing[popover]:popover-open
    :fullscreenthe element shown fullscreenvideo:fullscreen

    9 · Gotchas to remember

    • :first-child means "is the first child", not "the first child of this type". Use :first-of-type for the latter.
    • :nth-child counts every sibling; :nth-of-type counts only same-tag siblings. They give different results whenever the children are mixed tags.
    • ::before, ::after, ::first-line are pseudo-elements (two colons). They are not in this list.
    • Link states must be ordered L V H A or later rules will hide earlier ones.
    • :visited can only change a few colour properties, and JavaScript can't read whether it matched — both for privacy.
    • :not() and :is() keep the specificity of their most specific argument. :where() is the only one that adds nothing.
    • A newline and indentation inside a tag count as text, so :empty won't match an element that merely looks empty in your source.

    Units, Colors & Functions

    Length units

    UnitWhat it isUse for
    pxOne CSS pixel (absolute).Borders, small fixed details, hairlines.
    remRelative to the root font size (usually 16px).Font sizes and spacing. Scales with user settings; predictable.
    emRelative to this element's font size.Spacing that should track the local text size (padding inside a button).
    %Relative to the parent's corresponding dimension.Fluid widths inside a container.
    vw / vh1% of the viewport width / height.Full-screen sections, hero heights. Watch mobile address bars — see dvh.
    dvh / svh / lvhDynamic / small / large viewport height.100dvh for reliable full-height on mobile.
    chWidth of the "0" character.Line length: max-width: 65ch for readable paragraphs.
    frA fraction of leftover space (Grid only).grid-template-columns: 2fr 1fr;

    Writing colors

    FormExampleNotes
    Namedcolor: rebeccapurple;~150 keywords. Fine for prototyping.
    Hex#2563eb / #25f / #2563ebcc3, 6, or 8 digits (last pair = alpha).
    rgb()rgb(37 99 235 / 0.8)Modern syntax uses spaces + / alpha.
    hsl()hsl(220 83% 53%)Hue-Saturation-Lightness — easy to tweak by hand.
    oklch()oklch(0.62 0.19 255)Perceptually even; great for generating consistent palettes.
    currentColorborder-color: currentColor;Reuses the element's color value.
    transparentbackground: transparent;Fully see-through.
    Contrast. Body text should hit a contrast ratio of at least 4.5:1 against its background (3:1 for large text). Check with your browser's dev-tools color picker.

    Useful functions

    FunctionWhat it doesExample
    calc()Mix units in one value.width: calc(100% - 2rem);
    min() / max()Pick the smaller / larger of several values.width: min(90%, 1100px);
    clamp()min, preferred, max — fluid type without media queries.font-size: clamp(1rem, 2.5vw, 1.5rem);
    var()Read a custom property, with optional fallback.color: var(--brand, #2563eb);
    url()Reference an image/font/resource.background-image: url("hero.jpg");
    linear-gradient() / radial-gradient()Generate an image from color stops.background: linear-gradient(90deg, #2563eb, #7c3aed);

    Layout Patterns & Examples

    Real markup for real pages — whole-page skeletons first, then the components that go inside them. Every block is commented. Copy one, swap the words for your own, and you have an accessible starting point.

    The mental model. A page is like a textbook: <main> is the book, <article> is a self-contained chapter, <section> is a sub-topic with its own heading, and <p> holds the sentences. Nest your tags to match that outline and you get a logical document, keyboard/screen-reader navigation, and better SEO for free.
    Whole-page skeletons

    1. The complete document

    Every page starts here. The <head> is configuration the visitor never sees; the <body> is everything they do.

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <!-- Always first: character encoding -->
      <meta charset="UTF-8">
      <!-- Makes the page scale correctly on phones -->
      <meta name="viewport" content="width=device-width, initial-scale=1">
    
      <!-- Shown in the browser tab and search results -->
      <title>Sourdough for Beginners – The Bakehouse</title>
      <!-- The grey text under the title in Google results -->
      <meta name="description" content="A step-by-step guide to your first loaf.">
    
      <!-- Tab icon, and social-share preview -->
      <link rel="icon" href="/favicon.svg">
      <meta property="og:title" content="Sourdough for Beginners">
      <meta property="og:image" content="https://example.com/loaf.jpg">
    
      <!-- Your styles. Put <script> near </body> or use defer. -->
      <link rel="stylesheet" href="/styles.css">
      <script src="/app.js" defer></script>
    </head>
    <body>
      <!-- Visible content lives here -->
    </body>
    </html>

    2. A standard content page

    The chrome that wraps almost every page: a skip link for keyboard users, the site header and navigation, one <main>, and a footer.

    <body>
      <!-- First focusable element: lets keyboard users jump past the nav -->
      <a class="skip-link" href="#main">Skip to content</a>
    
      <!-- Site-wide header: appears on every page -->
      <header class="site-header">
        <a href="/" class="logo">The Bakehouse</a>
    
        <nav aria-label="Primary">
          <ul>
            <li><a href="/">Home</a></li>
            <!-- aria-current marks the page you're on -->
            <li><a href="/guides" aria-current="page">Guides</a></li>
            <li><a href="/about">About</a></li>
          </ul>
        </nav>
      </header>
    
      <!-- The one unique block of content for THIS page -->
      <main id="main">
        <h1>Baking Guides</h1>
        <p>Choose a recipe to get started.</p>
      </main>
    
      <!-- Site-wide footer -->
      <footer class="site-footer">
        <nav aria-label="Footer">
          <a href="/privacy">Privacy</a>
          <a href="/contact">Contact</a>
        </nav>
        <p>&copy; 2026 The Bakehouse</p>
      </footer>
    </body>
    One <h1> per page. It names the whole page. Everything else steps down: <h2> for sections, <h3> inside those. Never skip a level to get a smaller size — style it with CSS instead.

    3. A blog post / article page

    An <article> is content that would still make sense on its own (in a feed reader, shared on its own URL). Its <header> carries the title and byline; each <section> is a topic within it.

    <main>
      <article>
    
        <!-- Article intro: title, author, date, hero image -->
        <header>
          <h1>How to Bake Sourdough Bread</h1>
          <p class="byline">
            By <a rel="author" href="/authors/john-doe">John Doe</a>
            <!-- machine-readable date, human-readable text -->
            <time datetime="2026-03-14">March 14, 2026</time>
          </p>
          <figure>
            <img src="/loaf.jpg" alt="A cross-section of a sourdough loaf" width="800" height="500">
            <figcaption>An open, airy crumb is the goal.</figcaption>
          </figure>
        </header>
    
        <!-- First topic -->
        <section>
          <h2>The Ingredients</h2>
          <p>Flour is the most important component of your bread.</p>
          <p>You will also need filtered water and salt.</p>
        </section>
    
        <!-- Second topic -->
        <section>
          <h2>The Instructions</h2>
          <ol>
            <li>Mix the ingredients in a large bowl.</li>
            <li>Let the dough rise for at least four hours.</li>
            <li>Bake at 450&deg;F for 40 minutes.</li>
          </ol>
        </section>
    
        <footer>
          <p>Filed under
            <a href="/tags/bread" rel="tag">bread</a>,
            <a href="/tags/beginner" rel="tag">beginner</a>.
          </p>
        </footer>
    
      </article>
    
      <!-- Related to the page but not part of the article itself -->
      <aside aria-label="Related recipes">
        <h2>You might also like</h2>
        <ul>
          <li><a href="/no-knead">No-knead bread</a></li>
          <li><a href="/focaccia">Rosemary focaccia</a></li>
        </ul>
      </aside>
    </main>

    4. A marketing / landing page

    A run of full-width <section>s, each with its own heading. The hero, the value props, social proof, and a final call to action.

    <main>
    
      <!-- Hero: the one-sentence pitch + primary action -->
      <section class="hero">
        <h1>Ship your side project this weekend</h1>
        <p>Starter kits, hosting, and a domain in one click.</p>
        <a class="btn btn-primary" href="/signup">Start free</a>
        <a class="btn btn-ghost" href="#features">See how it works</a>
      </section>
    
      <!-- Features: a heading + a list of cards -->
      <section id="features" aria-labelledby="features-h">
        <h2 id="features-h">Everything included</h2>
        <ul class="feature-grid">
          <li>
            <h3>One-click deploy</h3>
            <p>Push to main and we build it.</p>
          </li>
          <li>
            <h3>Free SSL</h3>
            <p>HTTPS on every domain, automatically.</p>
          </li>
          <li>
            <h3>Global CDN</h3>
            <p>Fast everywhere, no config.</p>
          </li>
        </ul>
      </section>
    
      <!-- Social proof -->
      <section aria-labelledby="quote-h">
        <h2 id="quote-h" class="visually-hidden">What customers say</h2>
        <figure>
          <blockquote><p>I launched in an afternoon. Genuinely.</p></blockquote>
          <figcaption>&mdash; Priya N., <cite>indie developer</cite></figcaption>
        </figure>
      </section>
    
      <!-- Closing call to action -->
      <section class="cta">
        <h2>Ready to build?</h2>
        <a class="btn btn-primary" href="/signup">Create your account</a>
      </section>
    
    </main>
    Section vs. div. Reach for <section> when the group of content has a heading and belongs in the page outline. If you only need a box to hang CSS on, that's a <div>. A <section> with no heading is usually a <div> in disguise.

    5. Documentation layout (sidebar + content)

    Two columns: a navigation <aside> and the <main> article. CSS Grid or Flexbox places them side by side; the markup order still puts content first.

    <div class="docs-layout">
    
      <!-- Secondary navigation for this docs area -->
      <aside class="docs-nav">
        <nav aria-label="Documentation">
          <h2>Getting started</h2>
          <ul>
            <li><a href="/docs/install">Installation</a></li>
            <li><a href="/docs/config" aria-current="page">Configuration</a></li>
            <li><a href="/docs/deploy">Deploying</a></li>
          </ul>
        </nav>
      </aside>
    
      <main class="docs-content">
        <article>
          <h1>Configuration</h1>
          <p>All settings live in <code>config.json</code>.</p>
    
          <section>
            <h2>Environment variables</h2>
            <p>Prefix custom values with <code>APP_</code>.</p>
            <pre><code>APP_PORT=3000</code></pre>
          </section>
    
          <section>
            <h2>Reloading</h2>
            <p>Changes apply on the next request in dev mode.</p>
          </section>
    
          <!-- Prev / next pager -->
          <nav class="pager" aria-label="Docs pages">
            <a rel="prev" href="/docs/install">&larr; Installation</a>
            <a rel="next" href="/docs/deploy">Deploying &rarr;</a>
          </nav>
        </article>
      </main>
    
    </div>

    6. App / dashboard shell

    A fixed top bar, a persistent side nav, and a <main> work area built from <section> panels. Landmarks (header, nav, main) let power users jump straight to a region.

    <body class="app">
    
      <header class="app-bar">
        <button aria-label="Toggle menu" aria-expanded="false">&#9776;</button>
        <span class="app-title">Analytics</span>
        <nav aria-label="Account">
          <a href="/settings">Settings</a>
          <a href="/logout">Sign out</a>
        </nav>
      </header>
    
      <nav class="app-side" aria-label="Sections">
        <ul>
          <li><a href="/overview" aria-current="page">Overview</a></li>
          <li><a href="/traffic">Traffic</a></li>
          <li><a href="/revenue">Revenue</a></li>
        </ul>
      </nav>
    
      <main class="app-main">
        <h1>Overview</h1>
    
        <section aria-labelledby="kpi-h">
          <h2 id="kpi-h">This week</h2>
          <ul class="kpi-row">
            <li><span class="kpi-label">Visitors</span> <strong>12,480</strong></li>
            <li><span class="kpi-label">Sign-ups</span> <strong>318</strong></li>
          </ul>
        </section>
    
        <section aria-labelledby="chart-h">
          <h2 id="chart-h">Traffic over time</h2>
          <figure>
            <img src="/chart.png" alt="Line chart trending up from Monday to Sunday">
            <figcaption>Sessions per day.</figcaption>
          </figure>
        </section>
      </main>
    
    </body>
    Components in context

    7. Navigation with a submenu & current page

    A list of links is the whole pattern. aria-current="page" marks where you are; a nested <ul> is a dropdown.

    <nav aria-label="Primary">
      <ul>
        <li><a href="/">Home</a></li>
    
        <li>
          <a href="/products" aria-current="page">Products</a>
          <!-- Submenu: a plain nested list, shown/hidden with CSS or JS -->
          <ul>
            <li><a href="/products/new">New arrivals</a></li>
            <li><a href="/products/sale">On sale</a></li>
          </ul>
        </li>
    
        <li><a href="/contact">Contact</a></li>
      </ul>
    </nav>

    8. A responsive card grid

    A collection of things is a list. Each card is an <article> (it stands alone). CSS Grid with auto-fill makes it wrap without media queries.

    <section aria-labelledby="team-h">
      <h2 id="team-h">Our team</h2>
    
      <ul class="card-grid">
        <li>
          <article class="card">
            <img src="/ada.jpg" alt="Ada Lovelace" width="200" height="200">
            <h3>Ada Lovelace</h3>
            <p>Founder & CEO</p>
            <a href="/team/ada">Read bio</a>
          </article>
        </li>
        <li>
          <article class="card">
            <img src="/grace.jpg" alt="Grace Hopper" width="200" height="200">
            <h3>Grace Hopper</h3>
            <p>Head of Engineering</p>
            <a href="/team/grace">Read bio</a>
          </article>
        </li>
        <!-- …more <li> cards… -->
      </ul>
    </section>
    
    <style>
      .card-grid {
        list-style: none;
        padding: 0;
        display: grid;
        /* as many 220px+ columns as fit, then wrap */
        grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
        gap: 1.5rem;
      }
      .card img { width: 100%; height: auto; border-radius: 50%; }
    </style>

    9. An accessible form

    Every field has a real <label>. Related choices go in a <fieldset> with a <legend>. Help and error text are linked with aria-describedby so screen readers announce them.

    <form action="/subscribe" method="post">
    
      <div class="field">
        <label for="email">Email address</label>
        <input
          type="email" id="email" name="email"
          autocomplete="email" required
          aria-describedby="email-help">
        <p id="email-help" class="help">We'll only email you the newsletter.</p>
      </div>
    
      <!-- A group of radio buttons: fieldset + legend is the label for the group -->
      <fieldset>
        <legend>How often?</legend>
        <label><input type="radio" name="freq" value="weekly" checked> Weekly</label>
        <label><input type="radio" name="freq" value="monthly"> Monthly</label>
      </fieldset>
    
      <div class="field">
        <label for="name">Name <span class="opt">(optional)</span></label>
        <input type="text" id="name" name="name" autocomplete="name">
      </div>
    
      <label class="check">
        <input type="checkbox" name="terms" required>
        I agree to the <a href="/terms">terms</a>.
      </label>
    
      <!-- A real submit button, not a <div onclick> -->
      <button type="submit">Subscribe</button>
    </form>
    Show errors as text, next to the field — not just a red border. Link it with aria-describedby="email-error" and set aria-invalid="true" on the input.

    10. A data table with a totals row

    <caption> titles the table. <th scope> tells assistive tech which cells are headers for which row or column. <tfoot> holds summary rows.

    <table>
      <caption>Q1 sales by region</caption>
    
      <thead>
        <tr>
          <th scope="col">Region</th>
          <th scope="col">Units</th>
          <th scope="col">Revenue</th>
        </tr>
      </thead>
    
      <tbody>
        <tr>
          <th scope="row">North</th>
          <td>1,204</td>
          <td>$48,160</td>
        </tr>
        <tr>
          <th scope="row">South</th>
          <td>980</td>
          <td>$39,200</td>
        </tr>
      </tbody>
    
      <tfoot>
        <tr>
          <th scope="row">Total</th>
          <td>2,184</td>
          <td>$87,360</td>
        </tr>
      </tfoot>
    </table>
    On small screens, wrap the table in <div style="overflow-x:auto"> so it can scroll sideways instead of breaking the layout.

    11. Figures & responsive media

    <figure> groups a visual with its caption. <picture> serves a different image per screen size or format; the <img> inside is the always-works fallback.

    <!-- Image with a caption -->
    <figure>
      <img src="/diagram.png"
           alt="Data flows from the client to the API to the database"
           width="900" height="500">
      <figcaption>Figure 1. The request lifecycle.</figcaption>
    </figure>
    
    <!-- Different crop on phones, modern format when supported -->
    <picture>
      <source media="(min-width: 800px)" srcset="/hero-wide.avif" type="image/avif">
      <source media="(min-width: 800px)" srcset="/hero-wide.jpg">
      <source srcset="/hero-square.jpg">
      <img src="/hero-square.jpg" alt="Chef plating a dish" width="600" height="600">
    </picture>
    
    <!-- Video with captions and a poster frame -->
    <figure>
      <video controls width="640" poster="/thumb.jpg">
        <source src="/demo.webm" type="video/webm">
        <source src="/demo.mp4" type="video/mp4">
        <track kind="captions" src="/demo.en.vtt" srclang="en" label="English" default>
      </video>
      <figcaption>A two-minute product tour.</figcaption>
    </figure>

    12. Breadcrumbs

    A trail back to the home page. It's an ordered list — the sequence matters — inside a labelled <nav>. The last item is the current page and isn't a link.

    <nav aria-label="Breadcrumb">
      <ol class="breadcrumb">
        <li><a href="/">Home</a></li>
        <li><a href="/guides">Guides</a></li>
        <li><a href="/guides/bread">Bread</a></li>
        <!-- Current page: text only, marked with aria-current -->
        <li><span aria-current="page">Sourdough</span></li>
      </ol>
    </nav>

    13. An FAQ (no JavaScript)

    <details> is a built-in show/hide widget. <summary> is the always-visible question; everything after it is the answer.

    <section aria-labelledby="faq-h">
      <h2 id="faq-h">Frequently asked questions</h2>
    
      <details>
        <summary>Do I need a sourdough starter?</summary>
        <p>Yes &mdash; either make one over a week or get some from a friend.</p>
      </details>
    
      <details>
        <summary>Can I use all-purpose flour?</summary>
        <p>You can, but bread flour gives a better rise.</p>
      </details>
    
      <!-- Add the "open" attribute to have one expanded by default -->
      <details open>
        <summary>How long does it keep?</summary>
        <p>Three days at room temperature, or slice and freeze.</p>
      </details>
    </section>

    14. A comment thread

    Each comment is its own <article> (it stands alone and has an author + date). Replies nest inside the comment they answer.

    <section aria-labelledby="comments-h">
      <h2 id="comments-h">3 comments</h2>
    
      <article class="comment">
        <header>
          <img src="/u/sam.jpg" alt="" width="40" height="40">
          <strong>Sam</strong>
          <time datetime="2026-03-15T09:12">2 hours ago</time>
        </header>
        <p>Worked on the first try. Thank you!</p>
    
        <!-- A reply is a nested article -->
        <article class="comment reply">
          <header>
            <strong>John Doe</strong> <small>(author)</small>
            <time datetime="2026-03-15T10:03">1 hour ago</time>
          </header>
          <p>So glad it helped!</p>
        </article>
      </article>
    
      <article class="comment">
        <header>
          <strong>Priya</strong>
          <time datetime="2026-03-15T11:20">40 minutes ago</time>
        </header>
        <p>What hydration do you recommend for a beginner?</p>
      </article>
    </section>

    15. A testimonial / pull quote

    <blockquote> is the quoted words; <figure> + <figcaption> attribute it. <cite> is the title of a work or the source, not a person's name.

    <figure class="testimonial">
      <blockquote cite="https://example.com/review/42">
        <p>
          This is the guide I wish I'd had when I started. Clear,
          no fluff, and my loaf actually rose.
        </p>
      </blockquote>
      <figcaption>
        &mdash; Dana Reyes, home baker,
        reviewing <cite>Sourdough for Beginners</cite>
      </figcaption>
    </figure>
    Across all of these: write the HTML in the order the content should be read (content before sidebars), give every <img> an alt, keep one <h1> and don't skip heading levels, and use a real <button> or <a> for anything clickable. Then let CSS place things wherever you like.

    Border-Image Slicer

    border-image takes one picture and cuts it into 9 pieces with 4 lines: the 4 corners keep their exact size, the 4 edges stretch or repeat along each side, and the middle is dropped (or kept, with fill). Drop in a frame or button-skin image, drag the guides to where the stretchable part begins, and copy the CSS.

    Reading the values. border-image-slice: 12 20 30 40 means "cut 12 from the top, 20 from the right, 30 from the bottom, 40 from the left" — the usual top / right / bottom / left order. One number applies to all four sides. Plain numbers are source-image pixels; add % to slice by percentage of the image instead.
    Always set a real border-width and a plain border fallback. border-image paints over the border area but reserves no layout space on its own — with no border width there is nothing to paint into, and browsers without border-image support fall back to the plain border.

    Live Code Editor

    Type HTML and CSS in the boxes on the left; the result renders instantly on the right. Load a preset to see a pattern in full.

    Load Preset: