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

Tabindex Values

Value Behavior
-1 Focusable by script, not by tab
0 Natural tab order (recommended)
1+ Explicit order (avoid - breaks accessibility)

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

JavaScript Access

HTML JavaScript
data-id dataset.id
data-user-name dataset.userName
data-index-value dataset.indexValue

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

InputMode Values

Value Keyboard Type
text Standard keyboard
numeric Number pad
tel Telephone keypad
email Email keyboard (@)
url URL keyboard (.com)

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

Drag Events (on dragged element)

Event Fires When
ondragstart Drag begins
ondrag Element is dragged
ondragend Drag operation ends

Drop Events (on drop target)

Event Fires When
ondragenter Dragged element enters
ondragover Dragged over target
ondragleave Dragged element leaves
ondrop Element is dropped

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, accordions
  • inert: Modal backgrounds, loading states
  • aria-hidden: Decorative icons, duplicates
  • Toggle hidden with 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

  • id must be unique per page; class can 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 via dataset
  • contenteditable="true" enables rich text editing; sanitize input
  • draggable="true" enables drag; must preventDefault on dragover
  • hidden removes from view; inert disables interactions
  • aria-hidden hides from screen readers only (keep visible)