Reference

Look it up.
The answer and the trap.

Every entry says what the thing does, what it looks like, and the mistake people make with it. Curated rather than exhaustive — these are the ones you actually reach for.

415Entries
3Languages

141 entries

<!doctype html>

Document

Puts the browser in standards mode. It carries no version information — that is its only job.

html
<!doctype html>
<html lang="en">
Watch out

Without it you get quirks mode, where old layout bugs are emulated on purpose.

<html>

Document

The root element. Carries the page language and, for right-to-left scripts, the direction.

html
<html lang="en" dir="ltr">
Watch out

lang is not optional: it sets screen-reader pronunciation, hyphenation and translation.

<head>

Document

Information about the document: title, metadata, stylesheets, scripts. None of it is drawn.

<body>

Document

The document itself — everything a reader sees.

<meta charset>

Document

Declares the character encoding. Always UTF-8.

html
<meta charset="utf-8">
Watch out

Must appear within the first 1024 bytes, so it goes first in the head.

<meta name="viewport">

Document

Tells a phone to render at device width instead of 980px and scaling down.

html
<meta name="viewport" content="width=device-width, initial-scale=1">
Watch out

Never add user-scalable=no — it blocks zoom, which people need.

<title>

Document

The tab, the bookmark, the search result and the first thing a screen reader announces.

Watch out

Put the distinctive part first: "Learn HTML — DOMVYBE", not the other way round.

<script>

Document

Loads or contains JavaScript.

html
<script type="module" src="/app.js"></script>   <!-- deferred, module scope -->
<script defer src="/old.js"></script>            <!-- after parsing, in order -->
<script async src="/analytics.js"></script>      <!-- whenever it lands -->
Watch out

defer and async are ignored on inline scripts — those always run immediately.

<style>

Document

CSS inside the document. Useful for the handful of rules needed before the stylesheet arrives.

<base>

Document

Sets the base URL every relative link resolves against. One per document, and it affects everything after it.

Watch out

Rarely worth it — it surprises the next person to read the page.

<meta name="description">

Document

The sentence a search engine may show under your title. 50–160 characters, unique per page.

html
<meta name="description" content="Solid oak doors, painted in any colour, with a frame measured on site.">
Watch out

It is not a ranking signal, but it decides whether anyone clicks. A duplicate description across a site is worse than none.

<link rel="canonical">

Document

The address this page should be indexed under, when the same content is reachable at several URLs.

html
<link rel="canonical" href="https://example.com/doors/painted-oak">
Watch out

Absolute URL. Filters and tracking parameters are the usual reason two URLs hold one page.

Open Graph tags

Document

What a link looks like when it is pasted into a chat or a post.

html
<meta property="og:title" content="Painted oak door">
<meta property="og:description" content="Five days, made to order.">
<meta property="og:image" content="https://example.com/og/painted.png">
<meta property="og:type" content="product">
<meta name="twitter:card" content="summary_large_image">
Watch out

1200×630 renders well everywhere. A relative image URL is dropped — make it absolute.

<meta name="theme-color">

Document

Tints the browser interface around the page on mobile and in installed apps.

html
<meta name="theme-color" content="#07090c">
<meta name="theme-color" content="#fff" media="(prefers-color-scheme: light)">

<script> defer and async

Document

How a classic script is fetched and when it runs.

html
<script src="a.js"></script>        <!-- blocks parsing -->
<script src="a.js" defer></script>  <!-- fetches now, runs after parsing, in order -->
<script src="a.js" async></script>  <!-- fetches now, runs whenever it lands -->
<script type="module" src="a.js"></script>  <!-- deferred by default -->
Watch out

defer for anything that touches the DOM; async only for something wholly independent, like analytics.

<link rel="preload">

Document

Start fetching something the page will certainly need, before the parser reaches it.

html
<link rel="preload" href="/fonts/space.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preconnect" href="https://cdn.example.com">
Watch out

