|$ curl https://forge-ai.dev/api/markdown?path=docs/html/attributes
$cat docs/html-attributes.md
updated Last week·20 min read·published

HTML Attributes

HTMLBeginnerAttributesBeginner🎯Free Tools
Introduction

Attributes provide additional information about HTML elements. They appear inside the opening tag as name-value pairs and control element behavior, appearance, and semantics. Every HTML element can have attributes, and they are essential for building interactive, accessible, and well-structured web pages.

HTML5 introduced several new attributes and standardized many that were previously informal. Understanding the full set of available attributes — from global ones that work on every element to element-specific ones — is fundamental to writing correct, maintainable markup.

Syntax Basics

Attributes always appear in the opening tag of an element. The general syntax uses an attribute name followed by an equals sign and a quoted value. Boolean attributes can be written without a value:

attributes-syntax.html
HTML
1<!-- Standard attribute with a value -->
2<a href="https://example.com" target="_blank">Visit</a>
3
4<!-- Attribute with no value needed (boolean) -->
5<input type="text" disabled>
6
7<!-- Single-quoted values are also valid -->
8<img src='image.png' alt='A photo'>
9
10<!-- Attribute names are case-insensitive in HTML5, but always use lowercase -->
11<IMG SRC="logo.png" ALT="Logo"> <!-- valid but discouraged -->
12
13<!-- Self-closing elements still use attributes -->
14<br />
15<img src="photo.jpg" alt="Photo" width="300" />
16<input type="email" name="user-email" />
17

info

Always use double quotes around attribute values. While single quotes and unquoted values work in HTML5, double quotes are the most common convention and improve consistency across your codebase.
Global Attributes

Global attributes can be used on any HTML element. They provide common functionality like identification, styling hooks, event handlers, and accessibility metadata. The most important global attributes are:

AttributePurposeExample
classAssigns CSS classes for styling and selectionclass="btn primary"
idUnique identifier for the elementid="main-nav"
styleInline CSS stylesstyle="color: red"
titleAdvisory information (tooltip on hover)title="Close dialog"
langLanguage of the element's contentlang="es"
dirText direction (ltr, rtl, auto)dir="rtl"
tabindexTab order for keyboard navigationtabindex="0"
contenteditableMakes element content editablecontenteditable="true"
draggableEnables drag-and-dropdraggable="true"
hiddenRemoves element from renderinghidden
translateWhether content should be translatedtranslate="no"
spellcheckEnable browser spell checkingspellcheck="false"
global-attributes.html
HTML
1<!-- class: multiple CSS classes separated by spaces -->
2<div class="card card--dark card--featured">
3 <h2 class="card__title">Featured Card</h2>
4</div>
5
6<!-- id: must be unique per page -->
7<section id="pricing">
8 <h2>Pricing</h2>
9</section>
10
11<!-- style: inline CSS (avoid in production) -->
12<p style="color: #00FF41; font-weight: bold;">Highlighted text</p>
13
14<!-- lang: changes language context -->
15<p lang="fr">Ceci est un paragraphe en français.</p>
16
17<!-- dir: text direction for RTL languages -->
18<p dir="rtl" lang="ar">هذا نص بالعربية</p>
19
20<!-- tabindex: keyboard navigation order -->
21<div tabindex="0" role="button">Focusable element</div>
22
23<!-- contenteditable: inline editing -->
24<div contenteditable="true" spellcheck="false">
25 Click here and start typing...
26</div>
27
28<!-- hidden: removes from DOM rendering -->
29<div hidden>This content is not displayed</div>
30
31<!-- title: tooltip on hover -->
32<abbr title="HyperText Markup Language">HTML</abbr>

best practice

Avoid using inline style attributes in production. They are hard to maintain, cannot be overridden by CSS, and prevent caching. Use class for all styling.
Class & ID Patterns

The class and id attributes are the most frequently used global attributes. Classes are reusable and support multiple values, while IDs are unique and used for anchoring, JavaScript targeting, and ARIA references:

