How to Hide Instructions In Your HTML Without Breaking Accessibility
You've probably seen this problem before. You need to include setup instructions, onboarding hints, or explanatory text in your markup, but you don't want them visible on the page under normal circumstances. The typical solution is some kind of modal, tooltip, or collapsible section that requires a lot of boilerplate JavaScript. There's a cleaner way.
The Instructions Are Not Included Pattern
The idea is simple. You place all your instructional text directly in the HTML, hidden from view using CSS. When a user triggers a specific state — clicking a help button, hovering over an element, or focusing on a field — the instructions appear. The instructions themselves are not included in the visual layout by default. They're in the DOM, they're accessible to screen readers, but they take up no space and draw no attention until needed.
Here's the basic markup. It uses a `` tag, which is the cleanest container for content you don't want rendered:
?
Please fill out all required fields marked with an asterisk. If you encounter errors, make sure your email format is correct and that no fields are left blank.
The CSS keeps everything collapsed:
.instruction-block {
display: none;
position: absolute;
background: #f5f5f5;
border: 1px solid #ccc;
padding: 12px;
border-radius: 4px;
max-width: 300px;
z-index: 100;
}
.instruction-container:hover .instruction-block,
.instruction-container:focus-within .instruction-block,
.instruction-container[data-visible="true"] .instruction-block {
display: block;
}
When you toggle the `data-visible` attribute to true via a click handler or focus event, the instructions show. When you remove it, they disappear. The content itself is static HTML. No JS templating required.
Why This Approach Actually Works Better Than You'd Expect
Most developers skip the template approach and just put hidden divs everywhere. The problem with that is SEO and rendering overhead. Search engines and screen readers will still index content inside regular divs, even when it's visually hidden with `display: none`. With a `` element, the browser treats it as inert content by default. It doesn't render, it doesn't consume layout space, and most importantly, screen readers ignore it until the content is activated and moved into the visible DOM.
I ran into a real problem with this a few months ago on a government accessibility project. We had about forty form fields, each with detailed instructions that needed to be available to screen reader users but invisible to sighted users. The initial approach was to put all instructions in hidden divs with `aria-hidden="false"` toggled via JavaScript. The issue was that every single instruction block was loaded into the accessibility tree immediately, even though ninety percent of users never triggered them. Screen reader navigation became extremely slow on complex pages because the virtual cursor had to walk past dozens of hidden instruction elements before reaching anything interactive.
The fix was to use the `` approach, but with a small refinement. Instead of keeping the template in place and showing it, I cloned the template content into a dedicated region on the page when the help trigger was focused, and removed it entirely when focus moved away. The content physically left the DOM. Screen readers no longer encountered phantom instructions. Page performance improved noticeably because the accessibility tree stayed lean.
Here's the exact clone-and-attach pattern I used:
const trigger = document.querySelector('.help-trigger');
const instructionRegion = document.getElementById('instruction-region');
trigger.addEventListener('focus', () => {
const template = document.getElementById('instructions-for-field');
const clone = template.content.cloneNode(true);
instructionRegion.innerHTML = '';
instructionRegion.appendChild(clone);
});
trigger.addEventListener('blur', () => {
instructionRegion.innerHTML = '';
});
This is more code than the hover approach, but it's the only way to solve the accessibility tree bloat problem. The instruction-region element should have `role="region"` and `aria-label` set so screen reader users understand what they're navigating into.
Common Mistakes People Make With This Pattern
The biggest mistake I see is using `visibility: hidden` instead of `display: none`. Both hide content visually, but `visibility: hidden` keeps the element in the tab order and in the accessibility tree. That means screen readers will still announce it. If you want content truly excluded until activation, `display: none` or the template element is the right choice.
Another mistake is putting too much instruction text into a single block. I've seen instruction blocks that were three paragraphs long. Users don't read them. They open the help, scan for thirty seconds, and close it. Keep each instruction block to one or two sentences maximum. If you need more detail, link to a separate help page instead of nesting it inline.
You should also make sure the trigger element is keyboard accessible. Using `tabindex="0"` on a span works, but you need to handle the Enter key and Escape key manually. A better approach is to use a native `
Gallery Instructions Are Not Included
Instructions Not Included Full Movie
Instructions Not Included (2013) - Posters — The Movie Database (TMDB)
Instructions Not Included Movie Poster
Instructions Not Included Poster Instructions Not Included – Emma
Instructions Not Included Poster Instructions Not Included – Emma