Before is a classless, semantic style reset that styles HTML5 elements directly, providing accessible defaults without relying on utility-first CSS libraries or overly complex frameworks. It is themeable (via CSS custom properties) and designed for progressive enhancement, allowing further customization through classes, components, or frameworks when desired. By targeting semantic HTML, it provides a rock-solid, long-term foundation. All components are implemented according to the ARIA Authoring Practices Guide (APG), ensuring they are accessible, predictable, and keyboard-friendly, so your semantic HTML remains usable for everyone.
Before Style is a classless CSS library. This means:
- ❌ Never use CSS classes (no
class="..."attributes) - ✅ Use semantic HTML elements (
<nav>,<article>,<section>, etc.) - ✅ Use ARIA roles and attributes (
role="tablist",aria-orientation="vertical") - ✅ Use HTML5 native attributes (
name="accordion-group",open,disabled) - ✅ Use data attributes (
data-sticky,data-variant="...")
The library provides these CSS custom properties for theming:
:root {
--palette_gray: 0.55 0.01 260;
--palette_red: 0.65 0.20 25;
--palette_orange: 0.70 0.18 55;
--palette_yellow: 0.85 0.18 95;
--palette_green: 0.70 0.17 145;
--palette_blue: 0.65 0.18 250;
--palette_purple: 0.60 0.20 300;
--palette_white: 0.98 0.005 260;
--palette_black: 0.15 0.01 260;
--body_max_width: 120ch;
--body_padding: 1.5rem;
--body_margin: 0 auto;
--scale_opacity: 1;
--scale_contrast: 1;
--scale_font_scaling: 1;
--scale_line_height: 1;
--scale_font_weight: 1;
--scale_border_radius: 0.5;
--scale_shadow_intensity: 1;
--scale_spacing: 1;
--scale_transition_speed: 1;
--tone_opacity_solid: 1;
--tone_opacity_strong: 0.85;
--tone_opacity_normal: 0.7;
--tone_opacity_muted: 0.5;
--tone_opacity_faint: 0.25;
--tone_neutral: oklch(var(--palette_gray));
--tone_info: oklch(var(--palette_blue));
--tone_success: oklch(var(--palette_green));
--tone_warning: oklch(var(--palette_yellow));
--tone_error: oklch(var(--palette_red));
--tone_accent: oklch(var(--palette_purple));
--text_color_primary: oklch(var(--palette_white) / var(--tone_opacity_normal));
--text_color_heading: oklch(var(--palette_white));
--text_color_muted: oklch(var(--palette_white) / var(--tone_opacity_muted));
--text_color_inverse: oklch(var(--palette_black));
--text_color_link: oklch(var(--palette_blue));
--font_family_serif: ui-serif, Georgia, serif;
--font_family_sans: system-ui, -apple-system, sans-serif;
--font_family_mono: ui-monospace, "SF Mono", Menlo, monospace;
--font_family_script: "Comic Sans MS", cursive, sans-serif;
--font_family_display: system-ui, -apple-system, sans-serif;
--font_weight_regular: 400;
--font_weight_medium: 500;
--font_weight_bold: 700;
--font_size_body: 1rem;
--font_size_label: 0.875rem;
--font_size_heading: 1.5rem;
--font_size_code: 0.9rem;
--text_font_body: var(--font_family_sans);
--text_font_heading: var(--font_family_display);
--text_font_label: var(--font_family_sans);
--text_font_code: var(--font_family_mono);
--text_font_system: var(--font_family_sans);
--surface_base: oklch(var(--palette_black));
--surface_raised: oklch(0.96 0.005 260);
--surface_overlay: oklch(0.92 0.005 260);
--surface_sunken: oklch(0.9 0.005 260);
--surface_muted: oklch(0.85 0.005 260);
--surface_base_dark: oklch(var(--palette_black));
--surface_raised_dark: oklch(0.2 0.01 260);
--surface_overlay_dark: oklch(0.25 0.01 260);
--surface_elevated_dark: oklch(0.3 0.01 260);
--surface_border_dark: oklch(0.35 0.01 260);
--surface_interactive: oklch(var(--palette_blue));
--surface_interactive_hover: oklch(0.55 0.18 250);
--surface_interactive_active: oklch(0.5 0.18 250);
--surface_backdrop: oklch(0 0 0 / 0.5);
--surface_highlight: oklch(0.92 0.15 95);
--surface_highlight_dark: oklch(0.45 0.12 95);
}The following HTML5 elements are styled by Before Style:
Anchor element that creates a hyperlink to other pages, files, or locations.
A standard hyperlink with underline styling that inherits the current text color.
<a href="#">Click here to learn more</a>Links that have been visited maintain the current color with slightly reduced opacity.
<a href="#visited-example">Previously visited link</a>Links with target="_blank" automatically display an external link indicator (↗).
<a href="https://example.com" target="_blank" rel="noopener noreferrer">Visit Example.com</a>Links with the download attribute display a download indicator (↓) before the text.
<a href="/files/document.pdf" download>Download PDF</a>Links with mailto: protocol display an email icon (✉) before the text.
<a href="mailto:hello@example.com">hello@example.com</a>Links with tel: protocol display a phone icon (📞) before the text.
<a href="tel:+1234567890">+1 (234) 567-890</a>Use aria-disabled="true" to visually disable a link while maintaining accessibility.
<a href="#" aria-disabled="true">Unavailable link</a>Use aria-current="page" to indicate the current page in navigation. The link appears bold without underline.
<nav>
<a href="/">Home</a>
<a href="/about" aria-current="page">About</a>
<a href="/contact">Contact</a>
</nav>A hidden link that becomes visible on focus, allowing keyboard users to skip to main content.
<a href="#main-content">Skip to main content</a>
<main id="main-content">Main content here...</main>Represents an abbreviation or acronym with an optional title for the full description.
Dotted underline indicates hover for full text.
<p>The <abbr title="World Wide Web">WWW</abbr> changed everything.</p>Provides contact information for the nearest article or body ancestor.
Italic contact information block.
<address>
Contact: <a href="mailto:info@example.com">info@example.com</a><br>
123 Main St, City
</address>Defines a clickable area inside an image map.
Represents a self-contained composition intended for independent distribution or reuse.
Self-contained content block with implicit padding.
<article>
<h2>Article Title</h2>
<p>Article content goes here...</p>
</article>Represents content tangentially related to the main content, often used for sidebars.
Sidebar or supplementary content with subtle styling.
<aside>
<h3>Related Links</h3>
<ul>
<li><a href="#">Link one</a></li>
<li><a href="#">Link two</a></li>
</ul>
</aside>Embeds sound content with controls for playback.
Full-width audio player with native controls.
<audio controls>
<source src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4
" type="audio/mpeg">
Your browser does not support audio.
</audio>Represents text stylistically offset from normal text without conveying extra importance.
Bold text for stylistic offset.
<p>The <b>quick</b> brown fox jumps.</p>Isolates a span of text that might be formatted in a different direction from surrounding text.
Isolates text direction from surrounding content.
<p>User: <bdi>محمد</bdi> - 5 posts</p>Overrides the current text directionality.
Forces text direction override.
<p><bdo dir="rtl">This text is reversed</bdo></p>Indicates an extended quotation from another source.
Indented with a left border to distinguish quoted content.
<blockquote>
<p>The only way to do great work is to love what you do.</p>
</blockquote>Represents the content of an HTML document.
Clean, readable defaults with system fonts, comfortable line height, and responsive max-width for optimal reading.
<p>The body element provides the foundation for all content. It uses system fonts for fast loading and familiar appearance.</p>Produces a line break in text.
Forces a line break within text.
<p>Line one<br>Line two</p>Container for graphics drawn via scripting (usually JavaScript).
Drawing surface with responsive sizing.
<canvas width="300" height="150">
Your browser does not support canvas.
</canvas>Specifies the title of a table.
Descriptive title displayed above the table.
<table>
<caption>Monthly Sales Data</caption>
<tr><th>Month</th><th>Sales</th></tr>
<tr><td>Jan</td><td>$1,000</td></tr>
</table>Represents the title of a creative work being referenced.
Italic text for referencing creative works.
<p>My favorite book is <cite>The Great Gatsby</cite>.</p>Displays a fragment of computer code.
Inline code with subtle background for visibility.
<p>Use the <code>console.log()</code> function to debug.</p>Wrap code in pre for multi-line code blocks.
<pre><code>function greet(name) {
return "Hello, " + name;
}</code></pre>Definesss a column within a table and is used for styling columns.
Groups one or more columns in a table for formatting.
Links content with a machine-readable translation.
Machine-readable value with human display.
<p>Price: <data value="49.99">$49.99</data></p>Contains a set of option elements representing predefined options for an input.
Provides autocomplete options for an input.
<input list="browsers" placeholder="Choose a browser">
<datalist id="browsers">
<option value="Chrome">
<option value="Firefox">
<option value="Safari">
</datalist>Provides the description or value for a term in a description list.
Indented description for a term.
<dl>
<dt>CSS</dt>
<dd>Cascading Style Sheets</dd>
</dl>Represents text that has been deleted from a document.
Strikethrough styling to indicate removed content.
<p>Price: <del>$50</del> $30</p>Creates a disclosure widget from which the user can obtain additional information.
Expandable content with toggle control.
<details>
<summary>Click to expand</summary>
<p>Hidden content revealed when expanded.</p>
</details>Represents a dialog box or other interactive component.
A modal dialog box for user interaction.
<dialog>
<p>This is a dialog box.</p>
<button>Close</button>
</dialog>Indicates the defining instance of a term.
Italic styling for terms being defined.
<p>A <dfn>pixel</dfn> is the smallest unit of a digital image.</p>A generic container for flow content with no semantic meaning.
Generic block-level container.
<div>
<p>Content inside a div.</p>
</div>Represents a description list of term-description pairs.
A list of terms and their descriptions, perfect for glossaries or metadata.
<dl>
<dt>Term</dt>
<dd>The definition or description of the term.</dd>
<dt>Another Term</dt>
<dd>Another definition.</dd>
</dl>Specifies a term in a description list.
Bold term in a definition list.
<dl>
<dt>HTML</dt>
<dd>HyperText Markup Language</dd>
</dl>Marks text with stress emphasis.
Italic text for stress emphasis.
<p>I <em>really</em> mean it.</p>Embeds external content from an external application or plugin.
Groups related elements within a form.
Bordered container for grouping related form fields.
<fieldset>
<legend>Personal Info</legend>
<label>Name</label>
<input type="text">
<label>Email</label>
<input type="email">
</fieldset>Represents a caption or legend for a figure.
Smaller, muted text for describing figure content.
<figcaption>Photo by Jane Doe, 2024</figcaption>Represents self-contained content with an optional caption.
Image container with descriptive caption below.
<figure>
<img src="https://picsum.photos/400/200" alt="Sample">
<figcaption>A descriptive caption for the image.</figcaption>
</figure>Represents the footer of a section or page, typically containing authorship or copyright.
Footer content container.
<footer>
<p>© 2024 Company Name</p>
</footer>Represents a section containing interactive controls for submitting information.
A simple form with inputs and a submit button.
<form>
<label>Name</label>
<input type="text" placeholder="Your name">
<label>Email</label>
<input type="email" placeholder="you@example.com">
<button type="submit">Submit</button>
</form>Represents the highest level section heading.
The main heading of the page. Bold and large for clear hierarchy.
<h1>Main Page Title</h1>Represents a second-level section heading.
Major section heading at 2rem size.
<h2>Section Heading</h2>Represents a third-level section heading.
Subsection heading at 1.5rem size.
<h3>Subsection Heading</h3>Represents a fourth-level section heading.
Minor heading at 1.25rem size.
<h4>Minor Heading</h4>Represents a fifth-level section heading.
Small heading at 1rem size.
<h5>Small Heading</h5>Represents the lowest level section heading.
Smallest heading at 0.875rem size.
<h6>Smallest Heading</h6>Contains machine-readable metadata about the document.
Represents introductory content or navigational aids for a section or page.
Introductory content container.
<header>
<h1>Site Title</h1>
<nav>
<a href="#">Home</a>
<a href="#">About</a>
</nav>
</header>Groups a heading with related content such as subheadings.
Groups heading with subtitle, reduced spacing between.
<hgroup>
<h1>Main Title</h1>
<p>Subtitle or tagline</p>
</hgroup>Represents a thematic break between paragraph-level elements.
A subtle line to separate content sections.
<p>Content above the break.</p>
<hr>
<p>Content below the break.</p>The root element of an HTML document.
Represents text in an alternate voice or mood, such as technical terms or foreign phrases.
Italic text for alternate voice or mood.
<p>The word <i>café</i> is from French.</p>Embeds another HTML page within the current page.
Embedded frame with no border.
<iframe src="https://example.com" title="Embedded page"></iframe>Embeds an image into the document.
Responsive image that scales to its container.
<img src="https://picsum.photos/400/200" alt="Sample image">Creates interactive form controls for accepting user data.
Standard text input with clean borders and focus state.
<input type="text" placeholder="Enter text...">Checkbox input using system accent color.
<label><input type="checkbox"> Accept terms</label>Radio button for single selection from a group.
<label><input type="radio" name="option"> Option A</label>
<label><input type="radio" name="option"> Option B</label>Represents text that has been added to a document.
Underlined to indicate newly added content.
<p>We now offer <ins>free shipping</ins> on all orders.</p>Represents user keyboard input.
Styled like a physical keyboard key with border and shadow.
<p>Press <kbd>Ctrl</kbd> + <kbd>S</kbd> to save.</p>Represents a caption for an item in a user interface.
Block-level label with subtle weight.
<label>Username</label>
<input type="text">Represents a caption for a fieldset.
Caption displayed on fieldset border.
<fieldset>
<legend>Account Info</legend>
<label>Email</label>
<input type="email">
</fieldset>Represents an item in a list.
Individual list items with comfortable spacing.
<ul>
<li>A single list item with proper vertical rhythm</li>
</ul>Represents the dominant content of the body of a document.
Primary content area of the document.
<main>
<h1>Page Title</h1>
<p>Main content goes here...</p>
</main>Defines an image map with clickable areas.
Represents text marked or highlighted for reference or notation.
Yellow highlight for marking relevant content.
<p>Search results: The <mark>quick brown fox</mark> jumps over the lazy dog.</p>Represents metadata that cannot be expressed with other HTML elements.
Represents a section with navigation links.
Navigation block for site or page links.
<nav>
<a href="#">Home</a>
<a href="#">About</a>
<a href="#">Contact</a>
</nav>Defines content to display when scripts are not supported or disabled.
Represents an external resource such as an image, plugin, or nested browsing context.
Represents an ordered list of items.
A numbered list for sequential content.
<ol>
<li>First step</li>
<li>Second step</li>
<li>Third step</li>
</ol>Groups related options within a select element.
Groups options with a bold label.
<select>
<optgroup label="Fruits">
<option>Apple</option>
<option>Banana</option>
</optgroup>
<optgroup label="Vegetables">
<option>Carrot</option>
</optgroup>
</select>Represents an option in a select element or datalist.
Selectable item within a dropdown.
<select>
<option value="1">First option</option>
<option value="2">Second option</option>
</select>Container for the result of a calculation or user action.
Displays calculation results inline.
<p>Total: <output>42</output></p>Represents a paragraph of text.
Standard paragraph with comfortable line height and spacing.
<p>This is a paragraph of text. It has comfortable line height for readability and proper spacing between consecutive paragraphs.</p>
<p>This is a second paragraph demonstrating the vertical rhythm between paragraphs.</p>Contains source elements and one img element for responsive images.
Responsive image container for multiple sources.
<picture>
<source srcset="https://picsum.photos/seed/button/800/400" media="(min-width: 800px)">
<img src="https://picsum.photos/seed/button/400/200" alt="Responsive image">
</picture>Represents preformatted text preserving whitespace and line breaks.
Preserves whitespace and uses monospace font with subtle background.
<pre>Line 1
Line 2
Indented line</pre>Displays the completion progress of a task.
Visual progress indicator using the primary color.
<progress value="70" max="100"></progress>Represents a short inline quotation.
Automatically wrapped with quotation marks.
<p>She said, <q>This is amazing!</q></p>Provides fallback parentheses for browsers that don't support ruby annotations.
Fallback parentheses for non-ruby browsers.
<ruby>漢<rp>(</rp><rt>kan</rt><rp>)</rp></ruby>Specifies the ruby text component of a ruby annotation.
Small annotation text above base character.
<ruby>漢<rt>kan</rt></ruby>Represents a ruby annotation for showing pronunciation of East Asian characters.
Shows pronunciation above characters.
<ruby>
漢 <rp>(</rp><rt>kan</rt><rp>)</rp>
字 <rp>(</rp><rt>ji</rt><rp>)</rp>
</ruby>Represents text that is no longer accurate or relevant.
Text with line through indicating outdated content.
<p>Price: <s>$50</s> $35</p>Represents sample output from a computer program.
Monospace font for computer output.
<p>The error was: <samp>File not found</samp></p>Embeds or references executable JavaScript code.
Represents a standalone section of a document.
Thematic grouping of content.
<section>
<h2>Section Heading</h2>
<p>Section content...</p>
</section>Represents a control providing a menu of options.
Dropdown menu for selecting from predefined options.
<select>
<option>Choose an option</option>
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
</select>A placeholder inside a web component for custom markup.
Represents side comments or small print.
Reduced font size for fine print or disclaimers.
<p>Price: $99 <small>(plus tax)</small></p>Specifies multiple media resources for picture, audio, or video elements.
A generic inline container for phrasing content.
Generic inline container.
<p>This is <span>inline content</span> in a paragraph.</p>Indicates text with strong importance or urgency.
Bold text for emphasis and importance.
<p>This is <strong>very important</strong> information.</p>Contains CSS styling information for a document.
Represents subscript text.
Text positioned below the baseline.
<p>H<sub>2</sub>O is the chemical formula for water.</p>Specifies a visible heading for a details element.
Clickable heading that toggles the details content.
<details>
<summary>Show more info</summary>
<p>Additional information here.</p>
</details>Represents superscript text.
Text positioned above the baseline.
<p>E = mc<sup>2</sup> is Einstein's famous equation.</p>Represents tabular data with rows and columns.
A simple table with headers and data cells.
<table>
<thead>
<tr><th>Name</th><th>Age</th></tr>
</thead>
<tbody>
<tr><td>Alice</td><td>30</td></tr>
<tr><td>Bob</td><td>25</td></tr>
</tbody>
</table>Groups the body content rows of a table.
Container for table body rows.
<table>
<thead>
<tr><th>Name</th></tr>
</thead>
<tbody>
<tr><td>Alice</td></tr>
<tr><td>Bob</td></tr>
</tbody>
</table>Represents a data cell in a table.
Standard data cell with padding and border.
<table>
<tr><th>Item</th><th>Price</th></tr>
<tr><td>Apple</td><td>$1.50</td></tr>
<tr><td>Banana</td><td>$0.75</td></tr>
</table>Holds HTML content that is not rendered but can be instantiated via JavaScript.
Represents a multi-line plain text editing control.
Multi-line input with resizable height.
<textarea placeholder="Enter your message..."></textarea>Groups the footer content rows of a table.
Container for table footer rows, often for totals.
<table>
<thead><tr><th>Item</th><th>Cost</th></tr></thead>
<tbody><tr><td>Item 1</td><td>$5</td></tr></tbody>
<tfoot><tr><td>Total</td><td>$5</td></tr></tfoot>
</table>Represents a header cell in a table.
Bold header cell with bottom border.
<table>
<tr><th>Name</th><th>Age</th><th>City</th></tr>
<tr><td>Alice</td><td>30</td><td>NYC</td></tr>
</table>Groups the header content rows of a table.
Container for table header rows.
<table>
<thead>
<tr><th>Product</th><th>Price</th></tr>
</thead>
<tbody>
<tr><td>Widget</td><td>$10</td></tr>
</tbody>
</table>Represents a specific period in time or a machine-readable datetime.
Machine-readable date/time with human display.
<p>Published on <time datetime="2024-01-15">January 15, 2024</time></p>Defines the document title shown in the browser tab.
Represents a row of cells in a table.
Horizontal row containing table cells.
<table>
<tr><th>Col 1</th><th>Col 2</th></tr>
<tr><td>A1</td><td>A2</td></tr>
<tr><td>B1</td><td>B2</td></tr>
</table>Specifies timed text tracks for media elements.
Represents text with an unarticulated annotation, such as misspelled words.
Wavy underline for annotated text like spelling errors.
<p>Check the <u>speling</u> of this word.</p>Represents an unordered list of items.
A bullet list with proper spacing and indentation.
<ul>
<li>First item</li>
<li>Second item</li>
<li>Third item</li>
</ul>Lists can be nested for hierarchical content.
<ul>
<li>Parent item
<ul>
<li>Child item</li>
<li>Another child</li>
</ul>
</li>
<li>Another parent</li>
</ul>Represents the name of a variable in a mathematical or programming context.
Italic monospace for variable names.
<p>Let <var>x</var> equal the number of items.</p>Embeds video content with playback controls.
Responsive video with native controls.
<video controls>
<source src="https://storage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4
" type="video/mp4">
Your browser does not support video.
</video>Represents an optional line break opportunity.
Suggests where a line break may occur.
<p>super<wbr>cali<wbr>fragilistic</p>The following components are built using semantic HTML:
A vertically stacked set of interactive headings that each reveal a section of content.
Selectors: details[name], details[name] > summary, details[name] > summary::-webkit-details-marker, details[name] > :not(summary), details[name] > :last-child
A simple accordion using native details/summary elements with exclusive behavior via the name attribute.
<div role="region" aria-label="FAQ">
<details name="accordion-basic">
<summary>What is an accordion?</summary>
<p>An accordion is a vertically stacked set of interactive headings that each reveal a section of content.</p>
</details>
<details name="accordion-basic">
<summary>When should I use an accordion?</summary>
<p>Use accordions when you have multiple sections of content that users may want to browse through without leaving the page.</p>
</details>
<details name="accordion-basic">
<summary>Are accordions accessible?</summary>
<p>Yes, when built with native details/summary elements, accordions are keyboard navigable and screen reader friendly.</p>
</details>
</div>An accordion where one panel starts expanded using the open attribute.
<nav aria-label="Product categories">
<details name="accordion-open" open>
<summary>Electronics</summary>
<ul>
<li>Phones</li>
<li>Laptops</li>
<li>Tablets</li>
</ul>
</details>
<details name="accordion-open">
<summary>Clothing</summary>
<ul>
<li>Shirts</li>
<li>Pants</li>
<li>Shoes</li>
</ul>
</details>
<details name="accordion-open">
<summary>Home & Garden</summary>
<ul>
<li>Furniture</li>
<li>Decor</li>
<li>Plants</li>
</ul>
</details>
</nav>Accordions can be nested to create hierarchical content structures.
<section aria-labelledby="docs-heading">
<h3 id="docs-heading">Documentation</h3>
<details name="accordion-nested">
<summary>Getting Started</summary>
<details>
<summary>Installation</summary>
<p>Run npm install to get started with the project.</p>
</details>
<details>
<summary>Configuration</summary>
<p>Edit the config file to customize your setup.</p>
</details>
</details>
<details name="accordion-nested">
<summary>API Reference</summary>
<details>
<summary>Components</summary>
<p>Learn about available component APIs.</p>
</details>
<details>
<summary>Utilities</summary>
<p>Explore utility functions and helpers.</p>
</details>
</details>
</section>A live region that displays important, time-sensitive information to the user.
Selectors: [role="alert"], [role="alert"][aria-live="assertive"], [role="alert"][aria-live="polite"], [role="alert"][data-tone="success"], [role="alert"][data-tone="warning"]
A simple alert for displaying messages to users.
<div role="alert">
<strong>Notice:</strong> Your session will expire in 5 minutes.
</div>Alerts with different semantic tones using data-tone attribute.
<div role="alert" data-tone="success">
<strong>Success!</strong> Your changes have been saved.
</div>
<div role="alert" data-tone="warning">
<strong>Warning:</strong> This action cannot be undone.
</div>
<div role="alert" data-tone="error">
<strong>Error:</strong> Failed to save changes.
</div>
<div role="alert" data-tone="info">
<strong>Info:</strong> New features are available.
</div>A navigation aid that shows the user's current location within a site hierarchy.
Selectors: nav[aria-label*="breadcrumb"], nav[aria-label*="Breadcrumb"], nav[aria-label*="breadcrumb"] ol, nav[aria-label*="Breadcrumb"] ol, nav[aria-label*="breadcrumb"] li, nav[aria-label*="Breadcrumb"] li, nav[aria-label*="breadcrumb"] li:not(:last-child)::after, nav[aria-label*="Breadcrumb"] li:not(:last-child)::after, nav[aria-label*="breadcrumb"] a[aria-current="page"], nav[aria-label*="Breadcrumb"] a[aria-current="page"]
A simple breadcrumb navigation showing the page hierarchy.
<nav aria-label="Breadcrumb">
<ol>
<li><a href="#">Home</a></li>
<li><a href="#">Products</a></li>
<li><a href="#">Electronics</a></li>
<li><a href="#" aria-current="page">Laptops</a></li>
</ol>
</nav>An interactive element that triggers an action when activated by the user.
Selectors: button, [role='button'], input[type='button'], input[type='submit'], input[type='reset'], button:hover, [role='button']:hover, input[type='button']:hover, input[type='submit']:hover, input[type='reset']:hover, button:active, [role='button']:active, input[type='button']:active, input[type='submit']:active, input[type='reset']:active, button:focus-visible, [role='button']:focus-visible, input[type='button']:focus-visible, input[type='submit']:focus-visible, input[type='reset']:focus-visible, button:disabled, [role='button'][aria-disabled='true'], input[type='button']:disabled, input[type='submit']:disabled, input[type='reset']:disabled
Different button styles using data-variant attribute.
<div style="display: flex; gap: 1em; flex-wrap: wrap;">
<button>Primary</button>
<button data-variant="secondary">Secondary</button>
<button data-variant="ghost">Ghost</button>
<button data-variant="danger">Danger</button>
<button disabled>Disabled</button>
</div>An anchor element styled as a button using role='button'.
<a href="#" role="button">Link Button</a>A rotating set of content items that can be navigated through sequentially.
Selectors: [aria-roledescription="carousel"], [aria-roledescription="carousel"] [aria-live], [aria-roledescription="carousel"] [aria-live]::-webkit-scrollbar, [aria-roledescription="slide"], [aria-roledescription="carousel"] [aria-label*="revious"], [aria-roledescription="carousel"] [aria-label*="ext"]
A simple image carousel with navigation buttons.
<section aria-roledescription="carousel" aria-label="Featured images">
<div aria-live="polite">
<article aria-roledescription="slide" aria-label="Slide 1 of 3">
<img src="https://picsum.photos/400/200?random=1" alt="Sample image 1" style="width: 100%;">
</article>
<article aria-roledescription="slide" aria-label="Slide 2 of 3">
<img src="https://picsum.photos/400/200?random=2" alt="Sample image 2" style="width: 100%;">
</article>
<article aria-roledescription="slide" aria-label="Slide 3 of 3">
<img src="https://picsum.photos/400/200?random=3" alt="Sample image 3" style="width: 100%;">
</article>
</div>
</section>A form control that allows users to select one or more options from a set.
Selectors: input[type="checkbox"], input[type="checkbox"]:checked, input[type="checkbox"]:checked::after, input[type="checkbox"]:focus-visible, input[type="checkbox"]:disabled
Checkboxes in various states.
<div style="display: flex; flex-direction: column; gap: 0.5em;">
<label><input type="checkbox"> Unchecked</label>
<label><input type="checkbox" checked> Checked</label>
<label><input type="checkbox" disabled> Disabled</label>
<label><input type="checkbox" checked disabled> Checked & Disabled</label>
</div>A composite widget combining a text input with a popup listbox for selecting values.
Selectors: [role="combobox"], [role="combobox"] input, [role="combobox"] [role="listbox"], [role="combobox"] [role="listbox"][hidden], [role="combobox"] [role="option"]
A text input with an associated listbox.
<div role="combobox" aria-expanded="true" aria-haspopup="listbox">
<input type="text" placeholder="Select a fruit..." aria-autocomplete="list">
<ul role="listbox">
<li role="option">Apple</li>
<li role="option" aria-selected="true">Banana</li>
<li role="option">Cherry</li>
<li role="option">Date</li>
</ul>
</div>A modal or non-modal window that appears above the page content requiring user interaction.
Selectors: dialog, dialog::backdrop, dialog[open], dialog header, dialog footer
A modal dialog with header and footer.
<dialog>
<header>
<h3>Confirm Action</h3>
</header>
<p>Are you sure you want to proceed with this action?</p>
<footer>
<button data-variant="secondary">Cancel</button>
<button>Confirm</button>
</footer>
</dialog>A button that controls the visibility of a section of content.
Selectors: details:not([name]), details:not([name]) > summary, details:not([name]) > summary::-webkit-details-marker, details:not([name]) > summary::after, details:not([name])[open] > summary::after
A collapsible section using the native details/summary elements.
<details>
<summary>Click to reveal more information</summary>
<p>This content is hidden by default and revealed when the summary is clicked.</p>
<p>You can include any content here.</p>
</details>A disclosure that starts in the open state.
<details open>
<summary>Already expanded</summary>
<p>This content is visible by default because the open attribute is present.</p>
</details>A scrollable list of articles where new content may be added as the user scrolls.
Selectors: [role="feed"], [role="feed"] article, [role="feed"] article:focus-within
A feed of articles with proper ARIA attributes.
<section role="feed" aria-label="News feed">
<article aria-posinset="1" aria-setsize="3" tabindex="0">
<h4>First Article</h4>
<p>Content of the first article...</p>
</article>
<article aria-posinset="2" aria-setsize="3" tabindex="0">
<h4>Second Article</h4>
<p>Content of the second article...</p>
</article>
<article aria-posinset="3" aria-setsize="3" tabindex="0">
<h4>Third Article</h4>
<p>Content of the third article...</p>
</article>
</section>An interactive two-dimensional data structure with rows and columns of cells.
Selectors: [role="grid"], [role="grid"] [role="row"], [role="grid"] [role="gridcell"], [role="grid"] [role="columnheader"], [role="grid"] [role="rowheader"], [role="grid"] [role="columnheader"], [role="grid"] [role="rowheader"], [role="grid"] [role="gridcell"]:focus, [role="grid"] [role="columnheader"]:focus, [role="grid"] [role="rowheader"]:focus
An interactive grid with keyboard navigation support.
<div role="grid" aria-label="Sample data" style="grid-template-columns: repeat(3, 1fr);">
<div role="row">
<div role="columnheader">Name</div>
<div role="columnheader">Email</div>
<div role="columnheader">Role</div>
</div>
<div role="row">
<div role="gridcell" tabindex="0">Alice</div>
<div role="gridcell">alice@example.com</div>
<div role="gridcell">Admin</div>
</div>
<div role="row">
<div role="gridcell" tabindex="-1">Bob</div>
<div role="gridcell">bob@example.com</div>
<div role="gridcell">User</div>
</div>
</div>A container for introductory content or navigational aids at the top of a page or section.
Selectors: header, header > :first-child, header > :last-child, article header, section header
A header element at the top of a page.
<header>
<h1>Page Title</h1>
<p>A brief description of the page content.</p>
</header>Semantic regions that help assistive technology users navigate and understand page structure.
Selectors: main, aside:not(article aside), footer
Semantic landmark elements for page structure.
<div style="border: 1px dashed var(--surface_muted); padding: 1em;">
<header style="padding: 0.5em; background: var(--surface_raised);">
<header> - Page header
</header>
<nav style="padding: 0.5em; background: var(--surface_overlay); margin-block: 0.5em;">
<nav> - Navigation
</nav>
<main style="padding: 0.5em; background: var(--surface_raised);">
<main> - Main content
<aside style="margin: 0.5em 0;">
<aside> - Sidebar
</aside>
</main>
<footer style="padding: 0.5em; background: var(--surface_overlay);">
<footer> - Page footer
</footer>
</div>An interactive reference to a resource that navigates the user when activated.
Selectors: a[aria-disabled="true"], a[download]::after, a[target="_blank"]::after
Different link states and types.
<div style="display: flex; flex-direction: column; gap: 0.5em;">
<a href="#">Standard Link</a>
<a href="#" aria-current="page">Current Page</a>
<a href="#" aria-disabled="true">Disabled Link</a>
<a href="#" target="_blank">External Link</a>
<a href="#" download>Download Link</a>
</div>A widget that allows users to select one or more items from a list of choices.
Selectors: [role="listbox"], [role="listbox"] [role="option"], [role="listbox"] [role="option"]:hover, [role="listbox"] [role="option"][aria-selected="true"], [role="listbox"] [role="option"]:focus
A listbox for selecting a single option.
<ul role="listbox" aria-label="Select a color">
<li role="option" aria-selected="false" tabindex="0">Red</li>
<li role="option" aria-selected="true" tabindex="-1">Green</li>
<li role="option" aria-selected="false" tabindex="-1">Blue</li>
<li role="option" aria-disabled="true" tabindex="-1">Yellow (unavailable)</li>
</ul>A widget that offers a list of actions or options that the user can invoke. Supports horizontal and vertical layouts, nested submenus, sticky positioning, and dividers—all with pure CSS and semantic HTML.
Selectors: nav[role="navigation"], nav[role="navigation"] ul, nav[role="navigation"] li, nav[role="navigation"] a, nav[role="navigation"] button, nav[role="navigation"] a[href^="#"]::before
A horizontal navigation menu with dropdown submenus. Uses aria-orientation='horizontal' (or omit for default horizontal behavior).
<nav role="navigation" aria-label="Main menu" aria-orientation="horizontal">
<ul>
<li><a href="#" aria-current="page">Home</a></li>
<li>
<a href="#">Products</a>
<ul>
<li><a href="#">Electronics</a></li>
<li><a href="#">Clothing</a></li>
<li role="separator"></li>
<li><a href="#">View All</a></li>
</ul>
</li>
<li>
<a href="#">Services</a>
<ul>
<li><a href="#">Consulting</a></li>
<li>
<a href="#">Development</a>
<ul>
<li><a href="#">Web</a></li>
<li><a href="#">Mobile</a></li>
<li><a href="#">Desktop</a></li>
</ul>
</li>
<li><a href="#">Support</a></li>
</ul>
</li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>A vertical sidebar-style menu with flyout submenus. Set aria-orientation='vertical' for vertical layout.
<nav role="navigation" aria-label="Sidebar menu" aria-orientation="vertical" style="width: 200px;">
<ul>
<li><a href="#" aria-current="page">Dashboard</a></li>
<li>
<a href="#">Settings</a>
<ul>
<li><a href="#">Profile</a></li>
<li><a href="#">Security</a></li>
<li><a href="#">Notifications</a></li>
</ul>
</li>
<li role="separator"></li>
<li><a href="#">Users</a></li>
<li>
<a href="#">Reports</a>
<ul>
<li><a href="#">Monthly</a></li>
<li><a href="#">Quarterly</a></li>
<li><a href="#">Annual</a></li>
</ul>
</li>
<li role="separator"></li>
<li><a href="#" aria-disabled="true">Archived</a></li>
<li><a href="#">Logout</a></li>
</ul>
</nav>A menu that sticks to the top of the viewport while scrolling. Use data-sticky for top, or data-sticky='bottom' for bottom.
<nav role="navigation" aria-label="Sticky navigation" aria-orientation="horizontal" data-sticky>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">Features</a></li>
<li><a href="#">Pricing</a></li>
<li><a href="#">Docs</a></li>
<li><a href="#">Blog</a></li>
</ul>
</nav>Menus can be nested multiple levels deep with flyout submenus.
<nav role="navigation" aria-label="Category menu" aria-orientation="horizontal">
<ul>
<li>
<a href="#">Categories</a>
<ul>
<li>
<a href="#">Electronics</a>
<ul>
<li>
<a href="#">Computers</a>
<ul>
<li><a href="#">Laptops</a></li>
<li><a href="#">Desktops</a></li>
<li><a href="#">Tablets</a></li>
</ul>
</li>
<li><a href="#">Phones</a></li>
<li><a href="#">Accessories</a></li>
</ul>
</li>
<li>
<a href="#">Clothing</a>
<ul>
<li><a href="#">Men</a></li>
<li><a href="#">Women</a></li>
<li><a href="#">Kids</a></li>
</ul>
</li>
<li><a href="#">Home & Garden</a></li>
</ul>
</li>
<li><a href="#">Deals</a></li>
<li><a href="#">New Arrivals</a></li>
</ul>
</nav>A graphical display of a numeric value within a known range.
Selectors: meter, meter::-webkit-meter-bar, meter::-webkit-meter-optimum-value, meter::-webkit-meter-suboptimum-value, meter::-webkit-meter-even-less-good-value
Meters showing different value ranges.
<div style="display: flex; flex-direction: column; gap: 1em;">
<label>Storage (optimal): <meter value="0.3" min="0" max="1" low="0.25" high="0.75" optimum="0.1"></meter></label>
<label>Memory (suboptimal): <meter value="0.7" min="0" max="1" low="0.25" high="0.75" optimum="0.1"></meter></label>
<label>CPU (critical): <meter value="0.95" min="0" max="1" low="0.25" high="0.75" optimum="0.1"></meter></label>
</div>A group of mutually exclusive options where only one can be selected at a time.
Selectors: input[type="radio"], input[type="radio"]:checked, input[type="radio"]:checked::after, input[type="radio"]:focus-visible, input[type="radio"]:disabled
A group of radio buttons for single selection.
<fieldset role="radiogroup" aria-label="Favorite color">
<legend>Choose a color:</legend>
<label><input type="radio" name="color" value="red"> Red</label>
<label><input type="radio" name="color" value="green" checked> Green</label>
<label><input type="radio" name="color" value="blue"> Blue</label>
<label><input type="radio" name="color" value="yellow" disabled> Yellow (unavailable)</label>
</fieldset>An input control that allows users to select a value from a range by dragging a thumb.
Selectors: input[type="range"], input[type="range"]::-webkit-slider-thumb, input[type="range"]::-moz-range-thumb, input[type="range"]::-webkit-slider-thumb:active, input[type="range"]:focus-visible
A slider for selecting a value within a range.
<div style="display: flex; flex-direction: column; gap: 1em;">
<label>Volume: <input type="range" min="0" max="100" value="50"></label>
<label>Brightness: <input type="range" min="0" max="100" value="75"></label>
<label>Disabled: <input type="range" min="0" max="100" value="25" disabled></label>
</div>A numeric input field with increment and decrement buttons for adjusting values.
Selectors: input[type="number"], input[type="number"]::-webkit-inner-spin-button, input[type="number"]::-webkit-outer-spin-button, input[type="number"]:focus, input[type="number"]:disabled, [role="spinbutton"]
A numeric input with spin buttons.
<div style="display: flex; flex-direction: column; gap: 1em;">
<label>Quantity: <input type="number" min="0" max="100" value="1"></label>
<label>Price: <input type="number" min="0" step="0.01" value="9.99"></label>
<label>Disabled: <input type="number" value="5" disabled></label>
</div>A toggle control that represents an on/off or enabled/disabled state.
Selectors: [role="switch"], [role="switch"]::before, [role="switch"][aria-checked="true"], [role="switch"][aria-checked="true"]::before, [role="switch"]:focus-visible
Toggle switches for on/off states.
<div style="display: flex; flex-direction: column; gap: 1em;">
<label style="display: flex; align-items: center; gap: 0.75em;">
<span role="switch" aria-checked="false" tabindex="0"></span>
Off
</label>
<label style="display: flex; align-items: center; gap: 0.75em;">
<span role="switch" aria-checked="true" tabindex="0"></span>
On
</label>
<label style="display: flex; align-items: center; gap: 0.75em;">
<span role="switch" aria-checked="false" aria-disabled="true" tabindex="-1"></span>
Disabled
</label>
</div>A structured grid of data organized in rows and columns for displaying information.
Selectors: table, th, td, th, thead th, tbody tr:hover
A data table with headers and rows.
<table>
<caption>User Data</caption>
<thead>
<tr>
<th>Name</th>
<th>Email</th>
<th>Role</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alice Johnson</td>
<td>alice@example.com</td>
<td>Admin</td>
</tr>
<tr>
<td>Bob Smith</td>
<td>bob@example.com</td>
<td>User</td>
</tr>
<tr>
<td>Carol White</td>
<td>carol@example.com</td>
<td>Moderator</td>
</tr>
</tbody>
</table>A set of layered content panels where only one panel is displayed at a time. Uses CSS-only functionality with radio inputs for state management.
Selectors: [role="tablist"], [role="tablist"][aria-orientation="vertical"], [role="tablist"] input[type="radio"], [role="tablist"] label, [role="tablist"][aria-orientation="vertical"] label
Standard horizontal tabs with radio inputs for CSS-only state management.
<div>
<ul role="tablist" aria-label="Settings tabs">
<li><input type="radio" name="tabs-demo" id="tab1" checked /><label for="tab1" id="tab1-label">General</label></li>
<li><input type="radio" name="tabs-demo" id="tab2" /><label for="tab2" id="tab2-label">Profile</label></li>
<li><input type="radio" name="tabs-demo" id="tab3" /><label for="tab3" id="tab3-label">Security</label></li>
</ul>
<div role="group" aria-label="Tab panels">
<div role="tabpanel" aria-labelledby="tab1-label">
<h4>General Settings</h4>
<p>Configure your general application settings here.</p>
</div>
<div role="tabpanel" aria-labelledby="tab2-label">
<h4>Profile Settings</h4>
<p>Update your profile information and preferences.</p>
</div>
<div role="tabpanel" aria-labelledby="tab3-label">
<h4>Security Settings</h4>
<p>Manage your password and security options.</p>
</div>
</div>
</div>Vertical tab orientation for sidebar-style navigation. Use aria-orientation='vertical'.
<div style="display: flex;">
<ul role="tablist" aria-label="Navigation tabs" aria-orientation="vertical">
<li><input type="radio" name="vtabs-demo" id="vtab1" checked /><label for="vtab1" id="vtab1-label">Dashboard</label></li>
<li><input type="radio" name="vtabs-demo" id="vtab2" /><label for="vtab2" id="vtab2-label">Analytics</label></li>
<li><input type="radio" name="vtabs-demo" id="vtab3" /><label for="vtab3" id="vtab3-label">Reports</label></li>
</ul>
<div role="group" aria-label="Tab panels">
<div role="tabpanel" aria-labelledby="vtab1-label">
<h4>Dashboard</h4>
<p>Welcome to your dashboard overview.</p>
</div>
<div role="tabpanel" aria-labelledby="vtab2-label">
<h4>Analytics</h4>
<p>View your analytics and metrics here.</p>
</div>
<div role="tabpanel" aria-labelledby="vtab3-label">
<h4>Reports</h4>
<p>Generate and download reports.</p>
</div>
</div>
</div>Tabs can be disabled using the disabled attribute on the radio input.
<div>
<ul role="tablist" aria-label="Feature tabs">
<li><input type="radio" name="dtabs-demo" id="dtab1" checked /><label for="dtab1" id="dtab1-label">Active</label></li>
<li><input type="radio" name="dtabs-demo" id="dtab2" disabled /><label for="dtab2" id="dtab2-label">Disabled</label></li>
<li><input type="radio" name="dtabs-demo" id="dtab3" /><label for="dtab3" id="dtab3-label">Available</label></li>
</ul>
<div role="group" aria-label="Tab panels">
<div role="tabpanel" aria-labelledby="dtab1-label">
<p>This tab is active and selectable.</p>
</div>
<div role="tabpanel" aria-labelledby="dtab2-label">
<p>This content is not accessible.</p>
</div>
<div role="tabpanel" aria-labelledby="dtab3-label">
<p>This tab is also available for selection.</p>
</div>
</div>
</div>A container for grouping related controls such as buttons and menu items.
Selectors: [role="toolbar"], [role="toolbar"][aria-orientation="vertical"], [role="toolbar"] [role="separator"], [role="toolbar"][aria-orientation="vertical"] [role="separator"], [role="toolbar"] [role="group"]
A horizontal toolbar with grouped controls.
<div role="toolbar" aria-label="Text formatting">
<div role="group" aria-label="Text style">
<button data-variant="ghost">B</button>
<button data-variant="ghost">I</button>
<button data-variant="ghost">U</button>
</div>
<span role="separator"></span>
<div role="group" aria-label="Alignment">
<button data-variant="ghost">Left</button>
<button data-variant="ghost">Center</button>
<button data-variant="ghost">Right</button>
</div>
<span role="separator"></span>
<button data-variant="ghost">Link</button>
</div>A vertical toolbar using aria-orientation.
<div role="toolbar" aria-label="Tools" aria-orientation="vertical">
<button data-variant="ghost">Select</button>
<button data-variant="ghost">Move</button>
<span role="separator"></span>
<button data-variant="ghost">Draw</button>
<button data-variant="ghost">Erase</button>
</div>A contextual popup that displays descriptive information about an element on hover or focus.
Selectors: [data-tooltip], [data-tooltip]::after, [data-tooltip]:hover::after, [data-tooltip]:focus::after, [data-tooltip][data-tooltip-position="bottom"]::after, [data-tooltip][data-tooltip-position="left"]::after
CSS-only tooltips using data-tooltip attribute.
<div style="display: flex; gap: 2em; padding: 2em;">
<button data-tooltip="Save your changes">Save</button>
<button data-tooltip="Delete this item" data-tooltip-position="bottom">Delete</button>
<button data-tooltip="Edit content" data-tooltip-position="right">Edit</button>
</div>Tooltip with proper ARIA role for accessibility.
<div style="position: relative; display: inline-block;">
<button aria-describedby="tooltip1">Hover for info</button>
<span role="tooltip" id="tooltip1" style="top: 100%; left: 50%; transform: translateX(-50%); margin-top: 0.5em;">
Additional information about this button
</span>
</div>A grid widget that combines the features of a tree and a data grid.
Selectors: [role="treegrid"], [role="treegrid"] [role="row"], [role="treegrid"] [role="gridcell"], [role="treegrid"] [role="columnheader"], [role="treegrid"] [role="columnheader"], [role="treegrid"] [role="row"][aria-level="2"] [role="gridcell"]:first-child
A hierarchical data grid with expandable rows.
<div role="treegrid" aria-label="File browser">
<div role="row">
<span role="columnheader">Name</span>
<span role="columnheader">Size</span>
<span role="columnheader">Modified</span>
</div>
<div role="row" aria-level="1" aria-expanded="true" tabindex="0">
<span role="gridcell">Documents</span>
<span role="gridcell">—</span>
<span role="gridcell">Today</span>
</div>
<div role="row" aria-level="2" tabindex="-1">
<span role="gridcell">Report.pdf</span>
<span role="gridcell">2.4 MB</span>
<span role="gridcell">Yesterday</span>
</div>
<div role="row" aria-level="2" tabindex="-1">
<span role="gridcell">Notes.txt</span>
<span role="gridcell">12 KB</span>
<span role="gridcell">Last week</span>
</div>
</div>A hierarchical list that can have nested groups of items that can be expanded or collapsed.
Selectors: [role="tree"], [role="tree"] [role="group"], [role="tree"] [role="treeitem"], [role="tree"] [role="treeitem"]:hover, [role="tree"] [role="treeitem"]:focus
A hierarchical tree with expandable nodes.
<ul role="tree" aria-label="File system">
<li role="treeitem" aria-expanded="true" tabindex="0">
Documents
<ul role="group">
<li role="treeitem" aria-expanded="false" tabindex="-1">
Work
<ul role="group">
<li role="treeitem" tabindex="-1">Report.docx</li>
<li role="treeitem" tabindex="-1">Presentation.pptx</li>
</ul>
</li>
<li role="treeitem" tabindex="-1">Personal</li>
</ul>
</li>
<li role="treeitem" aria-expanded="false" tabindex="-1">
Pictures
<ul role="group">
<li role="treeitem" tabindex="-1">Vacation</li>
<li role="treeitem" tabindex="-1">Family</li>
</ul>
</li>
<li role="treeitem" aria-selected="true" tabindex="-1">Downloads</li>
</ul>A movable divider that separates two sections and allows resizing them.
Selectors: [role="separator"][aria-orientation="vertical"], [role="separator"]:not([aria-orientation]), [role="separator"][aria-orientation="horizontal"], [role="separator"]:hover, [role="separator"]:focus, [role="separator"]:focus
A vertical divider between two horizontal panes.
<div style="display: flex; height: 150px; border: 1px solid var(--surface_muted); border-radius: 0.5em; overflow: hidden;">
<div style="flex: 1; padding: 1em; background: var(--surface_raised);">Left Pane</div>
<div role="separator" aria-orientation="vertical" aria-valuenow="50" tabindex="0"></div>
<div style="flex: 1; padding: 1em;">Right Pane</div>
</div>A horizontal divider between two vertical panes.
<div style="display: flex; flex-direction: column; height: 200px; border: 1px solid var(--surface_muted); border-radius: 0.5em; overflow: hidden;">
<div style="flex: 1; padding: 1em; background: var(--surface_raised);">Top Pane</div>
<div role="separator" aria-orientation="horizontal" aria-valuenow="50" tabindex="0"></div>
<div style="flex: 1; padding: 1em;">Bottom Pane</div>
</div>| Pattern | Purpose |
|---|---|
nav[role="navigation"] |
Navigation menu |
nav[aria-orientation="vertical"] |
Vertical navigation |
nav[data-sticky] |
Sticky navigation |
details[name] |
Accordion (grouped) |
[role="tablist"] |
Tab container |
[role="tabpanel"] |
Tab panel |
[role="group"] |
Tab panels container |
li[role="separator"] |
Menu divider |
a[aria-current="page"] |
Current page indicator |
| ✅ DO | ❌ DON'T |
|---|---|
| Use semantic HTML5 elements | Use div soup |
| Use ARIA roles for components | Use CSS classes |
| Use ARIA attributes for state | Forget accessibility |
| Use HTML5 native attributes | Use inline styles for layout |
| Use data attributes when needed | Mix with class-based frameworks |
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page Title</title>
<link rel="stylesheet" href="before.css">
</head>
<body>
<nav role="navigation" aria-label="Main" data-sticky>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
<main>
<section>
<h1>Page Heading</h1>
<p>Content goes here.</p>
</section>
</main>
<footer>
<p>© 2026 Company Name</p>
</footer>
</body>
</html>