HTML Attributes and Global Properties
1. Core Global Attributes (id, class, title, lang)
| Attribute | Purpose | Values | Uniqueness |
|---|---|---|---|
| id | Unique identifier for element | Alphanumeric, hyphen, underscore (no spaces) | Must be unique per page |
| class | CSS class name(s) for styling | Space-separated list of class names | Can be reused across elements |
| title | Advisory information (tooltip) | Any text (shows on hover) | Can be duplicated |
| lang | Language of element content | BCP 47 language tag (e.g., en, es, fr) | Inherits from parent if not set |
| dir | Text directionality | ltr, rtl, auto |
Inherits from parent |
| style | Inline CSS styles | CSS property declarations | Avoid (use CSS instead) |
| tabindex | Tab order for keyboard navigation | Integer (-1, 0, positive) | Controls focus order |
| accesskey | Keyboard shortcut to activate element | Single character | Limited browser support |
ID Attribute Rules:
- Must be unique on the page
- Start with letter (a-z, A-Z)
- Can contain: letters, digits, hyphens, underscores, periods
- Case-sensitive
- Used for: CSS, JavaScript, URL fragments (#)
- Avoid special characters and spaces
Example: Core global attributes usage
<!-- ID - unique identifier -->
<div id="main-content">...</div>
<a href="#main-content">Skip to content</a>
<!-- Class - multiple classes -->
<p class="intro highlight important">Important introduction</p>
<!-- Title - tooltip text -->
<abbr title="HyperText Markup Language">HTML</abbr>
<button title="Click to submit form">Submit</button>
<!-- Lang - language specification -->
<html lang="en">
<p lang="es">Hola, ¿cómo estás?</p>
<p lang="fr">Bonjour, comment allez-vous?</p>
<!-- Dir - text direction -->
<p dir="ltr">Left to right text (English)</p>
<p dir="rtl">نص من اليمين إلى اليسار (Arabic)</p>
<!-- Tabindex - keyboard navigation -->
<div tabindex="0">Keyboard focusable div</div>
<div tabindex="-1">Script-only focusable</div>
<!-- Accesskey - keyboard shortcut -->
<a href="/" accesskey="h">Home</a> <!-- Alt+H or similar -->
Warning: Avoid positive tabindex values (1, 2, 3...) as they disrupt natural tab order and harm
accessibility. Use
tabindex="0" for custom interactive elements.
2. Event Handler Attributes (onclick, onload, etc.)
| Category | Events | Fires When |
|---|---|---|
| Mouse Events | onclick, ondblclick, onmousedown, onmouseup,
onmouseover, onmouseout, onmousemove
|
User interacts with mouse/pointer |
| Keyboard Events | onkeydown, onkeyup, onkeypress DEPRECATED |
User presses/releases keys |
| Form Events | onsubmit, onchange, oninput, onfocus,
onblur, onreset
|
Form field interactions |
| Document Events | onload, onunload, onbeforeunload, onresize,
onscroll
|
Document/window state changes |
| Drag Events | ondrag, ondragstart, ondragend, ondragover,
ondrop
|
Drag and drop operations |
| Media Events | onplay, onpause, onended, onvolumechange,
ontimeupdate
|
Media playback events |
| Clipboard Events | oncopy, oncut, onpaste |
Clipboard operations |
Common Mouse Events
| Event | Use Case |
|---|---|
| onclick | Button clicks, interactive elements |
| ondblclick | Double-click actions |
| onmouseover | Hover effects, tooltips |
| onmouseout | End hover effects |
Best Practices:
- Prefer addEventListener() in JavaScript
- Inline event handlers discouraged
- Violates separation of concerns
- Harder to maintain and debug
- Security risks (CSP violations)
- Limited to single handler per event
Example: Inline event handlers (avoid in production)
<!-- Mouse events -->
<button onclick="alert('Clicked!')">Click Me</button>
<div onmouseover="this.style.background='yellow'">Hover me</div>
<!-- Keyboard events -->
<input type="text" onkeydown="console.log('Key pressed')">
<!-- Form events -->
<form onsubmit="return validateForm()">
<input type="text" onchange="handleChange(this.value)">
<input type="text" oninput="liveUpdate(this.value)">
</form>
<!-- Document events -->
<body onload="init()" onresize="handleResize()">
<!-- PREFERRED: Use addEventListener in JavaScript -->
<button id="myButton">Click Me</button>
<script>
document.getElementById('myButton')
.addEventListener('click', function() {
alert('Clicked!');
});
</script>
Warning: Inline event handlers are discouraged. Use
addEventListener() in JavaScript files for better maintainability, multiple handlers, and Content
Security Policy compliance.
3. Data Attributes (data-*) and Custom Properties
| Feature | Syntax | Purpose | Access Method |
|---|---|---|---|
| Data Attributes | data-{name}="{value}" |
Store custom data on elements | JavaScript: element.dataset.name |
| Naming Rules | Lowercase, hyphen-separated | Valid: data-user-id |
Converts to camelCase in dataset |
| Values | String (any text) | Store: IDs, config, state | Always returns string |
Data Attribute Rules:
- Must start with
data- - Name must be lowercase
- Use hyphens for multi-word names
- No uppercase letters after "data-"
- Can store any string value
- Accessible via CSS attribute selectors
Example: Data attributes usage
<!-- Storing IDs and metadata -->
<article data-post-id="12345" data-author="john" data-category="tech">
<h2>Article Title</h2>
</article>
<!-- Configuration data -->
<button data-action="delete" data-confirm="true" data-target-id="item-123">
Delete
</button>
<!-- State information -->
<div data-state="collapsed" data-animate="true">Collapsible content</div>
<!-- Complex data (JSON) -->
<div data-config='{"theme":"dark","size":"large"}'></div>
<!-- JavaScript access -->
<script>
const article = document.querySelector('article');
// Read data attributes
console.log(article.dataset.postId); // "12345"
console.log(article.dataset.author); // "john"
console.log(article.dataset.category); // "tech"
// Set data attributes
article.dataset.views = "1500";
article.dataset.publishDate = "2025-12-21";
// Delete data attribute
delete article.dataset.category;
</script>
<!-- CSS with data attributes -->
<style>
[data-state="collapsed"] { display: none; }
[data-theme="dark"] { background: black; color: white; }
</style>
Note: Data attributes are visible in HTML source. Don't store
sensitive information. Values are always strings; parse JSON/numbers in JavaScript if needed.
4. Content Editable and User Interaction
| Attribute | Values | Purpose | Browser Support |
|---|---|---|---|
| contenteditable | true, false, inherit |
Makes element editable by user | All modern browsers |
| spellcheck | true, false |
Enable/disable spell checking | All modern browsers |
| translate | yes, no |
Control automatic translation | Modern browsers |
| autocapitalize | off, on, words, characters |
Auto-capitalization (mobile) | Mobile browsers |
| inputmode | text, numeric, tel, email, url |
Virtual keyboard type (mobile) | Mobile browsers |
| enterkeyhint | enter, done, go, next, search,
send
|
Enter key label (mobile) | Mobile browsers |
ContentEditable Use Cases:
- Rich text editors (WYSIWYG)
- Inline editing interfaces
- Note-taking applications
- Collaborative editing tools
- Content management systems
- Live comment editing
Example: Content editable and user interaction
<!-- Basic contenteditable -->
<div contenteditable="true">
This text can be edited by the user. Click to edit.
</div>
<!-- Rich text editor -->
<div contenteditable="true" spellcheck="true" class="editor">
<h2>Editable Heading</h2>
<p>Editable paragraph with spell checking enabled.</p>
</div>
<!-- Disable editing in child -->
<div contenteditable="true">
Editable content
<span contenteditable="false">But this part is not editable</span>
</div>
<!-- Spellcheck control -->
<textarea spellcheck="true"></textarea>
<textarea spellcheck="false"></textarea>
<!-- Translation control -->
<p translate="no">Product Name™</p>
<code translate="no">console.log()</code>
<!-- Mobile keyboard optimization -->
<input type="text" inputmode="numeric" enterkeyhint="done"
placeholder="Enter amount">
<input type="text" inputmode="email" enterkeyhint="next">
<input type="text" inputmode="tel" pattern="[0-9]*">
<!-- Auto-capitalization -->
<input type="text" autocapitalize="words"> <!-- Title Case -->
<input type="text" autocapitalize="characters"> <!-- ALL CAPS -->
Warning: ContentEditable creates security risks. Always sanitize
user input before saving. Malicious users can paste HTML/scripts. Use libraries like DOMPurify for sanitization.
5. Draggable and Drop Zone Attributes
| Attribute | Values | Purpose | Use On |
|---|---|---|---|
| draggable | true, false, auto |
Makes element draggable | Any element |
| dropzone REMOVED | copy, move, link |
Defines drop behavior (removed from spec) | Drop targets |
Example: Drag and drop implementation
<!-- Draggable elements -->
<div draggable="true" id="drag1" ondragstart="drag(event)">
Drag me!
</div>
<!-- Drop zone -->
<div id="dropzone" ondrop="drop(event)" ondragover="allowDrop(event)">
Drop here
</div>
<script>
function drag(event) {
// Store dragged element's ID
event.dataTransfer.setData("text", event.target.id);
event.dataTransfer.effectAllowed = "move";
}
function allowDrop(event) {
// Must prevent default to allow drop
event.preventDefault();
event.dataTransfer.dropEffect = "move";
}
function drop(event) {
event.preventDefault();
const data = event.dataTransfer.getData("text");
const draggedElement = document.getElementById(data);
event.target.appendChild(draggedElement);
}
</script>
<!-- List reordering example -->
<ul>
<li draggable="true">Item 1</li>
<li draggable="true">Item 2</li>
<li draggable="true">Item 3</li>
</ul>
<!-- File upload drop zone -->
<div id="file-drop" ondrop="handleFiles(event)" ondragover="allowDrop(event)">
Drop files here to upload
</div>
Note: Default draggable elements:
<a>, <img>, selected
text. For custom elements, set draggable="true". Must call preventDefault() on
dragover to enable drop.
6. Hidden, Inert, and Visibility Controls
| Attribute | Values | Effect | Accessibility |
|---|---|---|---|
| hidden | Boolean (no value needed) | Removes from rendering (display: none) | Hidden from screen readers |
| inert NEW | Boolean | Makes element and descendants inert (unfocusable, unclickable) | Disabled for all interactions |
| aria-hidden | true, false |
Visible but hidden from screen readers | Hidden from assistive tech only |
Visibility Comparison
| Method | Display | Screen Reader | Focusable |
|---|---|---|---|
| hidden | ❌ Hidden | ❌ Hidden | ❌ No |
| inert | ✅ Visible | ❌ Hidden | ❌ No |
| aria-hidden | ✅ Visible | ❌ Hidden | ✅ Yes |
| visibility:hidden | ❌ Hidden | ❌ Hidden | ❌ No |
| opacity:0 | ❌ Hidden | ✅ Visible | ✅ Yes |
Use Cases:
hidden: Conditional content, tabs, accordionsinert: Modal backgrounds, loading statesaria-hidden: Decorative icons, duplicates- Toggle
hiddenwith JavaScript - Inert prevents focus traps
- Combine for complex visibility needs
Example: Visibility control attributes
<!-- Hidden attribute -->
<div hidden>
This content is completely hidden from view and screen readers.
</div>
<!-- Toggle hidden with JavaScript -->
<button onclick="toggle()">Toggle</button>
<div id="content" hidden>Hidden content</div>
<script>
function toggle() {
const el = document.getElementById('content');
el.hidden = !el.hidden;
}
</script>
<!-- Inert attribute (disable interactions) -->
<div inert>
This content is visible but cannot be interacted with.
<button>Can't click me</button>
<a href="#">Can't follow this link</a>
</div>
<!-- Modal with inert background -->
<main inert>Background content (inert when modal open)</main>
<dialog open>
<h2>Modal Dialog</h2>
<button>Close</button>
</dialog>
<!-- aria-hidden (visible but hidden from screen readers) -->
<button>
<span aria-hidden="true">🔍</span>
Search
</button>
<!-- Decorative images -->
<img src="decoration.png" aria-hidden="true" alt="">
<!-- Tab panels -->
<div role="tabpanel" hidden id="tab1">Tab 1 content</div>
<div role="tabpanel" id="tab2">Tab 2 content (visible)</div>
Warning: Don't use
aria-hidden="true" on focusable elements. This creates
confusion where keyboard users can focus invisible content. Use hidden or inert
instead.
Section 4 Key Takeaways
idmust be unique per page;classcan be reused- Use
tabindex="0"for custom focusable elements; avoid positive values - Prefer
addEventListener()over inline event handlers - Data attributes (
data-*) store custom data; access viadataset contenteditable="true"enables rich text editing; sanitize inputdraggable="true"enables drag; must preventDefault on dragoverhiddenremoves from view;inertdisables interactionsaria-hiddenhides from screen readers only (keep visible)