Preload everything and you have prioritised nothing. One or two per page, and only what is on the critical path.

<noscript>

Document

Content shown only when scripting is off or has failed.

Watch out

Useful as a fallback message, and as a reminder that a page which renders nothing without JavaScript has a cost.

<h1> … <h6>

Text

Headings. They are the document outline, not sizes — screen readers list them so a page can be skimmed.

Watch out

One h1 per page. Do not skip levels to get a smaller size; that is what CSS is for.

<p>

Text

A paragraph. Accepts phrasing content only.

Watch out

Put a div or a heading inside one and the browser closes the paragraph before it.

<strong>

Text

Strong importance, seriousness or urgency. Bold by default — but the meaning is the point.

<em>

Text

Stress emphasis: the sentence changes meaning depending on which word carries it.

<b>

Text

Bold with no added importance — a keyword, a product name, a lead-in.

<i>

Text

A different voice or mood: a technical term, a taxonomic name, a thought.

<mark>

Text

Highlighted because it is relevant to what the reader is doing right now — a search hit, for instance.

<small>

Text

Side comments and small print: legal text, attribution, caveats.

<s> / <del> / <ins>

Text

s is no longer accurate. del is removed content, ins is added content — both take datetime and cite.

<blockquote>

Text

A quoted block. Takes cite with the source URL.

html
<figure>
  <blockquote cite="https://example.com">
    <p>Programs must be written for people to read.</p>
  </blockquote>
  <figcaption>Abelson and Sussman, <cite>SICP</cite></figcaption>
</figure>

<q>

Text

An inline quotation. The browser adds the quotation marks, in the right style for the language.

<cite>

Text

The title of a work — a book, a film, a paper. Not the name of the person.

<code>

Text

A fragment of code. Inside a pre for a block.

Watch out

A < inside must be written &lt; or the browser reads it as a tag.

<pre>

Text

Preformatted: whitespace and newlines are preserved exactly.

<kbd> / <samp> / <var>

Text

A key to press, output from a program, and a variable name.

<abbr>

Text

An abbreviation. The title attribute carries the expansion.

html
<abbr title="Cascading Style Sheets">CSS</abbr>

<time>

Text

A date or time a machine can read, with any wording you like for people.

html
<time datetime="2026-09-21">21 September 2026</time>

<br>

Text

A line break that is part of the content — an address, a line of verse.

Watch out

Not for spacing between paragraphs. That is a margin.

<hr>

Text

A thematic break: the subject changes. Not a decorative line — use a border for that.

<span>

Text

An inline container with no meaning. For styling or scripting a run of text.

<bdi>

Text

Isolates a fragment whose direction is unknown — a user name — so it cannot disturb the line around it.

Character entities

Text

Four characters must be escaped in HTML.

html
&lt;   <   less than
&gt;   >   greater than
&amp;  &   ampersand
&quot; "   inside a double-quoted attribute
&nbsp;     a space that does not break

<sub> / <sup>

Text

Subscript and superscript — chemistry, footnote markers, ordinals.

html
H<sub>2</sub>O · 4<sup>th</sup> · <a href="#fn1"><sup>1</sup></a>
Watch out

For mathematics, MathML or an image with a description is better than nested sup tags.

<data>

Text

Text for a person, with a machine-readable value beside it.

html
<data value="480">£480</data>
<data value="8901234">Product no. 8901234</data>
Watch out

The datetime twin of this is <time>.

<address>

Text

Contact details for the nearest article or for the page as a whole.

Watch out

Not for postal addresses in general — only for how to reach the author or owner.

<dfn>

Text

Marks the place where a term is defined, rather than every use of it.

<wbr>

Text

A place a long word may break, if it has to.

html
https://example.com/a/<wbr>very/<wbr>long/<wbr>path

<u> and <bdo>

Text

<u> is a non-textual annotation, like a spelling error. <bdo> forces text direction.

