Accessibility in JavaScript: How to Make a Website Convenient for Everyone
\n\nImagine you visit a website, and the "Buy" button cannot be clicked with a mouse — only with the keyboard. Or you can't see the screen, and the screen reader simply skips half the content. Unpleasant, right? Yet for millions of people, this is an everyday reality.
\n\nAccessibility (or a11y) is not just a trendy term. It's a way to make your code honest. Accessibility in JavaScript is about making your website work for everyone: for people with visual impairments, motor disabilities, for those who only use a keyboard or voice control. And yes, it's also about SEO: search engines love clean, semantically correct code.
\n\nIn this article, we'll break down real JavaScript examples that you can implement today. No fluff — only code and practice.
\n\nWhy is accessibility your responsibility?
\n\nIf you write in JavaScript, you control the interface behavior. It's JS that most often breaks accessibility: dynamic modals, infinite scrolls, custom selects. Screen readers (programs that read the screen) can't read your mind — they read what you tell them through HTML and ARIA.
\n\nThe good news: most problems can be fixed in an evening. The bad news: if you don't think about accessibility from the start, you'll have to rewrite things for weeks.
\n\nARIA Attributes: Your Main Tool
\n\nARIA (Accessible Rich Internet Applications) is a set of attributes that help assistive technologies understand what is happening on the page. JavaScript is perfect for dynamically updating these attributes.
\n\nExample 1: Dynamically Updating aria-live
\n\nLet's say you have a chat where messages are loaded without a page refresh. The screen reader must announce the new message. Without aria-live, the user simply won't know about the update.
// Create a container for notifications\nconst liveRegion = document.createElement('div');\nliveRegion.setAttribute('aria-live', 'polite');\nliveRegion.setAttribute('aria-atomic', 'true');\nliveRegion.classList.add('sr-only'); // hide visually\ndocument.body.appendChild(liveRegion);\n\n// Function to add a message\nfunction addChatMessage(message) {\n liveRegion.textContent = ''; // clear\n liveRegion.textContent = `New message: ${message}`;\n}\n\n// Example call\naddChatMessage('Hello! How are you?');\n\nImportant: aria-live="polite" tells the screen reader: "Announce when you finish reading the current content." aria-live="assertive" interrupts reading — use it for critical errors.
Example 2: Custom Spoiler/Accordion
\n\nStandard <details> and <summary> are already accessible, but if you are making a custom accordion in JS, you need to add ARIA roles and states.
// For each accordion section\nconst accordionButton = document.querySelector('.accordion-button');\nconst accordionPanel = document.querySelector('.accordion-panel');\n\naccordionButton.setAttribute('aria-expanded', 'false');\naccordionButton.setAttribute('aria-controls', 'panel-1');\naccordionPanel.setAttribute('id', 'panel-1');\naccordionPanel.setAttribute('aria-hidden', 'true');\n\naccordionButton.addEventListener('click', () => {\n const isOpen = accordionButton.getAttribute('aria-expanded') === 'true';\n accordionButton.setAttribute('aria-expanded', !isOpen);\n accordionPanel.setAttribute('aria-hidden', isOpen);\n});\n\nNow the screen reader understands that the button controls the panel and knows whether it is open or closed.
\n\nFocus Management: Don't Let the User Get Lost
\n\nOne of the most common mistakes in JavaScript accessibility is losing focus. When a modal window opens, focus should move inside it. When it closes, focus should return to the button that triggered it.
\n\n