Frontend · Concept
The DOM, Events, and User Interaction
Understand the live document tree and how browser events move from a user action to the right handler.
On this page
The short answer
The browser exposes a live document as a tree of objects called the DOM. Scripts can read and change that tree. When someone clicks, types, or uses a control, the browser dispatches an event to an appropriate target. Listeners can respond, and many events also travel through ancestors of that target.
The previous lesson explained how document structure contributes to pixels. Here the focus is the document as a programmable interface and the route an interaction takes through it.
Mental model
Treat the DOM as the current document structure, not the original file. Treat an event as a dispatched signal with a target and a path, not as a script continuously asking whether a button was clicked. First identify the target, then which listeners can receive the event, then whether the browser has a default action.
- CaptureAncestors with capturing listeners can observe the event on its way down
- TargetThe clicked button is the event target
- BubbleEligible ancestor listeners can observe the event on its way up
- Default actionThe browser may perform a cancelable built-in behavior
HTML source versus live DOM
HTML is markup sent to or embedded in the page. The DOM is an object representation created from that markup by parsing rules and then exposed through browser APIs. Parsing can correct or infer structure; scripts can later change it. Looking at “View Source” and inspecting the live Elements panel can therefore show different things.MDN distinguishes document source from the DOM representation.2
The DOM can also include nodes a framework added after the first response. That does not mean the framework owns a separate browser DOM. It means application code caused the browser's live tree to change.
Nodes and elements
A node is a member of the document tree. An element, such as a button, is one kind of node; text inside it is usually represented by text nodes. A document node sits above the element tree. Attributes such as id or data-id belong to elements.
The distinction matters when APIs return a node that is not necessarily an element. A text node does not have the same querying or styling methods as an element. The DOM Standard defines these interfaces and relationships.The standard is the primary reference for the DOM and events.1
Finding elements
JavaScript can ask the document for an element using methods such as querySelector. A selector expresses which node you want; the returned element reference can be used to read text, attributes, or children and to attach a listener. A query can return null if nothing matches, so production code should account for that possibility.
Selecting #save does not freeze a copy of the HTML. It returns a reference to a live object in the current document. A later query can find a different set after the document changes.
Reading and changing the DOM
An application can set text, add a node, remove a node, or change a class. The browser may then recalculate style or rendering work if the change affects what is displayed. This is a browser operation, not the same as rewriting the response file on the server.
Prefer a text-setting API such as textContent for plain user-provided text. Inserting untrusted strings as HTML has security implications; the later browser-security lesson will explain that boundary. A framework may perform DOM updates on your behalf, but it still ultimately changes browser-managed document state.
Attributes, properties, and state
An HTML attribute is part of markup; a DOM property is an API value on an object. Some properties reflect attributes, so changing either updates the other. Others do not map one-to-one. For example, an input's current value can diverge from the initial value written in its markup. Avoid assuming that reading an attribute always tells you the control's current state.MDN explains reflected attributes and their limits.5
Application state is another layer: a framework or your own code may store a selected item separately from the DOM. Keeping those layers in agreement is an application responsibility, not a property of HTML syntax.
What browser events are
Events represent occurrences such as a click, a key press, a form submission, or a resource load. The browser dispatches an event object when the occurrence happens. A listener registered for the relevant event type can run in response. This is not continuous polling by your JavaScript function.
Events differ: some bubble, some can be canceled, and some follow additional rules. Never infer every event's behavior solely from a click example.
Event targets and listeners
event.target identifies the original target of an event within the relevant event-dispatch context. event.currentTarget is the object whose listener is currently running. In a parent list's click handler, the target might be a child button while the current target is the list. That distinction makes delegation possible.MDN demonstrates target and current target in event bubbling.3
Listeners can be added with addEventListener. Registering a listener tells the browser what to call later; the handler does not run at registration time. Duplicate registration patterns can cause more than one handler to respond to a single interaction.
Capturing, target, and bubbling
For a bubbling event, dispatch has a capture path through ancestors, a target phase, and a bubble path back through eligible ancestors. A listener registered with { capture: true } observes the capture side; ordinary listeners typically observe the target or bubble side.
This is a simplified view of DOM dispatch. Shadow DOM boundaries and event-specific flags add detail, and not every event bubbles. The durable diagnostic question is: which listener is running, and where did the event begin?
Event delegation
Suppose a list contains buttons and later gains more buttons. One click listener on the list can handle current and future buttons because eligible clicks bubble through the list. The handler checks whether the actual target is inside a button it cares about.
<ul id="notes">
<li><button type="button" data-id="a">Open note A</button></li>
</ul>
const list = document.querySelector("#notes");
list?.addEventListener("click", (event) => {
const button = event.target instanceof Element
? event.target.closest("button[data-id]")
: null;
if (!button || !list.contains(button)) return;
console.log(button.getAttribute("data-id"));
});The JavaScript fragment is illustrative and belongs in a script, not literally after the HTML in one source file. If application code later adds another button inside the list, the existing list listener can handle its click. closest accounts for a click on an element inside a button, while contains keeps the match inside this list. In an application, replace the log with a clearly defined action.
Default browser actions
A link normally navigates; a submit button can submit a form. These are built-in behaviors, separate from your listeners. Using real links and buttons gives users keyboard and assistive-technology behavior that a clickable div does not automatically provide. Framework event handlers do not make semantics optional.React's event guidance also recommends native buttons for button actions.6
Not every event has a cancelable default action, and a default action is not the same as event propagation.
preventDefault() and stopPropagation()
preventDefault() asks the browser not to perform a cancelable default action, such as navigating from a link. It does not stop listeners on ancestors from receiving the event. stopPropagation() prevents further travel through the propagation path; it does not, by itself, cancel the default action.The DOM Standard defines separate cancellation and propagation flags.1MDN documents the practical preventDefault() behavior.4
Use either only when the interaction actually calls for it. Blocking propagation to hide a confusing nested-control design can make other listeners and accessibility behavior harder to reason about.
DOM events in frontend frameworks
React, Vue, and other frameworks offer declarative ways to attach handlers and update interfaces. They still run in a browser with event targets, default actions, and document semantics. Frameworks may wrap or organize event handling differently, so their APIs are not a literal description of DOM dispatch.
A React component tree is a tree of application components, not the same thing as the browser's DOM tree. A component may produce several DOM nodes or none. When debugging, inspect both the framework-level handler and the actual rendered control.
Common misconceptions
A listener checks for clicks continuously
Registering a listener allows the browser to call it when a matching event is dispatched. It is not a polling loop written by your code.
Preventing default also stops bubbling
Canceling a built-in action and stopping propagation are separate operations. A parent listener can still run after preventDefault().
Debugging scenario
Debugging scenario
A card-like container has a click handler that opens a detail view. Inside it, a real button opens an options menu. Clicking the button opens both the menu and the detail view.
The button's click can bubble to the container. First inspect the rendered structure and both handlers. Should the container itself be an interactive control, or should it contain a separate link for the detail action? Could the handler respond only when the container's intended target is clicked? stopPropagation() may be appropriate in a specific design, but it is not automatically the best fix. Avoid nesting a button inside another button or a link inside another interactive control.
Why this matters when working with AI-generated code
Generated UI code can attach a handler to every new child, add a second listener during each update, or use a clickable div where a button belongs. Review what the browser actually renders, where listeners are attached, and whether propagation or default actions explain the observed behavior. Do not accept a blanket stopPropagation() patch without checking the interaction design.
Knowledge check
Reflect, then reveal each answer.
Can the live DOM differ from View Source?
Yes. Parsing rules can construct a tree that differs from literal source text, and scripts can change the DOM after parsing.
What is the difference between event.target and event.currentTarget?
The target identifies where the event began in the relevant dispatch context; currentTarget is the object whose listener is running now.
Why can a parent list handle a button added later?
A bubbling click from the new button can reach the listener already attached to the parent list. The listener checks the target to choose an action.
Does preventDefault() stop a parent click listener?
No. It cancels a cancelable browser default action; propagation continues unless separately stopped.
Should a double-action card always be fixed with stopPropagation()?
No. Inspect semantics, handler placement, and intended behavior first. Stopping propagation is one possible tool, not a substitute for sound interaction structure.
What to learn next
How this connects
- JavaScript runtime and async code
Events schedule handlers; the next lesson explains when that code can run and why it can block the interface.
- Components and state
Later, connect framework-managed state and component updates to the underlying DOM. This lesson is planned.
- Semantic HTML and accessibility
Later, examine how native controls and document structure support keyboard and assistive-technology use. This lesson is planned.
Key takeaway
References & further reading
References & further reading6 sourcesPrimary standards and official documentation used for this lesson.
- DOM Standard (opens in a new tab)
WHATWG
DOM nodes, event targets, listeners, propagation, cancellation, and dispatch
- Document Object Model (DOM) (opens in a new tab)
MDN Web Docs
Live document structure, node types, and DOM APIs
- Event: preventDefault() method (opens in a new tab)
MDN Web Docs
Canceling a default action without stopping propagation
- Attribute reflection (opens in a new tab)
MDN Web Docs
Relationships and differences between attributes and DOM properties
- Responding to Events (opens in a new tab)
React
Framework event handlers, propagation, and semantic controls