Watch out

Underlining anything that is not a link is a usability problem; that is why <u> is rare.

<a>

Links & media

A link. The text inside is what a screen reader announces, so it must make sense on its own.

html
<a href="/learn/">Another page here</a>
<a href="https://example.com" target="_blank" rel="noopener">Another site</a>
<a href="#forms">Further down this page</a>
<a href="mailto:a@b.com">Start an email</a>
<a href="/file.zip" download>Save the file</a>
Watch out

target="_blank" always needs rel="noopener". Never write "click here".

<img>

Links & media

An image. alt is what the image says, not what it looks like.

html
<img src="/a.jpg" alt="A brass lever on a walnut door" width="1600" height="900" loading="lazy">
Watch out

alt="" for decoration — empty, not missing. width and height reserve the space and stop the page jumping.

srcset / sizes

Links & media

Offers the browser several sizes of the same image so it can pick before layout.

html
<img src="/h-800.jpg"
     srcset="/h-400.jpg 400w, /h-800.jpg 800w, /h-1600.jpg 1600w"
     sizes="(max-width: 700px) 100vw, 50vw"
     alt="…" width="1600" height="900">
Watch out

sizes must describe the CSS width the image is drawn at. A wrong one is worse than none.

<picture>

Links & media

Chooses between genuinely different files: another format, or a different crop.

html
<picture>
  <source srcset="/h.avif" type="image/avif">
  <source media="(max-width: 700px)" srcset="/h-square.jpg">
  <img src="/h.jpg" alt="…" width="1600" height="900">
</picture>
Watch out

The img is the fallback and the element that is styled. alt always lives on it.

<figure> / <figcaption>

Links & media

Self-contained content with a visible caption.

Watch out

The caption and the alt do different jobs and should not be the same sentence.

<video>

Links & media

Video, with the browser player if you add controls.

html
<video src="/v.mp4" poster="/p.jpg" width="1600" height="900"
       controls playsinline preload="metadata">
  <track kind="captions" src="/v.en.vtt" srclang="en" label="English" default>
</video>
Watch out

Autoplay only works muted. Always include playsinline or iOS takes over the screen.

<audio>

Links & media

Audio. With controls it is a complete player; give it a caption saying what it is.

<track>

Links & media

A WebVTT captions, subtitles, descriptions or chapters file for a video.

Watch out

A cross-origin VTT needs CORS headers, and file:// will not load one at all.

<iframe>

Links & media

Another complete document inside a rectangle, with its own origin.

html
<iframe src="…" title="…" loading="lazy" sandbox="allow-scripts"></iframe>
Watch out

title is the accessible name. allow-scripts together with allow-same-origin removes the sandbox entirely.

<svg>

Links & media

Vector graphics inline in the page, where CSS can reach them.

Watch out

Decorative icon inside a labelled button: aria-hidden="true". Standalone meaning: role="img" and a <title> first.

<canvas>

Links & media

A bitmap you draw on with JavaScript. Nothing drawn is in the DOM, so it needs a text alternative.

target="_blank"

Links & media

Opens in a new tab. Modern browsers imply rel="noopener", but state it anyway.

html
<a href="https://example.com" target="_blank" rel="noopener noreferrer">
  Their site <span aria-hidden="true">↗</span>
  <span class="sr-only">(opens in a new tab)</span>
</a>
Watch out

Say that it opens a new tab. A screen-reader user otherwise finds the back button dead.

download

Links & media

Saves the target instead of navigating to it, optionally under a new name.

html
<a href="/exports/doors.csv" download="doors-2026.csv">Download the list</a>
Watch out

Only honoured for same-origin URLs and blob: URLs.

mailto: and tel:

Links & media

Links that open a mail client or start a call.

html
<a href="mailto:hello@example.com?subject=Doors">hello@example.com</a>
<a href="tel:+994501234567">+994 50 123 45 67</a>
Watch out

