LessonLesson 3 of 34

Elements, attributes, and the document tree

Understand nesting, content models, boolean attributes, and the difference between source HTML and the parsed DOM.

Beginner4 min readLearn · Practice · Review

Published by HTML Code Runner · AI-assisted material · Independent editorial review pending · Editorial policy

On this page

Learning objectives

Identify an element’s content and attributes; predict browser repair of invalid nesting; distinguish boolean attributes from string values.

Prerequisites

Read HTML introduction and document structure. Open your browser’s developer tools alongside a saved HTML file.

Read structure, not punctuation

A start tag names an element and may carry attributes. The content between start and end tags belongs to that element. In a paragraph containing an emphasized word, the emphasis element is a child of the paragraph; the text before and after it is also part of the paragraph. This parent-child relationship becomes the document tree that scripts, styles, and assistive technologies use.

Attributes describe properties of an element. Put them inside its start tag, separate them with spaces, and quote values consistently. An attribute belongs to the element on which it appears: placing href on a paragraph does not turn it into a hyperlink. Global attributes such as id, class, and lang are broadly available, while others apply to particular elements or states.

Learn the rules the parser actually follows

A void element cannot contain children in HTML. Examples include img, input, br, and meta. A trailing slash in <br /> does not create an XML-style self-closing mechanism for ordinary HTML elements. Writing <div /> therefore does not close a div; use an explicit end tag.

Every element has a content model describing what may appear inside it. A paragraph accepts phrasing content, so placing a div inside a p causes the parser to close the paragraph before the div. The Elements panel can consequently show a different tree from the source you typed. Browser recovery makes the web resilient, but it does not make invalid markup a reliable design technique.

Boolean attributes are enabled by presence. Disabled, checked, and required do not use the strings true and false as switches. Omit the attribute to turn it off. Other attributes, including aria-expanded, are token-valued and do require an explicit value. Learn each attribute’s definition rather than applying one rule to every name.

Inspect one node at a time

When debugging, select the visible content in developer tools and inspect its ancestors. Confirm that the element belongs to the intended section and that the attribute is on the correct node. View source answers what was delivered; the DOM inspector answers what the browser constructed. If a script changes the page after load, the latter can also reflect changes that never existed in the original response.

Working example

<p>A <strong>carefully labeled</strong> form is easier to use.</p>
<button type="button" disabled>Unavailable today</button>

Another example

<label for="name">Display name</label>
<input id="name" name="display_name" required>
<p lang="fr">Bonjour tout le monde.</p>

Expected output

The strong text receives default emphasis, and the disabled button cannot be activated. The second example exposes a required text field with a visible label; lang identifies the French passage without translating it.

Common mistakes

Do not duplicate an attribute on one tag, close a void element with </input>, or expect disabled="false" to enable a control. Do not diagnose nesting solely from what the page looks like: repaired markup can appear correct while changing relationships.

Accessibility and browser notes

Prefer elements with native semantics. An attribute such as title is supplementary and should not be the only way to expose necessary instructions. Native disabled controls are normally removed from sequential keyboard focus, so explain unavailable actions in surrounding visible text.

Practice

Repair this intended interaction: a required name field and an enabled Save button. Use a unique ID and an explicit button type.

Review the solution and reasoning
<label for="profile-name">Name</label>
<input id="profile-name" name="name" required>
<button type="submit">Save</button>

Required is present on the field. Disabled is absent from the button, so it remains enabled. The label points to the field’s ID, while name supplies the submitted key when the controls belong to a form.

Related lessons

Specifications and further reading

One more skill in your toolkit.

Finished the explanation and exercise? Save your progress.