MX Learn ยท Lesson 3 of 6
Explicit over implicit
The hands-on lesson: real before/after markup for every state a machine needs declared. Reading time about six minutes; the full lesson text is on this page even with scripting off.
Humans excel at inference. Machines do not.
A greyed-out button signals "unavailable" to a human. An AI agent sees a fully clickable button unless you explicitly mark it disabled.
A red asterisk next to a form field means "required" to a human. An agent sees decoration unless you add the required attribute.
The MX principle: if something matters, declare it explicitly in markup. Every pattern in this lesson answers one question: if you removed all CSS from the page, could a machine still understand what each element does?
State must be declared
Visual styling encodes state for eyes only. Open each pattern to compare the visual-only markup with its explicit replacement:
Visual only
<button class="btn-disabled" style="opacity: 0.5">Submit</button>
Explicit
<button disabled aria-disabled="true">Submit</button>
The opacity and the class name are invisible to an agent that never renders CSS. The disabled attribute is a declaration every parser reads.
Visual only
<div class="spinner"></div>
Explicit
<div role="status" aria-busy="true" aria-live="polite"> <span aria-hidden="true" class="spinner"></span> <span class="sr-only">Loading, please wait</span> </div>
An empty div with a class name means nothing. role="status" and aria-busy="true" tell every machine the content is on its way.
Open both patterns to continue.
Required fields and the current page
The same rule holds for forms and navigation. Open both patterns:
Visual only
<label>Email <span class="red">*</span></label> <input type="email" name="email">
Explicit
<label for="email">Email <abbr title="required">*</abbr></label> <input type="email" id="email" required aria-required="true">
The red asterisk is decoration to a machine. The required attribute, backed by aria-required and a proper for/id label association, is a contract.
Ambiguous
<a href="/" class="active">Home</a>
Explicit
<a href="/" aria-current="page">Home</a>
A class named "active" is a private convention your CSS understands. aria-current="page" is a standard every agent and screen reader understands.
Open both patterns to continue.
Error states
Validation feedback is the state that costs users most when a machine misses it. Open the pattern:
Visual only
<input type="email" class="error"> <span class="error-text">Invalid email</span>
Explicit
<input type="email" aria-invalid="true" aria-describedby="email-error"> <span id="email-error" role="alert">Please enter a valid email address</span>
Three declarations do the work: aria-invalid="true" marks the field as failed, aria-describedby binds the message to the field it describes, and role="alert" announces the message to every consumer.
Open the pattern to continue.
Why this matters for agents
AI agents fall into five categories, each with different capabilities, and none of them reads your CSS the way a human eye does. When state is encoded visually, through colour, opacity, position, or animation, it is invisible to every agent that does not render the page. View each group:
Agents like ChatGPT and Claude fetch raw HTML without executing JavaScript or rendering CSS. They see the DOM as plain text. A greyed-out button looks disabled to a human eye; to these agents it is an active, clickable button unless the disabled attribute is present.
Agents like Perplexity use headless Chrome, so they do render the page - but they still rely on semantic attributes to determine state. Rendering pixels does not tell an automation script whether a button may be pressed; disabled and aria-invalid do.
Local agents running on device have limited context windows and need every byte to count. An agent that meets ambiguous state makes one of two choices: it guesses (and sometimes guesses wrong, triggering unintended actions) or it skips the element entirely (and the user loses functionality). Neither outcome is acceptable.
View all three groups to continue.
Quick check
A button is styled with opacity 0.5 and a class of "btn-disabled" but has no disabled attribute. What does a server-side AI agent conclude?
disabled attribute in the markup, the button reads as active and clickable.Answer the question to finish the lesson.
What you now know
- Machines do not infer. Humans read a greyed-out button as unavailable; an agent reads only what the markup declares.
- State must be declared in markup: disabled, loading, required, current page, and error states all have explicit attributes.
- Native HTML beats ARIA retrofits:
required,disabled, and semantic elements first, ARIA where HTML has no native attribute. - If something matters, declare it explicitly. The test: remove all CSS - could a machine still understand what each element does?