Write the number in the link text the way a person reads it, and in the href the way a phone dials it.

<iframe> sandbox

Links & media

Drops privileges for the framed document and grants them back one at a time.

html
<iframe src="/preview" sandbox="allow-scripts" title="Preview"></iframe>

<!-- allow-scripts allow-same-origin together is the same as no sandbox -->
Watch out

Without allow-same-origin the frame gets an opaque origin: no storage, no cookies, and the parent cannot read it. That is the point.

<iframe> loading and allow

Links & media

Lazy-load an embed, and state which capabilities it may use.

html
<iframe src="https://player.example/v/1" title="The film"
  loading="lazy" allow="fullscreen; picture-in-picture"
  width="560" height="315"></iframe>
Watch out

A title is required for a frame — it is what a screen reader announces.

<source>

Links & media

One candidate inside <picture>, <video> or <audio>. The first that matches wins.

html
<picture>
  <source srcset="/door.avif" type="image/avif">
  <source srcset="/door.webp" type="image/webp">
  <img src="/door.jpg" alt="A painted oak door" width="1200" height="800">
</picture>
Watch out

The <img> is not a fallback afterthought: it is the element that actually renders, and it carries the alt.

Inline <svg> vs <img src=".svg">

Links & media

Inline SVG can be styled by the page and read by CSS; an SVG in an <img> cannot.

html
<svg viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" fill="none" stroke="currentColor">
  <path d="M5 12h14"/>
</svg>
Watch out

currentColor is the reason icons are inlined: they follow the text colour for free.

<ul>

Lists & tables

An unordered list — the order does not matter. Only li may be a direct child.

<ol>

Lists & tables

An ordered list — the order is the content. Takes start, reversed and type.

html
<ol start="4" reversed type="a">

<li>

Lists & tables

A list item. A nested list goes inside the li it belongs to, never between two.

<dl> / <dt> / <dd>

Lists & tables

Name and value pairs: a glossary, a specification sheet, metadata.

html
<dl>
  <div><dt>Material</dt><dd>Aluminium</dd></div>
  <div><dt>Tolerance</dt><dd>1 mm</dd></div>
</dl>
Watch out

Wrapping each pair in a div is allowed and makes it far easier to lay out.

<table>

Lists & tables

Data with two dimensions. Not a layout tool.

html
<table>
  <caption>Lead times</caption>
  <thead><tr><th scope="col">Finish</th><th scope="col">Days</th></tr></thead>
  <tbody><tr><th scope="row">Painted</th><td>5</td></tr></tbody>
</table>

<caption>

Lists & tables

The table's name and accessible name. Must be the first child of the table.

<th> scope

Lists & tables

A header cell. scope="col" or "row" tells assistive technology which cells it describes.

Watch out

Without scope, a cell is announced as a bare value with no idea which row or column it belongs to.

colspan / rowspan

Lists & tables

How many columns or rows a cell covers. Every row must still add up to the same total.

<ol start> and reversed

Lists & tables

Begin the numbering somewhere else, or count down.

html
<ol start="4">…</ol>
<ol reversed>…</ol>
<li value="9">…</li>

<colgroup> / <col>

Lists & tables

Styles or spans whole columns without touching every cell.

html
<table>
  <colgroup><col><col style="width: 30%"></colgroup>
  …
</table>

<thead> / <tbody> / <tfoot>

Lists & tables

Row groups. A header group can repeat when a long table is printed.

Watch out

tfoot goes after tbody in the markup; browsers render it at the bottom regardless.

<menu>

Lists & tables

A list of commands. Semantically a <ul>, with a name that says what the list is for.

<form>

Forms

Collects named values and sends them somewhere.

html
<form action="/subscribe" method="post">
Watch out

method="get" puts values in the query string; "post" puts them in the body. Only named controls are sent.

<label>

Forms

Names a control. Either for="id" or wrap the input.

Watch out

