Global Attributes & i18n
Global attributes work on any HTML element regardless of tag. A small set of them -- `lang`, `dir`, `id`, `class`, `data-*`, and `hidden` -- are the foundation of accessible, internationalised, and well-structured pages.
What global attributes are
Global attributes are HTML attributes you can place on any element, not just specific ones. class and id are the most familiar: id must be unique per page and serves as a fragment target, an AT label anchor, and a JavaScript handle; class carries zero semantic meaning but is the primary CSS and JS hook. hidden is a boolean attribute that removes an element from both the visual layout and the accessibility tree, which makes it stronger than display:none in CSS alone because assistive technology also ignores it.
The data-* family lets you store arbitrary key-value pairs directly in the markup. Any attribute starting with data- is valid. JavaScript reads and writes them through the dataset API: el.dataset.userId reads data-user-id. CSS can target them with [data-state='open'] selectors. They carry no semantic meaning for assistive technology, so they are the right place to store UI state that drives JavaScript behaviour without polluting the class list.
Why lang and dir matter for i18n
The lang attribute on <html> tells the browser, search engines, and screen readers what language the page is in. Screen readers use it to choose the correct voice and pronunciation engine. Without it, an English reader might pronounce French or Arabic text using English phonetics, making it unintelligible. WCAG 3.1.1 (Language of Page, Level AA) requires it. When a passage within a page switches language, wrap it in any element with lang set to the new language; this covers WCAG 3.1.2 (Language of Parts, Level AA).
The dir attribute controls the text direction and -- crucially -- the inline layout direction. Setting dir="rtl" on a container does more than align text to the right: it mirrors the reading flow, reverses the order of flex children that use flex-start/flex-end, swaps the meaning of logical CSS properties (margin-inline-start becomes the right margin instead of the left), and moves form labels and icons to the expected side for Arabic, Hebrew, and Persian users. Always pair dir on <html> or a container with the matching lang attribute.
How to use them correctly
Set lang on the <html> element using a valid BCP 47 language tag: lang="en" for English, lang="ar" for Arabic, lang="zh-Hant" for Traditional Chinese. For inline overrides, wrap the foreign passage: <span lang="fr">Bonjour</span>. Do not guess the tag; look it up in the IANA Language Subtag Registry.
For bidirectional text, prefer dir="auto" on mixed-content containers and dir="rtl" on fully RTL containers. Use CSS logical properties (padding-inline-start, text-align: start, border-inline-end) instead of physical properties (padding-left, text-align: left) so your layout adapts automatically when direction changes. Avoid hard-coded left and right in RTL-capable layouts.
Use data-* attributes to drive JavaScript and CSS hooks. Name them with hyphens in HTML (data-is-open) and access them in JS via dataset.isOpen (camelCase conversion is automatic). In CSS, select by state: [data-is-open='true'] { display: block; }. Never use data-* to pass information that assistive technology needs to understand; use ARIA for that.
Try it
Toggle dir between ltr and rtl and watch the layout mirror. Switch the active lang to see how the attribute is applied inline.
Text direction
Language
Build for everyone.
Applied attribute
dir="ltr"
Default direction. Flex children flow left to right. margin-inline-start = left side.
Applied attribute
lang="en" — screen reader uses English voice
WCAG 3.1.1 satisfied. AT uses English pronunciation.
data-* attributes
<!-- HTML -->
<button data-panel-open="false" data-panel-id="settings">
Open settings
</button>
<!-- JavaScript -->
const btn = document.querySelector('[data-panel-id="settings"]');
btn.dataset.panelOpen; // "false"
btn.dataset.panelOpen = "true";
<!-- CSS -->
[data-panel-open="true"] { display: block; }dataset converts hyphen-cased attribute names to camelCase automatically. Use data-* for JS and CSS hooks; use ARIA for anything assistive technology needs to understand.
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
langon<html>is required for WCAG 3.1.1 (AA). Use a valid BCP 47 tag like"en"or"ar".dir="rtl"mirrors the full inline layout, not just text -- flex ordering and logical CSS properties are affected.data-*attributes store UI state for JS and CSS; they carry no semantic meaning for AT.hiddenremoves an element from both the visual layout and the accessibility tree.
Done with this concept?
Mark it complete to track your progress. No login needed.