class-id-patterns.html
HTML
1<!-- Class: multiple classes, space-separated, reusable -->
2<button class="btn btn--primary btn--large">Submit</button>
3<button class="btn btn--secondary">Cancel</button>
4<button class="btn btn--ghost" disabled>Disabled</button>
5
6<!-- BEM naming convention -->
7<div class="sidebar sidebar--collapsed">
8 <nav class="sidebar__nav">
9 <a class="sidebar__link sidebar__link--active" href="/dashboard">
10 Dashboard
11 </a>
12 <a class="sidebar__link" href="/settings">Settings</a>
13 </nav>
14</div>
15
16<!-- ID: unique per page, used for anchors and JS -->
17<header id="main-header">
18 <nav id="primary-nav">
19 <a href="#pricing">Jump to Pricing</a>
20 <a href="#contact">Jump to Contact</a>
21 </nav>
22</header>
23
24<!-- ARIA: id referenced by aria-labelledby, aria-describedby -->
25<section aria-labelledby="section-title">
26 <h2 id="section-title">Welcome</h2>
27 <p id="section-desc">This section contains important information.</p>
28 <div aria-labelledby="section-title" aria-describedby="section-desc">
29 Content with explicit ARIA relationships
30 </div>
31</section>
32
33<!-- Skip navigation link using id anchor -->
34<a href="#main-content" class="skip-link">Skip to content</a>
35<main id="main-content">
36 <p>Main page content here</p>
37</main>

warning

IDs must be unique within a page. Duplicate IDs cause unpredictable behavior in JavaScript document.getElementById() calls, CSS selectors, and ARIA relationships. If you need the same structure multiple times, use classes instead.
Boolean Attributes

Boolean attributes represent a state that is either true or false. When the attribute is present, the value is true. When absent, it is false. You do not need to specify a value — the presence of the attribute name alone is sufficient:

boolean-attributes.html
HTML
1<!-- Correct: presence = true, absence = false -->
2<input type="text" disabled>
3<button type="submit" disabled>Submit</button>
4
5<!-- Also valid but redundant — same as above -->
6<input type="text" disabled="disabled">
7<input type="text" disabled="true">
8
9<!-- Common boolean attributes -->
10<a href="/page" target="_blank" rel="noopener">External Link</a>
11<img src="photo.jpg" alt="Photo" loading="lazy" decoding="async">
12<script src="app.js" defer></script>
13<script src="analytics.js" async></script>
14<input type="file" multiple accept="image/*">
15<form novalidate>
16 <input type="email" required>
17 <input type="text" readonly value="Fixed value">
18</form>
19<video controls autoplay muted loop poster="thumb.jpg">
20 <source src="video.mp4" type="video/mp4">
21</video>
22<details open>
23 <summary>Click to collapse</summary>
24 <p>This content is visible by default.</p>
25</details>
26<option selected>Pick me</option>
27<input type="text" autocomplete="off" autofocus>
28<iframe sandbox="allow-scripts" allowfullscreen></iframe>
AttributeElementsPurpose
disabledinput, button, select, textareaPrevents interaction
requiredinput, select, textareaField must be filled before submit
readonlyinput, textareaUser cannot modify value
checkedinput (checkbox, radio)Pre-selects the control
multipleinput, selectAllows multiple values
autoplayaudio, videoStarts playback immediately
loopaudio, videoRepeats when reaching the end
mutedaudio, videoAudio starts muted
controlsaudio, videoShows browser default controls
deferscriptExecutes after DOM parsing
asyncscriptExecutes as soon as loaded
novalidateformDisables browser validation
autofocusinput, select, textarea, buttonGains focus on page load

best practice

Do not use disabled="false" to enable an element. Simply remove the disabled attribute entirely. Boolean attributes only have meaning when present or absent.
Data Attributes

Custom data attributes let you store extra information on any HTML element using the data-* naming convention. They are accessible from JavaScript via the dataset property and from CSS via attribute selectors:

data-attributes.html
HTML
1<!-- Data attributes: data-* naming convention -->
2<div
3 class="product-card"
4 data-product-id="42"
5 data-category="electronics"
6 data-price="299.99"
7 data-in-stock="true"
8>
9 <h3>Wireless Headphones</h3>
10 <p>$299.99</p>
11 <button data-action="add-to-cart" data-quantity="1">
12 Add to Cart
13 </button>
14</div>
15
16<!-- Complex data stored as JSON strings -->
17<div
18 data-config='{"theme":"dark","lang":"en","analytics":true}'
19 data-permissions='["read","write","admin"]'
20></div>
21
22<!-- Testing and analytics selectors -->
23<button data-testid="checkout-button" data-track-click="checkout">
24 Checkout
25</button>
26
27<!-- State tracking for UI components -->
28<div class="tabs" data-active-tab="overview">
29 <button data-tab="overview">Overview</button>
30 <button data-tab="details">Details</button>
31 <button data-tab="reviews">Reviews</button>
32</div>
data-attributes-js.js
JavaScript
1// Accessing data attributes in JavaScript
2const card = document.querySelector('.product-card');
3
4// Via dataset property (camelCase conversion)
5console.log(card.dataset.productId); // "42"
6console.log(card.dataset.category); // "electronics"
7console.log(card.dataset.price); // "299.99"
8console.log(card.dataset.inStock); // "true" (string, not boolean!)
9
10// Parse values appropriately
11const price = parseFloat(card.dataset.price);
12const inStock = card.dataset.inStock === 'true';
13const config = JSON.parse(card.dataset.config);
14
15// Via getAttribute (always returns string or null)
16console.log(card.getAttribute('data-product-id')); // "42"
17console.log(card.getAttribute('data-missing')); // null
18
19// Modify data attributes
20card.dataset.price = "199.99";
21card.dataset.lastUpdated = new Date().toISOString();
ARIA Attributes

ARIA (Accessible Rich Internet Applications) attributes make web content more accessible to assistive technologies like screen readers. There are two types: roles (via the role attribute) and properties/states (via aria-* attributes):

aria-attributes.html
HTML
1<!-- ARIA roles: define what an element is -->
2<div role="button" tabindex="0" onclick="submit()">Submit</div>
3<nav role="navigation" aria-label="Main menu">
4 <ul>
5 <li><a href="/">Home</a></li>
6 <li><a href="/about">About</a></li>
7 </ul>
8</nav>
9
10<!-- ARIA properties: describe element semantics -->
11<div role="alert" aria-live="polite" aria-atomic="true">
12 Your changes have been saved.
13</div>
14
15<!-- ARIA states: describe current condition -->
16<button
17 aria-expanded="false"
18 aria-controls="dropdown-menu"
19 onclick="toggleMenu(this)"
20>
21 Options
22</button>
23<ul id="dropdown-menu" role="menu" hidden>
24 <li role="menuitem">Edit</li>
25 <li role="menuitem">Delete</li>
26</ul>
27
28<!-- Common ARIA patterns -->
29<div role="tablist" aria-label="Content tabs">
30 <button role="tab" aria-selected="true" aria-controls="panel-1">
31 Tab 1
32 </button>
33 <button role="tab" aria-selected="false" aria-controls="panel-2">
34 Tab 2
35 </button>
36</div>
37<div role="tabpanel" id="panel-1" aria-labelledby="tab-1">
38 <p>Tab 1 content</p>
39</div>
40
41<!-- Progress indicator -->
42<progress aria-label="Upload progress" value="70" max="100"></progress>
43
44<!-- Labeling for screen readers -->
45<label for="email-input">Email address</label>
46<input
47 id="email-input"
48 type="email"
49 aria-describedby="email-hint email-error"
50 aria-invalid="false"
51 required
52>
53<span id="email-hint">We never share your email.</span>
54<span id="email-error" role="alert" hidden>Please enter a valid email.</span>

info

The first rule of ARIA is: do not use ARIA if a native HTML element provides the semantics you need. Use <button> instead of role="button", <nav> instead of role="navigation", and <dialog> instead of role="dialog". Native elements come with keyboard support and built-in semantics for free.
Event Handler Attributes

Event handler attributes allow you to execute JavaScript in response to events directly in HTML. While inline handlers are generally discouraged in favor of addEventListener, they are useful for simple interactions and prototyping:

