Layout Is A Runtime
HTML and CSS are easy to mistake for documents.
They are not only documents.
A browser turns markup, selectors, cascade, layout, focus, input state, accessibility roles, media queries, and hydration into a running system. A small class change can move a button, hide a label, alter tab order, change the accessible name, or make a component render differently after the client takes over.
Layout is a runtime.
Markup Is Input
Markup is not the final state of the interface. It is input to a larger machine.
html: element tree and attributes
css: selectors, cascade, media rules, containment
browser: layout, paint, focus, accessibility tree
framework: hydration, state, event handlersA text merge can know that two branches edited different lines. A semantic merge can know that two branches edited different elements. But a UI merge also has to ask what those edits do after the browser runs them.
Two edits can be structurally independent and still collide in the rendered result.
branch A: adds sticky header
branch B: adds fixed toolbar
runtime conflict: toolbar covers header controlsThe conflict is not in the source shape. It is in the runtime surface.
CSS Has Control Flow
CSS looks declarative, but it has control flow of its own.
Media queries branch by viewport. Container queries branch by parent size. Cascade layers change precedence. Pseudo-classes branch by user state. Custom properties flow through scopes. Specificity decides which declaration wins.
@media -> viewport branch
@container -> layout branch
:hover -> input state branch
:focus-visible -> keyboard state branch
var() -> dependency edge
@layer -> precedence orderThat is why style merging cannot stop at "these declarations are different." It has to know where the declaration lands in the cascade and what other declarations it can override.
A safe merge for CSS is not just a parser problem. It is a cascade problem.
Evidence Needs To Match The Surface
Different UI changes need different evidence.
| Surface | Probe | Measured signal | Admission route |
|---|---|---|---|
| Selector reachabilityclass rename, CSS Module export, selector edit | Target probeResolve selectors against the output DOM. | Matched elements, orphaned selectors, intended target moves | Admit targetThe selector still reaches the same semantic target. |
| Viewport layoutmedia rule, container query, spacing, position | Viewport matrixRender declared widths and compare geometry. | Bounding boxes, overlap, visibility, scroll range | Gate layoutThe layout holds for the declared viewport set. |
| Interaction statehover, focus, disabled state, input workflow | Interaction traceReplay the smallest user path through the output. | Focus order, enabled controls, event result, state transition | Gate workflowThe workflow remains reachable after the merge. |
| Accessibility treerole, label, aria relationship, hidden content | A11y snapshotRead the browser accessibility tree. | Accessible name, role, state, relationships, tab stop | Require proofThe control keeps its user-facing semantics. |
| Hydration boundaryserver markup, client state, framework runtime | Hydration probeLoad server output and observe client takeover. | Console errors, markup drift, event attachment, first state | Block driftThe rendered output survives client hydration. |
If a patch changes a class name, selector reachability matters.
If a patch changes responsive layout, viewport evidence matters.
If a patch changes focus or visibility, interaction evidence matters.
If a patch changes labels, controls, or structure, accessibility evidence matters.
class rename -> selector and use-site graph
media rule edit -> viewport matrix
focus style edit -> keyboard trace
aria edit -> accessibility tree check
hydration edit -> server/client boundary evidenceThe point is not to require every proof for every change. The point is to route the change to the smallest proof that matches the runtime surface it touches.
Static Shape Still Helps
Runtime evidence does not make static structure useless.
Element identity, keyed children, selector specificity, CSS Modules exports, and source spans all reduce the search space. They tell the system where a change might matter.
static evidence:
element key
class attribute
selector
declaration
cascade key
runtime evidence:
viewport result
interaction trace
accessibility tree
hydration statusStatic evidence says what changed.
Runtime evidence says what the browser did with it.
The Mental Model
Treat UI source as a program for a browser runtime.
HTML describes structure. CSS describes constraints and branches. JSX describes a render function. The browser executes all of it into layout, interaction, and accessibility state.
A serious merge system should respect that boundary.
It can admit simple structural changes with static evidence. It should ask for runtime evidence when the change crosses into layout, focus, visibility, accessibility, hydration, or user interaction.