A placeholder is not a label: it disappears the moment someone types.

<input>

Forms

The type changes the control, the phone keyboard, the validation and what is announced.

html
text  email  tel  url  number  range  date  time
password  search  checkbox  radio  file  color  hidden
Watch out

type="number" is for quantities. A postcode, PIN or card number is text with inputmode="numeric".

<textarea>

Forms

Multi-line text. The value is the content between the tags, not a value attribute.

<select> / <option>

Forms

A choice from a fixed list. optgroup groups options; multiple allows several.

Watch out

The closed control is stylable; the open dropdown list is drawn by the operating system and is not.

<button>

Forms

A button. Inside a form the default type is submit.

Watch out

If it is not meant to submit, you must write type="button". This causes more surprise reloads than anything else.

<fieldset> / <legend>

Forms

Groups related controls and names the group. Essential for a set of radio buttons.

<datalist>

Forms

Suggestions for an input. Unlike select, the reader may type something else.

required / pattern / min / max

Forms

Constraints the browser enforces before submitting, and announces in the reader's own language.

html
<input required minlength="8" maxlength="40">
<input type="number" min="1" max="40" step="1">
<input pattern="[0-9]{4}" title="Four digits">
Watch out

pattern is anchored at both ends automatically. Always pair it with title. And validate again on the server.

autocomplete

Forms

Names what a field holds so the browser and password manager can fill it in one tap.

html
name  given-name  family-name  email  tel  organization
street-address  address-level2  postal-code  country-name
cc-number  cc-exp  username  current-password  new-password  one-time-code
Watch out

Do not switch it off on address or password fields — it makes the form harder for everyone.

readonly vs disabled

Forms

readonly is focusable and IS submitted. disabled is not focusable and is NOT submitted.

Watch out

If the value must arrive but not be edited, readonly is the one you want.

Text-like input types

Forms

text, email, tel, url, search, password — the keyboard and the validation change with the type.

html
<input type="email" autocomplete="email" required>
<input type="tel" inputmode="tel" autocomplete="tel">
<input type="url" placeholder="https://">
<input type="search">
Watch out

type="number" is for quantities, never for phone numbers, card numbers or postcodes: it strips leading zeros and spins on scroll.

Date and time inputs

Forms

date, time, datetime-local, month and week, with a native picker.

html
<input type="date" min="2026-01-01" max="2026-12-31" value="2026-09-21">
Watch out

The value is always ISO — "2026-09-21" — whatever the picker shows the user.

<input type="file">

Forms

Choose one or more files. Read them from the files property, never from value.

html
<input type="file" accept="image/png, image/jpeg" multiple>
<input type="file" accept="image/*" capture="environment">
Watch out

accept is a filter in the picker, not a guarantee. Check the type on the server.

<input type="range">

Forms

A slider. Always pair it with a visible number: a slider alone hides the value.

html
<label for="days">Lead time</label>
<input id="days" type="range" min="1" max="30" step="1" value="5"
  oninput="out.value = this.value">
<output id="out">5</output>

<input type="checkbox"> and radio

Forms

Checkboxes are independent; radios sharing a name are one choice.

html
<fieldset>
  <legend>Finish</legend>
  <label><input type="radio" name="finish" value="painted" checked> Painted</label>
  <label><input type="radio" name="finish" value="oiled"> Oiled</label>
</fieldset>
Watch out

Radios without a shared name are not a group. Radios without a fieldset and legend have no group label.

<input type="hidden">

Forms

Sends a value the user does not edit — an id, a token, a return path.

Watch out

Hidden from the page, not from the user. Anything here can be changed before it is sent.

<optgroup>

Forms

Groups options under a label inside a select.

html
<select>
  <optgroup label="Oak">
    <option value="painted">Painted</option>
    <option value="oiled">Oiled</option>
  </optgroup>
</select>

novalidate and formnovalidate

Forms

Turns off the browser’s own error bubbles — for the form, or for one button.