event-handlers.html
HTML
1<!-- Inline event handlers -->
2<button onclick="alert('Hello!')">Click Me</button>
3<input type="text" onfocus="this.style.borderColor='#00FF41'">
4<input type="text" onblur="this.style.borderColor=''">
5<img src="photo.jpg" onerror="this.src='/placeholder.png'">
6<form onsubmit="return handleSubmit(event)">
7 <input type="text" name="q" required>
8 <button type="submit">Search</button>
9</form>
10
11<!-- Common event handler attributes -->
12<input oninput="validateField(this)" type="email">
13<select onchange="updatePreview(this.value)">
14 <option>Option 1</option>
15</select>
16<div onmouseenter="highlight(this)" onmouseleave="unhighlight(this)">
17 Hover me
18</div>
19<body onkeydown="handleKeyboard(event)"></body>
20
21<!-- Better pattern: addEventListener in JS -->
22<button id="action-btn">Action</button>
23<script>
24 document.getElementById('action-btn').addEventListener('click', () => {
25 alert('This is the preferred approach.');
26 });
27</script>

warning

Inline event handlers cannot access local variables from closures, they must be global functions, and they mix structure with behavior. Use addEventListener for any non-trivial logic. The on* attributes are best reserved for simple fallback behavior like onerror on images.
Custom Attributes

HTML5 allows any attribute on any element, but non-standard attributes should follow the data- prefix convention. Attributes without the data- prefix that are not part of the HTML specification will cause validator warnings, though browsers will still render them:

custom-attributes.html
HTML
1<!-- Standard: data-* attributes for custom data -->
2<div data-tooltip="Click to expand" data-tooltip-position="top">
3 Hoverable card
4</div>
5
6<!-- Non-standard: works but generates validator warnings -->
7<div custom-attr="value">
8 This works but is not valid HTML
9</div>
10
11<!-- Useful custom attribute patterns -->
12<div data-controller="dropdown" data-action="click->dropdown#toggle">
13 Interactive component
14</div>
15
16<div data-react-component="PriceDisplay" data-props='{"price":29.99,"currency":"USD"}'>
17 React mount point
18</div>
19
20<!-- Framework-specific data attributes -->
21<div
22 data-testid="user-profile"
23 data-cy="profile-section"
24 data-qa="user-info"
25>
26 <h2>Profile</h2>
27</div>
28
29<!-- Validation configuration via data attributes -->
30<input
31 type="text"
32 data-validate="required|minLength:3|maxLength:50|pattern:^[a-zA-Z]+$"
33 data-error-message="Please enter 3-50 letters only"
34 name="username"
35>

info

Always use the data- prefix for custom attributes. This keeps your markup valid, prevents naming collisions with future HTML attributes, and signals to other developers that the attribute is application-specific.
Best Practices
Always use lowercase attribute names (href, not HREF) — HTML5 is case-insensitive but lowercase is convention
Always quote attribute values — use double quotes for consistency and to avoid parsing edge cases
Use boolean attributes correctly — presence means true, absence means false, never write disabled="false"
Use data-* attributes for custom application data — never use random attribute names without the prefix
Prefer class over id for styling hooks — id should be reserved for unique identifiers and ARIA references
Avoid inline style attributes — use CSS classes for all production styling
Keep ARIA attributes minimal — use native HTML elements with implicit semantics whenever possible
Do not repeat id values within a page — duplicate IDs break accessibility, JavaScript, and CSS selectors
Use aria-label or aria-labelledby for elements that lack visible text labels
Clean up event handler attributes — prefer addEventListener in JavaScript over inline onclick handlers
Live Demo

The following demo shows global and boolean attributes in action. Click the button to toggle the disabled state, and hover over elements to see title tooltips:

preview
Browser Support

All global attributes discussed on this page are supported in every modern browser. The following table covers the more advanced attributes:

AttributeChromeFirefoxSafariEdge
data-*
contenteditable
draggable
spellcheck
tabindex
ARIA attributes
$ForgeLearn — Engineering Documentation·Section ID: HTML-15·Revision: 1.0