Contenteditable and a handful of other interactive HTML attributes show up in the wild more often than you might expect. You already know forms, links, and buttons from the intro series. These are different: they change how the page behaves when someone clicks or types, and most of the time you should leave them alone.
The goal is to recognise them, know roughly what they do, and – more importantly – know when to leave them alone.
contenteditable
Add contenteditable="true" to almost any element and the user can edit its text in the browser. No <textarea> required.
<div contenteditable="true">
Click here and type. The browser treats this like a tiny document.
</div>
That is the whole attribute. Browsers may also allow bold, lists, and pasted HTML depending on how the user interacts with it. What you get back is often messy inner HTML, not plain text.
When it is useful: quick prototypes, internal admin tools, or the HTML layer beneath a proper rich-text editor (TinyMCE, TipTap, and similar all build on ideas like this).
When to avoid it:
- Replacing a normal form field. Use
<input>,<textarea>, or<select>unless you have a very good reason not to. - Expecting consistent behaviour across browsers without JavaScript to normalise the output.
- Public-facing editing where you cannot control what gets pasted (HTML, scripts in some older setups, enormous Word markup).
- Assuming it is accessible out of the box. Screen reader support exists but is patchy; you usually need ARIA roles, labels, and keyboard handling if this is a real feature.
If you do use it, decide early whether you are storing plain text or HTML, and sanitise on the server. Treat pasted content as untrusted.
spellcheck
spellcheck="true" or spellcheck="false" hints whether the browser should underline misspellings. It works on editable fields and on contenteditable regions.
<textarea spellcheck="true"></textarea>
<code spellcheck="false">npm install --save-dev</code>
Turn it off for code snippets, usernames, or anything where a red squiggle is noise. Harmless attribute; just do not rely on it as validation.
hidden
The boolean hidden attribute removes an element from the rendered page and from the accessibility tree in supporting browsers. Prefer it over style="display:none" when the content is genuinely not relevant yet.
<p hidden>This paragraph is not shown.</p>
<div id="error-panel" hidden>
<p>Please fix the fields marked below.</p>
</div>
JavaScript can toggle hidden when you need to reveal something. Do not use hidden on focusable elements you still want keyboard users to reach – that is a common mistake. If it should be reachable, it should not be hidden.
inert
inert tells the browser to ignore an element and everything inside it: no clicks, no tab focus, no screen reader interaction. Modal dialogs use this idea – background page goes inert while the dialog is open.
<main inert>
<!-- Background content while a modal is open -->
</main>
Browser support is good in current versions. You will usually toggle it with JavaScript rather than leaving it in static HTML. Pair it with a proper dialog pattern (<dialog> or an ARIA modal) rather than using inert on its own as a fix for messy focus management.
autofocus
autofocus moves keyboard focus to an element when the page loads. Handy on a single-field search box; annoying on a busy homepage where it steals focus from people using the keyboard to scroll.
<input type="search" name="q" autofocus>
Only one element per page should use it. Avoid on mobile landing pages where it can pop the virtual keyboard open unexpectedly. If you need autofocus after a client-side route change, set focus in JavaScript instead.
tabindex on non-interactive elements
tabindex="0" adds an element to the tab order. tabindex="-1" allows programmatic focus but skips it in normal tabbing. Positive values (tabindex="1") reorder focus manually and are almost always a bad idea.
Putting tabindex="0" on a <div> because you want it clickable is a smell. Ask whether it should be a <button> or <a href> instead. If you add tabindex to custom widgets, you owe keyboard users Enter/Space behaviour and a visible focus style.
popover (briefly)
HTML now has a popover attribute for lightweight overlays (tooltips, menus) with built-in top-layer behaviour in supporting browsers. You will still see plenty of JavaScript-driven popovers in the wild.
<button popovertarget="help-tip">Help</button>
<div id="help-tip" popover>Short explanation here.</div>
Worth knowing it exists. For production UI, check browser support and whether your project already has an accessible dialog component before reaching for the newest attribute.
Practical rule of thumb
Native interactive elements – links, buttons, form fields – already have browser behaviour, keyboard support, and accessibility mappings. Attributes like contenteditable and positive tabindex opt out of that contract. Use them when you are deliberately building a custom control and willing to finish the job in HTML, CSS, and JavaScript. Otherwise stick to the boring tags. Boring tags work.

