Aria

aria-expanded

screen reader users

<button id="menuBtn" aria-expanded="false">Menu</button>
 
<script>
  const btn = document.getElementById("menuBtn");
 
  btn.addEventListener("click", () => {
    const expanded = btn.getAttribute("aria-expanded") === "true";
    btn.setAttribute("aria-expanded", String(!expanded));
  });
</script>

aria-haspopup

<button
  id="menubutton"
  aria-haspopup="menu"
  aria-controls="filemenu"
  aria-expanded="false"
>
  File
</button>
 
<ul
  id="filemenu"
  role="menu"
  aria-labelledby="menubutton"
  hidden
>
  <li role="menuitem" tabindex="-1">Open</li>
  <li role="menuitem" tabindex="-1">New</li>
  <li role="menuitem" tabindex="-1">Save</li>
  <li role="menuitem" tabindex="-1">Delete</li>
</ul>
 
<script>
  const button = document.getElementById("menubutton");
  const menu = document.getElementById("filemenu");
 
  button.addEventListener("click", () => {
    const expanded = button.getAttribute("aria-expanded") === "true";
 
    button.setAttribute("aria-expanded", String(!expanded));
    menu.hidden = expanded;
  });
</script>

aria-checked

<div
  id="checkbox"
  role="checkbox"
  aria-checked="true"
  tabindex="0"
  style="
    display: inline-flex;
    align-items: center;
    gap: 6px;
    cursor: pointer;
  "
>
  <span
    id="box"
    aria-hidden="true"
    style="
      width: 16px;
      height: 16px;
      border: 2px solid blue;
      background: blue;
      display: inline-block;
    "
  ></span>
  Checkbox
</div>
 
<script>
  const checkbox = document.getElementById("checkbox");
  const box = document.getElementById("box");
 
  const toggle = () => {
    const checked = checkbox.getAttribute("aria-checked") === "true";
    checkbox.setAttribute("aria-checked", String(!checked));
    box.style.background = checked ? "white" : "black";
  };
 
  checkbox.addEventListener("click", toggle);
 
  checkbox.addEventListener("keydown", (e) => {
    if (e.key === " " || e.key === "Enter") {
      e.preventDefault();
      toggle();
    }
  });
</script>

aria-disabled

<div
  id="editBtn"
  role="button"
  tabindex="-1"
  aria-disabled="true"
  style="opacity: 0.5; cursor: not-allowed;"
>
  Edit
</div>
 
<button id="toggle">Toggle Disabled</button>
 
<script>
  const editBtn = document.getElementById("editBtn");
  const toggleBtn = document.getElementById("toggle");
 
  toggleBtn.addEventListener("click", () => {
    const disabled = editBtn.getAttribute("aria-disabled") === "true";
 
    editBtn.setAttribute("aria-disabled", String(!disabled));
    editBtn.tabIndex = disabled ? 0 : -1;
    editBtn.style.opacity = disabled ? "1" : "0.5";
    editBtn.style.cursor = disabled ? "pointer" : "not-allowed";
  });
</script>

aria-selected

<div role="tablist">
  <button role="tab" aria-selected="true">Tab 1</button>
  <button role="tab" aria-selected="false">Tab 2</button>
  <button role="tab" aria-selected="false">Tab 3</button>
</div>
 
<script>
  const tabs = document.querySelectorAll('[role="tab"]');
 
  tabs.forEach((tab) => {
    tab.addEventListener("click", () => {
      tabs.forEach(t => t.setAttribute("aria-selected", "false"));
      tab.setAttribute("aria-selected", "true");
    });
  });
</script>

aria-controls

<div role="tablist">
  <button 
    role="tab"
    id="tab1"
    aria-controls="section1"
    aria-selected="true"
  >
    Tab 1
  </button>
  <button
    role="tab"
    id="tab2"
    aria-controls="section2"
    aria-selected="false"
  >
    Tab 2
  </button>
  <button
    role="tab"
    id="tab3"
    aria-controls="section3"
    aria-selected="false"
  >
    Tab 3
  </button>
</div>

Aria live

<div aria-live="polite" id="status"></div>
 
<button id="updateStatus">Update Status</button>
 
<script>
  const statusEl = document.getElementById("status");
  const btn = document.getElementById("updateStatus");
 
  btn.addEventListener("click", () => {
    statusEl.textContent = "Your file has been successfully uploaded.";
  });
</script>

contenteditable

<div
  contenteditable="true"
  aria-label="Note editor"
  id="editor"
  style="border: 1px solid #ccc; padding: 8px;"
>
  Editable content goes here
</div>
 
<p id="status" aria-live="polite"></p>
 
<script>
  const editor = document.getElementById("editor");
  const status = document.getElementById("status");
 
  editor.addEventListener("input", () => {
    status.textContent = "Content updated";
  });
</script>

Focus blur events

Blur

<input
  id="nameInput"
  type="text"
  placeholder="Type here and click outside"
  aria-label="Name input"
/>
 
<p id="status" aria-live="polite"></p>
 
<script>
  const input = document.getElementById("nameInput");
  const status = document.getElementById("status");
 
  input.addEventListener("blur", () => {
    status.textContent = "Input lost focus";
  });
</script>

Focus

<input
  id="emailInput"
  type="email"
  placeholder="Click or tab into this field"
  aria-label="Email input"
/>
 
<p id="status" aria-live="polite"></p>
 
<script>
  const input = document.getElementById("emailInput");
  const status = document.getElementById("status");
 
  input.addEventListener("focus", () => {
    status.textContent = "Input received focus";
  });
</script>