Loading Developer Playground

Loading ...

Skip to main content
Share:
ARIA ATTRIBUTEโ€ขWidget Attributes

aria-level

Defines the hierarchical level of an element within a structure. Essential for headings when native HTML elements can't be used, and for tree structures to indicate nesting depth.

Value Type
integer (1+)
Common Use
Headings, Trees
Applies To
heading, treeitem

Overview

The aria-level attribute defines an element's hierarchical level within a structure. It's primarily used with role="heading" and role="treeitem".

The value must be an integer โ‰ฅ 1. For headings, levels 1-6 correspond to h1-h6. For tree items, the level indicates nesting depth (1 = root, 2 = child, etc.).

Prefer Native Elements

Always prefer native HTML elements like <h1>-<h6> when possible. Only use role="heading" with aria-level when native elements aren't feasible.

Live Demo: Tree Structure

  • โ–ผ๐Ÿ“Documents(level 1)
    • โ–ผ๐Ÿ“Projects(level 2)
      • ๐Ÿ“„report.pdf(level 3)
      • ๐Ÿ“„notes.txt(level 3)
  • โ–ถ๐Ÿ“Images(level 1)

Screen reader: "Documents, tree item, level 1, expanded". "Projects, tree item, level 2, expanded". "report.pdf, tree item, level 3".

Code Examples

Heading Levels

<!-- aria-level for heading hierarchy -->

<!-- Custom heading with explicit level -->
<div role="heading" aria-level="1">
  Main Page Title
</div>

<div role="heading" aria-level="2">
  Section Title
</div>

<div role="heading" aria-level="3">
  Subsection Title
</div>

<!-- Screen reader: "Main Page Title, heading level 1" -->

<!-- Semantic HTML is preferred when possible -->
<h1>Main Title</h1>      <!-- Level 1 implicit -->
<h2>Section Title</h2>   <!-- Level 2 implicit -->
<h3>Subsection</h3>      <!-- Level 3 implicit -->

<!-- Use aria-level only when you can't use native headings -->

Tree Structure

<!-- aria-level for tree structure -->
<ul role="tree" aria-label="File System">
  <!-- Level 1 items -->
  <li role="treeitem" aria-level="1" aria-expanded="true">
    ๐Ÿ“ Documents
    <ul role="group">
      <!-- Level 2 items -->
      <li role="treeitem" aria-level="2" aria-expanded="true">
        ๐Ÿ“ Projects
        <ul role="group">
          <!-- Level 3 items -->
          <li role="treeitem" aria-level="3">๐Ÿ“„ report.pdf</li>
          <li role="treeitem" aria-level="3">๐Ÿ“„ notes.txt</li>
        </ul>
      </li>
      <li role="treeitem" aria-level="2">๐Ÿ“„ todo.md</li>
    </ul>
  </li>
  <li role="treeitem" aria-level="1">
    ๐Ÿ“ Images
  </li>
</ul>

<!-- Screen reader announces depth: "Documents, tree item, level 1, expanded" -->

Nested Tabs

<!-- aria-level for nested tab structures -->
<div class="nested-tabs">
  <!-- Primary tabs (level 1) -->
  <div role="tablist" aria-label="Main sections">
    <button role="tab" aria-selected="true" aria-level="1">
      Account
    </button>
    <button role="tab" aria-selected="false" aria-level="1">
      Settings
    </button>
  </div>
  
  <!-- Secondary tabs within Account (level 2) -->
  <div role="tabpanel">
    <div role="tablist" aria-label="Account sections">
      <button role="tab" aria-selected="true" aria-level="2">
        Profile
      </button>
      <button role="tab" aria-selected="false" aria-level="2">
        Security
      </button>
    </div>
  </div>
</div>

React Components

// React Tree Component with aria-level
import { useState } from 'react';

function TreeItem({ item, level = 1 }) {
  const [expanded, setExpanded] = useState(false);
  const hasChildren = item.children && item.children.length > 0;
  
  return (
    <li
      role="treeitem"
      aria-level={level}
      aria-expanded={hasChildren ? expanded : undefined}
      aria-selected={item.selected}
    >
      <div 
        className="tree-item-content"
        onClick={() => hasChildren && setExpanded(!expanded)}
        style={{ paddingLeft: `${(level - 1) * 20}px` }}
      >
        {hasChildren && (
          <span className="expand-icon">
            {expanded ? 'โ–ผ' : 'โ–ถ'}
          </span>
        )}
        <span className="item-icon">{item.icon}</span>
        <span className="item-label">{item.label}</span>
      </div>
      
      {hasChildren && expanded && (
        <ul role="group">
          {item.children.map((child, index) => (
            <TreeItem 
              key={index} 
              item={child} 
              level={level + 1}
            />
          ))}
        </ul>
      )}
    </li>
  );
}

function FileTree({ data }) {
  return (
    <ul role="tree" aria-label="File browser">
      {data.map((item, index) => (
        <TreeItem key={index} item={item} level={1} />
      ))}
    </ul>
  );
}

// Custom Heading Component
function Heading({ level, children, ...props }) {
  // Prefer semantic elements when possible
  const Tag = level <= 6 ? `h${level}` : 'div';
  
  if (level <= 6) {
    return <Tag {...props}>{children}</Tag>;
  }
  
  // For levels > 6, use aria-level
  return (
    <div role="heading" aria-level={level} {...props}>
      {children}
    </div>
  );
}

// Usage
function DocumentOutline() {
  const files = [
    {
      label: 'Documents',
      icon: '๐Ÿ“',
      children: [
        { label: 'report.pdf', icon: '๐Ÿ“„' },
        { label: 'notes.txt', icon: '๐Ÿ“„' }
      ]
    },
    {
      label: 'Images',
      icon: '๐Ÿ“',
      children: [
        { label: 'photo.jpg', icon: '๐Ÿ–ผ๏ธ' }
      ]
    }
  ];
  
  return (
    <div>
      <Heading level={1}>File Browser</Heading>
      <FileTree data={files} />
    </div>
  );
}

Related Attributes

Specifications & Resources