Accessibility has a very cheap lever that is often forgotten: the right choice of HTML element. Semantic markup - where the tag is chosen by meaning rather than by appearance - at once improves keyboard support, populates the accessibility tree, eases parsing by search engines, and increases the robustness of the application. One move closes four fronts, and it costs exactly nothing.
The naive habit pulls the other way. Since everything is styled through CSS anyway, it seems easier to take a universal div and hang the look of a button on it: a class, padding, a cursor, a click handler. On screen the result is indistinguishable from a real button, and at first glance the job is done. But only the visual layer is done, while the semantic layer stays empty.
Here is what is lost if the add-to-cart button is assembled on a div. There is no role - the platform does not know it is a button. There is no keyboard activation - you cannot reach it with Tab or press Enter or Space. There is no disabled state - no way to report that the action is temporarily unavailable. There is no expected behavior that a user is used to getting from buttons. All of this has to be reproduced by hand in JavaScript and ARIA, and almost certainly not in full.
The right path is to take the native element. A real button already has a name, a role, focusability, Enter and Space handling, and a disabled state implemented by the browser - identically across all assistive technologies and for free. Hence the rule that saves weeks of work: native HTML first. ARIA and handlers finish off the missing parts, they do not rebuild from scratch what already exists.
To feel how much the browser gives away for free, it helps to gather a few native elements and what each brings to the accessibility tree and to behavior.
| Element | Role in the tree | What the browser gives for free |
|---|---|---|
| button | button | Focus, Enter/Space, the disabled state |
| a[href] | link | Focus, Enter, navigation by address, open in a new tab |
| h1..h6 | heading (with a level) | Hierarchy and fast navigation by headings |
|---|
| nav, main | landmark | Landmarks for jumping across page areas |
|---|
Headings are a topic of their own. A page should have one clear main heading, the h1, and the levels h2, h3, and beyond must reflect the structure of the content, not the font size. For the shoe card: h1 is the model name; h2 is sections such as description, specifications, and reviews. A screen reader builds a map of the page from these levels and lets the user jump around it, while a search engine reads the same hierarchy as a table of contents of the topic. Choosing h3 just because it is smaller means breaking both maps at once.
Links and buttons are not interchangeable decorations but elements different in meaning. A link moves the user to a resource: another page, a section, a file; it has an address, it can be opened in a new tab and copied. A button performs an action here and now: it adds to the cart, submits a form, expands a panel. Swapped for each other, they confuse both the keyboard user and the crawler: a link that is really a button promises a navigation that will not happen.
The large meaningful areas of a page are marked up with landmarks: header, nav, main, footer. They give assistive technology fast navigation across the page and a clear structure for parsing. The document skeleton stays strict: the navigation has a meaningful name, the main content lives in a single main, tables are used only for tabular relationships and not for layout, and interactive elements are not nested in one another (a link inside a button is a broken accessibility tree).
The failure here is invisible in a mockup and shows only in real use. A page made of nested divs renders perfectly, but a screen reader finds not a single landmark, not a single button, not one coherent heading hierarchy - to it this is a flat sheet of text with no map. Choosing the right elements returns all of that for free, which is why semantics comes first and styles and ARIA follow.
<div class="button" onclick="save()">
Save
</div><button type="button" disabled>
Save
</button><header>…</header>
<nav aria-label="Main navigation">…</nav>
<main id="main">
<article>
<h1>Page heading</h1>
…
</article>
</main>
<footer>…</footer>