What the DOM is
The DOM is the browser’s live object model of your HTML. JavaScript can read it, change text, update attributes, add classes, and create or remove elements.
Selecting elements
querySelector() returns the first matching element. querySelectorAll() returns a collection of matches. Data attributes such as data-menu-button make clear JavaScript hooks because they describe behaviour without tying the script to a visual class name.
Always make sure an element exists before using it if your script is shared across many pages. A guard clause such as if (!button || !menu) return; prevents a missing optional component from breaking unrelated page behaviour.
Changing state
A common professional pattern is to keep visual styling in CSS and use JavaScript to add, remove, or toggle state classes. Use the hidden property for simple show-and-hide behaviour and class changes when CSS needs to style a state such as is-open or is-selected.
Events
Events happen when users click, type, submit forms, scroll, or interact with controls. Event listeners connect those actions to functions.
Accessible interaction
Prefer native buttons for actions. When showing or hiding content, update ARIA attributes such as aria-expanded where appropriate. Keep the visible label accurate as well: if a button opens details, its label should change from “Show details” to “Hide details” when the panel opens.
Rendering user-entered content safely
When adding plain text supplied by a user, prefer textContent. It treats the value as text rather than as HTML markup. Use innerHTML only when you control and trust the markup being inserted. This distinction matters when you build comments, notes, task lists, or search results.
Example code
const button = document.querySelector("[data-menu-button]");
const menu = document.querySelector("[data-menu]");
button.addEventListener("click", () => {
const isOpen = menu.classList.toggle("is-open");
button.setAttribute("aria-expanded", String(isOpen));
});
Applied example: add a task safely
This example creates new elements and uses textContent so typed content is displayed as text.
const form = document.querySelector("[data-task-form]");
const input = document.querySelector("[data-task-input]");
const list = document.querySelector("[data-task-list]");
if (form && input && list) {
form.addEventListener("submit", (event) => {
event.preventDefault();
const title = input.value.trim();
if (!title) return;
const item = document.createElement("li");
item.textContent = title;
list.append(item);
form.reset();
});
}
Guided example: how to approach this lesson
Use these steps as a practical build process. The goal is not just to read the concept, but to know exactly how to apply it in your own page.
Step 1: Mark the HTML
Add useful IDs, classes, or data attributes to the elements JavaScript needs to control.
Step 2: Select the elements
Use querySelector or querySelectorAll and check that the elements exist.
Step 3: Listen for an event
Attach an event listener for click, input, submit, or another user action.
Step 4: Update the interface
Change text, classes, attributes, or hidden states so users receive feedback.
More examples
Compare these examples carefully. The improved version shows the kind of code pattern you should aim for when building your own project.
HTML for a toggle
<button data-details-button aria-expanded="false">
Show details
</button>
<div data-details hidden>
<p>This extra content can be shown or hidden.</p>
</div>
The button and panel have clear hooks for JavaScript and accessible state.
JavaScript for a toggle
const button = document.querySelector("[data-details-button]");
const details = document.querySelector("[data-details]");
button.addEventListener("click", () => {
const isHidden = details.hidden;
details.hidden = !isHidden;
button.setAttribute("aria-expanded", String(isHidden));
button.textContent = isHidden ? "Hide details" : "Show details";
});
This updates both the visual state and the accessibility state.
Before moving on
Use this checklist to make sure you understand the lesson well enough to apply it without copying blindly.
- Is the interactive element a real button?
- Does JavaScript update visible text or state?
- Are ARIA attributes updated when state changes?
- Can the interaction work with a keyboard?
Common mistakes to avoid
- Running DOM code before elements exist.
- Using clickable divs instead of buttons.
- Changing visual state without ARIA state.
- Using innerHTML for untrusted content.
Practice task
Build a three-question FAQ accordion for your responsive homepage.
Required outcome
- Use real buttons with
aria-expandedandaria-controls. - Use
hiddenpanels and update the expanded state whenever a panel opens or closes. - Change each button label so its current action remains clear.
- Confirm every accordion control works with Tab and Enter.
Stretch goal: Close the previously open answer when a different question opens.