Obsolete Elements, Void Reference, ARIA Deep Dive & Validation - vdsology
- Chapter 10 — Obsolete Elements, Void Reference, ARIA Deep Dive & Validation
- 10.1 — Obsolete Elements
- 10.2 — Obsolete Attributes
- 10.3 — The 13 Void Elements
- 10.4 — HTML Content Categories
- 10.5 — The Five Rules of ARIA
- 10.6 — ARIA Live Regions
- 10.7 — ARIA Widget Patterns
- 10.8 — Accessible Name Computation Priority
- 10.9 — Validation Tools
- 10.10 — The 14 Most Common Validation Errors
- 10.11 — Master Element Inventory (All 115 Non-Obsolete Elements)
Chapter 10 — Obsolete Elements, Void Reference, ARIA Deep Dive & Validation
10.1 — Obsolete Elements
The following elements must not be used in new content (excluding explicitly noted exceptions).
Presentational (Replaced by CSS)
| Obsolete element | Modern replacement |
|---|---|
<font> |
CSS font-family, font-size, color |
<center> |
CSS text-align: center or flexbox |
<big> |
CSS font-size: larger |
<tt> |
<code>, <kbd>, <samp> or CSS font-family: monospace |
<strike> |
<s> or <del> |
<blink> |
CSS animation (use sparingly) |
<marquee> |
CSS animation with overflow: hidden |
<basefont> |
CSS on body |
Layout Frame Elements
| Obsolete element | Modern replacement |
|---|---|
<frame> |
<iframe> for embeds; CSS Grid/Flexbox for layout |
<frameset> |
CSS layout systems |
<noframes> |
N/A |
Plugin Elements
| Obsolete element | Modern replacement |
|---|---|
<applet> |
<object> or native web APIs |
<bgsound> |
<audio> |
Obsolete Form Elements
| Obsolete element | Modern replacement |
|---|---|
<isindex> |
<input type="search"> |
<keygen> |
Web Cryptography API (window.crypto.subtle) |
Obsolete Semantic Elements
| Obsolete element | Modern replacement |
|---|---|
<acronym> |
<abbr title="…"> |
<dir> |
<ul> |
Obsolete Scripting/Behaviour Elements
| Obsolete element | Modern replacement |
|---|---|
<listing> |
<pre><code>…</code></pre> |
<xmp> |
<pre><code>…</code></pre> |
<plaintext> |
N/A |
<noembed> |
Content inside <object> |
<rb> |
Base text directly in <ruby> |
<rtc> |
<rt> elements directly |
<menu type="context"> |
JavaScript contextmenu event |
<menuitem> |
N/A |
10.2 — Obsolete Attributes
Valid elements — obsolete attributes:
| Attribute | Element | Replacement |
|---|---|---|
align |
Most elements | CSS text-align, margin: auto |
bgcolor |
<body>, <table>, cells |
CSS background-color |
border |
<table>, <img> |
CSS border |
cellpadding |
<table> |
CSS padding on <td> |
cellspacing |
<table> |
CSS border-spacing |
valign |
Table cells | CSS vertical-align |
width/height |
<table>, <hr>, <pre>, <col> |
CSS width/height |
color |
<hr> |
CSS color, border-color |
compact |
Lists | CSS margin, padding |
name |
<a> (non-form) |
id attribute |
hspace/vspace |
<img> |
CSS margin |
language |
<script> |
type attribute |
link/vlink/alink |
<body> |
CSS :link, :visited, :active |
accept-charset |
<form> |
Ensure UTF-8 throughout |
noshade |
<hr> |
CSS |
nowrap |
Table cells | CSS white-space: nowrap |
summary |
<table> |
<caption> or aria-labelledby |
10.3 — The 13 Void Elements
Void elements never have children and must not have closing tags.
| Element | Chapter | Purpose |
|---|---|---|
<area> |
6 | Clickable region in image map |
<base> |
2 | Base URL for relative links |
<br> |
5 | Line break |
<col> |
7 | Column in column group |
<embed> |
6 | External content |
<hr> |
4 | Thematic break |
<img> |
6 | Image |
<input> |
8 | Form control |
<link> |
2 | External resource |
<meta> |
2 | Metadata |
<source> |
6 | Media source |
<track> |
6 | Text track for media |
<wbr> |
5 | Word break opportunity |
In HTML serialisation, self-closing slash is optional and has no effect. In XHTML/XML serialisation, <img/> syntax is required.
10.4 — HTML Content Categories
METADATA CONTENT — used in <head>
<link>, <meta>, <style>, <script>, <title>, <base>, <noscript>, <template>
FLOW CONTENT — everything in <body>
│
├── SECTIONING CONTENT — creates document outline
│ <article>, <aside>, <nav>, <section>
│
├── HEADING CONTENT
│ <h1>–<h6>, <hgroup>
│
├── PHRASING CONTENT — "inline" elements
│ Text + inline elements (content of paragraphs)
│ │
│ ├── EMBEDDED CONTENT
│ │ <img>, <picture>, <video>, <audio>, <canvas>,
│ │ <iframe>, <embed>, <object>, <svg>, <math>
│ │
│ └── INTERACTIVE CONTENT
│ <a href>, <button>, <input>, <select>, <textarea>,
│ <details>, <dialog>
│
└── TRANSPARENT CONTENT
Content model inherited from parent
<a>, <ins>, <del>, <map>, <noscript>, <canvas>
SECTIONING ROOT — headings don't affect outer outline
<body>, <blockquote>, <details>, <dialog>,
<fieldset>, <figure>, <td>
FORM-ASSOCIATED CONTENT
Listed: <button>, <input>, <select>, <textarea>, <output>, <object>
Labelable: <button>, <input>, <meter>, <output>, <progress>, <select>, <textarea>
Submittable: <button>, <input>, <select>, <textarea>
Resettable: <input>, <output>, <select>, <textarea>
10.5 — The Five Rules of ARIA
Rule 1: Use native HTML first. <button> over <div role="button">.
Rule 2: Never change native semantics unless absolutely necessary.
Rule 3: All interactive ARIA controls must be keyboard operable. If you build <div role="button">, handle Space and Enter keys yourself.
Rule 4: Never use aria-hidden="true" on focusable elements.
Rule 5: All interactive elements must have an accessible name.
10.6 — ARIA Live Regions
aria-live values
off— No announcements (default)polite— Announce after current speech finishesassertive— Interrupt immediately (critical errors only)
aria-atomic
false— Announce only changed nodes (default)true— Announce entire region when any part changes
aria-relevant
Space-separated: additions, removals, text, all. Default: additions text.
aria-busy
Set to true while updating, false when done.
Predefined Live Region Roles
| Role | aria-live |
aria-atomic |
Use for |
|---|---|---|---|
alert |
assertive |
true |
Critical errors — interrupts immediately |
status |
polite |
true |
Confirmations, status messages |
log |
polite |
false |
Chat, logs — new entries announced |
timer |
off |
— | Countdowns — announced on focus only |
marquee |
off |
— | Scrolling (avoid) |
<div role="alert" id="error-region">
<!-- Injecting here announces immediately -->
</div>
<div role="status" id="success-region">
<!-- "File saved successfully." -->
</div>
<div role="log" id="chat-log" aria-live="polite">
<!-- New messages appended here -->
</div>
Golden rule: The live region must exist in the DOM before content is injected into it.
10.7 — ARIA Widget Patterns
Tabs
<div class="tabs">
<div role="tablist" aria-label="Content sections">
<button role="tab" id="tab-1" aria-selected="true"
aria-controls="panel-1" tabindex="0">Overview</button>
<button role="tab" id="tab-2" aria-selected="false"
aria-controls="panel-2" tabindex="-1">Specs</button>
<button role="tab" id="tab-3" aria-selected="false"
aria-controls="panel-3" tabindex="-1">Reviews</button>
</div>
<div role="tabpanel" id="panel-1" aria-labelledby="tab-1" tabindex="0">
Overview content
</div>
<div role="tabpanel" id="panel-2" aria-labelledby="tab-2" tabindex="0" hidden>
Specs content
</div>
<div role="tabpanel" id="panel-3" aria-labelledby="tab-3" tabindex="0" hidden>
Reviews content
</div>
</div>
Keyboard: →/← = move between tabs (roving tabindex). Tab = move to panel.
Menu / Menubar
<nav role="menubar" aria-label="Application menu">
<button role="menuitem" type="button"
aria-haspopup="menu" aria-expanded="false"
aria-controls="file-menu">File</button>
<ul role="menu" id="file-menu" aria-labelledby="file-menu-btn" hidden>
<li role="none">
<button role="menuitem" type="button">New</button>
</li>
<li role="separator" aria-orientation="horizontal"></li>
<li role="none">
<button role="menuitemcheckbox" aria-checked="true">Show Ruler</button>
</li>
</ul>
</nav>
Keyboard: ↑/↓ = move between items. Esc = close. Printable char = jump to item.
Slider
<div role="slider"
aria-labelledby="volume-label"
aria-valuemin="0" aria-valuemax="100"
aria-valuenow="50" aria-valuetext="50 percent"
tabindex="0">
<div class="slider-track">
<div class="slider-thumb" style="left: 50%"></div>
</div>
</div>
Keyboard: →/↑ = increase. ←/↓ = decrease. Home/End = min/max.
Data Grid
<div role="grid" aria-label="Sales data">
<div role="rowgroup">
<div role="row">
<div role="columnheader" aria-sort="ascending">Name ↑</div>
<div role="columnheader">Q1</div>
</div>
</div>
<div role="rowgroup">
<div role="row" aria-selected="false">
<div role="gridcell" tabindex="0">Alice</div>
<div role="gridcell" tabindex="-1">£120k</div>
</div>
</div>
</div>
Keyboard: Arrow keys = navigate cells. Enter = edit. Esc = cancel edit.
10.8 — Accessible Name Computation Priority
aria-labelledby(highest — references another element’s text)aria-label(directly supplied string)- Native label mechanisms (
<label>,<caption>,alt,<legend>) - Text content (for buttons, links, headings)
titleattribute (lowest — not accessible on mobile)
Accessible description:
aria-describedby— secondary supplementary texttitleattribute — shown as tooltip, used as description
10.9 — Validation Tools
Nu Html Checker (W3C): https://validator.w3.org/nu/
Command line:
curl -s -H "Content-Type: text/html; charset=utf-8" \
--data-binary @index.html \
"https://validator.w3.org/nu/?out=json" | jq '.messages[]'
Build tools:
npm install --save-dev htmlhint
npx html-validate "**/*.html"
npx @axe-core/cli https://localhost:3000
10.10 — The 14 Most Common Validation Errors
- Missing
alton<img>— Always present; empty""for decorative - Missing
<title>— Required; must be non-empty - Duplicate
idvalues — IDs must be unique per document - Block element inside
<p>—<p>can only contain phrasing content <button>inside<a>— Interactive inside interactive<li>without list parent — Must be inside<ul>,<ol>, or<menu><td>without<tr>— Table elements must have correct parents<form>inside<form>— Nested forms are invalid- Missing
langon<html>— Required for accessibility charsetnot first in<head>— Must precede<title>- Multiple visible
<main>elements — Only one visible; others needhidden valueon<li>in<ul>—valueonly meaningful in<ol><label for>pointing to non-existent id — Must match a real idaria-hidden="true"on focusable element — Never hide focusable elements
10.11 — Master Element Inventory (All 115 Non-Obsolete Elements)
Document Structure: <!DOCTYPE html> · <html> · <head> · <body>
Metadata: <title> · <base> · <link> · <meta> · <style> · <script> · <noscript>
Sectioning: <article> · <section> · <nav> · <main> · <aside> · <header> · <footer> · <address> · <search> · <hgroup> · <h1> · <h2> · <h3> · <h4> · <h5> · <h6>
Text Blocks: <p> · <div> · <ul> · <ol> · <li> · <menu> · <dl> · <dt> · <dd> · <figure> · <figcaption> · <blockquote> · <pre> · <hr>
Inline Text: <a> · <em> · <strong> · <small> · <s> · <cite> · <q> · <dfn> · <abbr> · <ruby> · <rt> · <rp> · <data> · <time> · <code> · <var> · <samp> · <kbd> · <sub> · <sup> · <i> · <b> · <u> · <mark> · <del> · <ins> · <bdi> · <bdo> · <span> · <br> · <wbr>
Embedded: <img> · <picture> · <source> · <video> · <audio> · <track> · <iframe> · <embed> · <object> · <canvas> · <map> · <area> · <svg> · <math>
Tables: <table> · <caption> · <colgroup> · <col> · <thead> · <tbody> · <tfoot> · <tr> · <th> · <td>
Forms: <form> · <input> · <textarea> · <select> · <option> · <optgroup> · <datalist> · <selectedcontent> · <button> · <label> · <fieldset> · <legend> · <output> · <progress> · <meter>
Interactive & Scripting: <details> · <summary> · <dialog> · <template> · <slot>
Tags: #html #vdsology #webdevelopment #vdsologyhtml #html5 #htmlreference #htmlreference2026
Write a comment