HTML syntax

15 cards covering elements, attributes, semantics, and accessibility. Pin anything to keep it visible in the side panel.

Semantic Elements

HTML5 elements that describe what content is, not just how it looks — helping browsers, search engines, and screen readers understand the page structure.

html
<header>
<nav aria-label="Main navigation">
<a href="/">Home</a>
<a href="/about">About</a>
</nav>
</header>
<main>
<article>
<h1>Article Title</h1>
<section>
<h2>Section Heading</h2>
<p>Content goes here.</p>
</section>
<aside>Related links</aside>
</article>
</main>
<footer>
<p>&copy; 2024 My Site</p>
</footer>
coresemanticstructurehtml5
not reviewed

Meta Tags

Common tags that go inside <head> to set character encoding, control mobile layout, help search engines, and improve how the page looks when shared on social media.

html
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Page description for SEO (150–160 chars)" />
<meta name="robots" content="index, follow" />
<!-- Open Graph (Facebook, LinkedIn) -->
<meta property="og:title" content="Page Title" />
<meta property="og:description" content="Page description" />
<meta property="og:image" content="https://example.com/og.jpg" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="website" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="Page Title" />
<title>Page Title | Site Name</title>
<link rel="canonical" href="https://example.com/page" />
</head>
coremetaseohead
not reviewed

Input Types

Setting the right input type does three things automatically: triggers browser validation, shows the correct keyboard on mobile, and displays the appropriate UI control (like a date picker or color wheel).

html
<input type="text" placeholder="Name" />
<input type="email" placeholder="you@example.com" />
<input type="password" placeholder="Password" />
<input type="number" min="0" max="100" step="5" />
<input type="range" min="0" max="100" value="50" />
<input type="date" min="2024-01-01" />
<input type="color" value="#ff0000" />
<input type="checkbox" id="agree" />
<input type="radio" name="size" value="sm" />
<input type="file" accept=".jpg,.png" multiple />
<input type="search" />
<input type="tel" pattern="[0-9]{10}" />
<input type="url" placeholder="https://" />
<input type="hidden" name="csrf" value="token123" />
coreformsinputvalidation
not reviewed

Form Structure

How to structure a form so it works correctly for keyboard users and screen readers — using fieldset, legend, label, and ARIA attributes to link inputs with their labels and error messages.

html
<form action="/submit" method="POST" novalidate>
<fieldset>
<legend>Personal Information</legend>
<div>
<label for="name">Full Name *</label>
<input
id="name"
type="text"
name="name"
required
autocomplete="name"
aria-describedby="name-hint"
/>
<span id="name-hint">Enter your legal full name</span>
</div>
<div>
<label for="email">Email *</label>
<input
id="email"
type="email"
name="email"
required
autocomplete="email"
aria-invalid="true"
aria-errormessage="email-error"
/>
<span id="email-error" role="alert">Invalid email format</span>
</div>
</fieldset>
<button type="submit">Submit</button>
<button type="reset">Clear</button>
</form>
coreformsaccessibilityfieldset
not reviewed

details & summary

A built-in browser element for collapsible sections — clicking the summary toggles content open or closed with no JavaScript needed.

html
<!-- Native accordion — no JS required -->
<details>
<summary>What is the return policy?</summary>
<p>Items can be returned within 30 days with a receipt.</p>
</details>
<!-- Open by default -->
<details open>
<summary>Currently expanded</summary>
<p>This section is open on page load.</p>
</details>
<!-- Styled with CSS -->
<details class="faq-item">
<summary class="faq-question">
How do I reset my password?
</summary>
<div class="faq-answer">
<p>Click "Forgot password" on the login page...</p>
</div>
</details>
coredetailssummarydisclosure
not reviewed

Accessible Tables

Table markup that screen readers can understand — using caption for the table title, thead/tbody/tfoot to group rows, and scope to tell assistive technology which header belongs to which column or row.

html
<table>
<caption>Q4 Sales Report</caption>
<thead>
<tr>
<th scope="col">Product</th>
<th scope="col">Units</th>
<th scope="col">Revenue</th>
</tr>
</thead>
<tbody>
<tr>
<th scope="row">Widget A</th>
<td>1,200</td>
<td>$24,000</td>
</tr>
<tr>
<th scope="row">Widget B</th>
<td>850</td>
<td>$17,000</td>
</tr>
</tbody>
<tfoot>
<tr>
<th scope="row">Total</th>
<td>2,050</td>
<td>$41,000</td>
</tr>
</tfoot>
</table>
coretablesaccessibilityscope
not reviewed

figure & figcaption

Wraps an image, diagram, or code block together with its caption so browsers and screen readers know the two are related.

html
<!-- Image with caption -->
<figure>
<img
src="diagram.svg"
alt="System architecture diagram showing three tiers"
width="640"
height="480"
/>
<figcaption>
Figure 1: Three-tier architecture overview.
</figcaption>
</figure>
<!-- Code listing with caption -->
<figure>
<figcaption>Listing 3: Fibonacci sequence</figcaption>
<pre><code>function fib(n) { ... }</code></pre>
</figure>
corefigurefigcaptionimages
not reviewed