html
<form novalidate>…</form>
<button formnovalidate>Save a draft</button>
Watch out

Keep required and type even when you validate yourself: assistive technology reads them.

formaction and formmethod

Forms

Lets one button submit the same form somewhere else.

html
<button type="submit">Save</button>
<button type="submit" formaction="/drafts">Save as a draft</button>

inputmode and enterkeyhint

Forms

Chooses the on-screen keyboard and what its action key says, without changing the input type.

html
<input inputmode="numeric" pattern="[0-9]*" enterkeyhint="done">
<input type="search" enterkeyhint="search">

The form attribute

Forms

Associates a control with a form it is not inside.

html
<form id="order">…</form>
<button type="submit" form="order">Order</button>

<header>

Sections

Introductory content for the page, or for the section it sits in. You may have several.

<nav>

Sections

A major block of navigation links. Not every group of links.

Watch out

With more than one, give each an aria-label so they can be told apart.

<main>

Sections

The unique content of this page. Exactly one, and not inside header, nav, article, aside or footer.

<article>

Sections

Something that would still make sense on its own: a post, a card, a comment.

<section>

Sections

A thematic grouping — and it should have a heading.

Watch out

A section with no heading is worse than a div: it announces a region and then fails to say what it is.

<aside>

Sections

Related but separable: a sidebar, a pull quote, related links.

<div>

Sections

A container with no meaning. Correct and honest when the grouping exists for layout.

<search>

Sections

The landmark for a search or filter region — the element that replaces role="search".

html
<search>
  <form action="/doors">
    <label for="q">Search doors</label>
    <input id="q" type="search" name="q">
  </form>
</search>

<hgroup>

Sections

A heading with its subtitle, so the subtitle is not a second heading in the outline.

html
<hgroup>
  <h1>Painted oak door</h1>
  <p>Made to order in five days</p>
</hgroup>

Heading order

Sections

One h1 per page, then h2, h3 — with nothing skipped. It is how a screen reader user navigates.

Watch out

Heading levels are structure, not size. Style them with CSS; do not pick h4 because it looks right.

Landmarks

Sections

header, nav, main, aside and footer map to landmarks that can be jumped between.

Watch out

One main per page. Two navs need distinct aria-labels, or they are announced identically.

<details> / <summary>

Interactive

A disclosure widget with keyboard support and no JavaScript.

html
<details name="faq">
  <summary>What is included?</summary>
  <p>Frame, leaf and fitting.</p>
</details>
Watch out

summary must be the first child. A shared name attribute makes a group behave like an accordion.

<dialog>

Interactive

A real modal: inert background, trapped focus, Escape to close, rendered in the top layer.

js
dialog.showModal();   // modal
dialog.show();        // non-modal
dialog.close("ok");
dialog.returnValue;
Watch out

A form with method="dialog" inside closes it and puts the button value in returnValue.

popover

Interactive

A light overlay that closes on Escape or a click outside, with no script.

html
<button popovertarget="menu">Options</button>
<div id="menu" popover>…</div>

<progress> / <meter>

Interactive

progress is a task moving to completion. meter is a reading on a known scale, coloured by low/high/optimum.

<output>

Interactive

The result of a calculation. It is a live region by default, so changes are announced.

<template>

Interactive

Markup that is parsed but inert: not rendered, images not loaded, scripts not run. Clone it to use it.

js
const node = tpl.content.cloneNode(true);
node.querySelector(".title").textContent = d.title;
list.append(node);

<slot>

Interactive

A hole in a shadow tree where the element's own children appear.

<details name>

Interactive

Give several details the same name and only one can be open — an accordion with no JavaScript.

html
<details name="faq"><summary>One</summary>…</details>
<details name="faq"><summary>Two</summary>…</details>

popovertarget

Interactive

Wires a button to a popover without a line of script, with light dismiss and the top layer included.

