The rules of an attribute
An attribute is written in the opening tag as name="value". Attribute names are case-insensitive, so CLASS and class are the same thing — write them in lower case and never think about it again.
Quote every value. Unquoted values work until the value contains a space, and then the rest of it silently becomes another attribute.
<div class=card wide> <!-- class="card" and an attribute called "wide" -->
<div class="card wide"> <!-- two classes, as intended -->
Boolean attributes
Some attributes are on or off, and their presence is what counts. disabled="false" is still disabled — the value is ignored entirely. To turn one off, remove it.
- Common ones:
disabled,checked,required,readonly,multiple,selected,hidden,open,autofocus,async,defer,novalidate,playsinline,muted,loop,controls.
<input disabled>
<input disabled="">
<input disabled="disabled">
<!-- this one is ALSO disabled -->
<input disabled="false">
Set them as properties, not strings: input.disabled = false. Using setAttribute("disabled", false) adds the attribute and disables the field.
The global attributes
| Attribute | What it does |
|---|---|
id | A unique address for one element. Used by labels, anchors and getElementById. |
class | One or more names, space separated. The main hook for CSS. |
style | Inline CSS. Beats a stylesheet, so use it sparingly. |
title | A tooltip on hover. Invisible on touch and to keyboard users — never the only place information lives. |
hidden | Removes the element from the page and from assistive technology. |
lang | The language of this element and its children. |
dir | ltr, rtl or auto — text direction. |
tabindex | Whether and where the element sits in the keyboard order. |
contenteditable | Makes the content editable in place. |
data-* | Your own data. The browser ignores it entirely. |
inert | The element and everything inside it stop responding to clicks and focus. |
id and class
- An
idmust be unique in the document. Two elements with the same id is not an error the browser reports — it just quietly uses the first one. - An id may not contain spaces. Keep it to letters, digits and hyphens so it works in CSS and in a URL fragment.
- A
classmay repeat as often as you like, and one element may carry several:class="card card--wide is-open". - Use
classfor styling andidfor addressing: a label'sfor, an anchor target, anaria-labelledby.
Your own data
Anything beginning with data- is yours. HTML ignores it, CSS can select on it, and JavaScript reads it from dataset with the name converted from kebab-case to camelCase.
<button class="tab" data-panel="specs" data-open-delay="200">Specification</button>
Reading it back
Every value is a string. Convert it yourself, and remember that a data- attribute is visible to anyone who opens developer tools — it is not a place for secrets.
const b = document.querySelector(".tab");
b.dataset.panel; // "specs"
b.dataset.openDelay; // "200" — always a string
Number(b.dataset.openDelay); // 200
b.dataset.state = "active"; // adds data-state="active"
What may go inside what
HTML elements belong to content categories, and each element states what it will accept. The two you meet constantly are flow content — most things, including block-level elements — and phrasing content: text and the elements that mark up text.
A <p> accepts phrasing content only. Put a <div> or an <h2> inside one and the browser closes the paragraph before it, which is why your CSS then applies to an element that no longer contains what you thought.
<!-- you wrote -->
<p>Intro <div>Block</div> more</p>
<!-- the DOM you get -->
<p>Intro </p>
<div>Block</div>
more<p></p>
<ul> and <ol> accept only <li>. <tr> accepts only <td> and <th>. An <a> may not contain another <a>, and a <button> may not contain a link or another button.
Case, whitespace and the rest
- Tag and attribute names are case-insensitive; write them lower case. Attribute values usually are case-sensitive — class names and ids definitely are.
- Any run of whitespace collapses to one space when rendered. Indent your source freely.
- The four characters to escape in text are
<,>,&and, inside a double-quoted attribute,". - Attributes on the same element must not repeat. A second
classon one tag is ignored.