video & audio

Built-in browser elements for embedding video and audio — with multiple format fallbacks so different browsers can play what they support, and track files for captions.

html
<video
controls
width="640"
height="360"
poster="thumbnail.jpg"
preload="metadata"
aria-label="Product demo video"
>
<source src="demo.webm" type="video/webm" />
<source src="demo.mp4" type="video/mp4" />
<track
kind="captions"
src="captions-en.vtt"
srclang="en"
label="English"
default
/>
<p>Your browser doesn't support HTML video. <a href="demo.mp4">Download</a></p>
</video>
<audio controls preload="none">
<source src="podcast.opus" type="audio/ogg; codecs=opus" />
<source src="podcast.mp3" type="audio/mpeg" />
</audio>
corevideoaudiomedia
not reviewed

Data Attributes

A way to attach custom data to any HTML element using data-* attributes — that data can then be read or changed by JavaScript without affecting how the element looks.

html
<!-- HTML — any attribute starting with data- -->
<button
data-action="delete"
data-id="42"
data-confirm="true"
>
Delete
</button>
<ul id="list">
<li data-id="1" data-category="fruit">Apple</li>
<li data-id="2" data-category="veggie">Broccoli</li>
</ul>
coredata-attributesjavascriptdom
not reviewed

ARIA Roles & Attributes

Extra attributes that add or clarify meaning for screen readers — especially useful when native HTML elements alone cannot describe the current state or role of a custom UI widget.

html
<!-- Landmark roles (prefer native elements) -->
<div role="banner">...</div> <!-- use <header> -->
<div role="navigation">...</div> <!-- use <nav> -->
<div role="main">...</div> <!-- use <main> -->
<!-- Live regions -->
<div aria-live="polite" aria-atomic="true">
Status updates announced to screen readers
</div>
<!-- Expanded state (accordion) -->
<button aria-expanded="false" aria-controls="panel-1">
Toggle
</button>
<div id="panel-1" hidden>Panel content</div>
<!-- Labeling non-text elements -->
<button aria-label="Close dialog">✕</button>
<img src="chart.png" alt="Bar chart showing Q4 revenue by region" />
<!-- Required + invalid state -->
<input
aria-required="true"
aria-invalid="true"
aria-describedby="error-msg"
/>
<span id="error-msg" role="alert">Required field</span>
coreariaaccessibilityscreen-reader
not reviewed

Script Loading Strategies

defer and async let the browser download a script in the background while still parsing HTML — the difference is when each script actually runs and whether order is guaranteed.

html
<!-- Blocking — fetch & execute immediately, parsing pauses -->
<script src="app.js"></script>
<!-- async — fetch in parallel, execute as soon as downloaded (order not guaranteed) -->
<script async src="analytics.js"></script>
<!-- defer — fetch in parallel, execute AFTER parsing, in document order -->
<script defer src="app.js"></script>
<!-- type="module" — always deferred, supports import/export -->
<script type="module" src="app.mjs"></script>
<!-- Inline module -->
<script type="module">
import { init } from './app.mjs';
init();
</script>
<!-- Preload critical resources -->
<link rel="preload" href="critical.js" as="script" />
<link rel="prefetch" href="lazy-page.js" as="script" />
corescriptdeferasync
not reviewed

Responsive Images

Tools for serving the right image at the right size — srcset lets the browser pick the best resolution, while picture lets you swap to a completely different image on different screen sizes.

html
<!-- srcset + sizes — resolution switching -->
<img
src="photo-800.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
alt="A scenic mountain view"
loading="lazy"
decoding="async"
/>
<!-- picture — art direction (different crops per breakpoint) -->
<picture>
<source
media="(max-width: 600px)"
srcset="photo-portrait.webp"
type="image/webp"
/>
<source
media="(max-width: 600px)"
srcset="photo-portrait.jpg"
/>
<img src="photo-landscape.jpg" alt="Photo" width="800" height="450" />
</picture>
coreimagesresponsiveperformance
not reviewed

dialog Element

A built-in browser element for popup dialogs — handles focus trapping (keeps keyboard focus inside the dialog), the dark backdrop overlay, and the Escape key to close, without any JavaScript library.

html
<dialog id="confirm-dialog" aria-labelledby="dialog-title">
<h2 id="dialog-title">Confirm Delete</h2>
<p>This action cannot be undone.</p>
<form method="dialog">
<button value="cancel">Cancel</button>
<button value="confirm" autofocus>Delete</button>
</form>
</dialog>
<button id="open-btn">Open Dialog</button>
advanceddialogmodalaccessibility
not reviewed

template Element

An HTML block that the browser parses and validates but does not display or run — you clone it with JavaScript and insert copies into the page when needed.

html
<!-- Template is inert — not rendered, scripts don't run -->
<template id="card-template">
<div class="card">
<h3 class="card-title"></h3>
<p class="card-body"></p>
</div>
</template>
advancedtemplateweb-componentsdom
not reviewed