html
<button popovertarget="menu">Options</button>
<div id="menu" popover>…</div>

<dialog> modal or not

Interactive

showModal() traps focus, adds a backdrop and blocks the page. show() does none of that.

js
dialog.showModal();
dialog.close("saved");
dialog.addEventListener("close", () => console.log(dialog.returnValue));
Watch out

A form with method="dialog" inside closes it on submit and sets returnValue.

id

Attributes

A unique address for one element: a label's for, an anchor target, aria-labelledby.

Watch out

Two elements with the same id is not an error the browser reports — it quietly uses the first.

class

Attributes

One or more names, space separated. The main hook for CSS.

data-*

Attributes

Your own data. Read from element.dataset with the name in camelCase.

js
<button data-panel="specs" data-open-delay="200">

el.dataset.panel;       // "specs"
el.dataset.openDelay;   // "200" — always a string

hidden

Attributes

Removes the element from the page and from assistive technology. Equivalent to display: none.

inert

Attributes

The element and everything inside it stop responding to clicks and focus. What showModal() applies to the page.

tabindex

Attributes

0 puts a non-interactive element in the tab order; -1 makes it focusable by script only.

Watch out

Never use a positive value. It reorders the whole page's tab sequence.

aria-label / aria-labelledby

Attributes

Gives an element an accessible name when its content does not — an icon-only button, for instance.

Watch out

Prefer real text. A name that differs from the visible label breaks voice control.

aria-expanded / aria-controls

Attributes

States whether a disclosure is open, and which element it controls.

html
<button aria-expanded="false" aria-controls="panel">Details</button>

aria-live / role="status"

Attributes

Announces content that appeared without a page load. polite waits for a pause; assertive interrupts.

aria-hidden

Attributes

Hides an element from assistive technology while leaving it visible.

Watch out

Never on anything focusable — a keyboard user would land on something that does not exist to them.

loading / decoding / fetchpriority

Attributes

loading="lazy" defers off-screen images. decoding="async" keeps decoding off the main thread. fetchpriority="high" for the one image that matters most.

Watch out

Never lazy-load the image at the top of the page.

rel values

Attributes

noopener, noreferrer, nofollow, sponsored, ugc, canonical, alternate, preload, preconnect.

contenteditable

Attributes

Makes the content editable in place. Powerful and full of edge cases — reach for a real input first.

translate

Attributes

translate="no" stops automatic translation mangling a product name or a code sample.

lang and dir

Attributes

The language of the content and the direction it runs. Set both on <html>, and again on any passage that differs.

html
<html lang="en">
<p lang="az">Qapı</p>
<p dir="rtl" lang="ar">…</p>
Watch out

lang decides the voice a screen reader uses, how text is hyphenated, and which quotation marks CSS inserts.

title

Attributes

A tooltip on hover. Invisible on touch, unreliable with a keyboard, and not a substitute for a label.

Watch out

The one genuinely good use is on an <iframe> and on <abbr>.

aria-describedby

Attributes

Points at the element that explains a control — a hint, or an error message.

html
<input id="email" aria-describedby="email-hint" aria-invalid="true">
<small id="email-hint" role="alert">That address looks wrong.</small>

aria-current

Attributes

Marks the one item in a set that is current: page, step, date or location.

html
<a href="/doors" aria-current="page">Doors</a>

aria-pressed and aria-checked

Attributes

State for a toggle button or a custom checkbox.

Watch out

If a native <button> or <input type="checkbox"> will do, use it — it carries this for free.

spellcheck, autocapitalize, autocorrect

Attributes

Control the typing conveniences a phone applies.

html
<input name="code" spellcheck="false" autocapitalize="off" autocomplete="off">
Watch out

Turn them off for codes, identifiers and passwords. Leave them on for prose.

draggable

Attributes

Marks an element as a drag source for the HTML drag-and-drop API.

Watch out

Drag and drop is keyboard-hostile by default. Give the same action a button as well.