Hero image for C.R.A.P., translated for agents: two principles compile, two only approximate

C.R.A.P., translated for agents: two principles compile, two only approximate

The eye is not an API

The C.R.A.P. mnemonic, popularised by Robin Williams in The Non-Designer’s Design Book, is a memorable shorthand for four graphic design principles: Contrast, Repetition, Alignment, and Proximity. These principles are instructions for a human visual system, a biological processor evolved to parse meaning from spatial relationships and colour. An AI design agent has no retina, no innate sense of harmony. Its only sensory input is the Document Object Model (DOM) and the CSS cascade. It sees the box tree and the computed values. To learn design, the agent must translate subjective heuristics into deterministic checks against this limited, numerical reality. This post evaluates how each C.R.A.P. principle compiles into a machine-readable rule. The thesis is stark: Contrast compiles to an exact check, Repetition compiles once a token file exists, Alignment degrades to a geometric proxy, and Proximity does not survive translation at all.

Contrast: the one principle that compiles exactly

The check

Contrast is the principle most amenable to computation because its core requirement is defined by a mathematical formula in the Web Content Accessibility Guidelines (WCAG). The W3C specifies SC 1.4.3 for text and SC 1.4.11 for non-text UI components. For an agent, the check is a two-step calculation.

First, retrieve the resolved foreground and background colours for a text node. The DOM API provides getComputedStyle(), which returns the final computed values (e.g., rgb(255, 255, 255)) after all CSS inheritance and cascade rules are resolved. Second, apply the WCAG relative luminance formula and contrast ratio calculation. Relative luminance (L) is computed as L = 0.2126R + 0.7152G + 0.0722B, where R, G, and B are linearised from their sRGB values. The linearisation is: if c <= 0.03928, then c/12.92, else ((c + 0.055) / 1.055) ^ 2.4. The contrast ratio is then (L1 + 0.05) / (L2 + 0.05), with L1 being the luminance of the lighter colour. The agent then compares this ratio to the applicable WCAG threshold: for normal text, at least 4.5:1 (AA) or 7:1 (AAA); for large text (at least 18pt/24px or 14pt bold/18.66px), at least 3:1. For non-text UI components, SC 1.4.11 mandates a 3:1 ratio.

Where it fails

The check is logically sound but contextually fragile. The getComputedStyle() API gives the colour of an element’s own background, but text often sits on a complex, composite background—a gradient, a semi-transparent overlay, an image. The DOM reports the element’s computed background colour, not the colour the human eye actually perceives behind the text. An agent measuring only background-color will generate false positives (flagging text as low-contrast when a parent container provides sufficient contrast) or false negatives. True accuracy would require rasterising the visual stack, which is computationally prohibitive for a simple audit agent.

Repetition: measurable if and only if tokens exist

The check

Repetition ensures visual consistency by reusing properties like colour, spacing, and typography. For an agent, repetition is verifiable against a source of truth: a design tokens file. Such a file declares properties with a $value and optional $type. The agent’s check becomes: query every element, retrieve its key visual properties via getComputedStyle(), and compute the fraction whose resolved values (e.g., rgb(241, 67, 54) for a colour, 16px for a margin) exactly match a declared $value in the token file.

Where it fails

This check is binary and brittle. It measures conformity, not quality. A component might use a colour from the token palette that is perfectly valid but used in a visually poor combination. More critically, if no token file exists, the check is meaningless. The sub-score should be reported as null, never 0, to indicate that the principle is inapplicable, not violated. The agent can only audit adherence to a predefined system; it cannot judge the aesthetic merit of the repetition itself.

Alignment: geometry is geometry, up to a tolerance

The check

Alignment creates order by placing elements along common axes. Geometrically, this means elements share x- or y-coordinates. An agent can approximate this by grouping elements (e.g., by a common parent or a CSS class) and then checking if their edges (left, right, top, bottom) align. The metric, as reported in the computational-aesthetics literature (Ngo et al.), often involves calculating the fraction of edges that share a coordinate within a tolerance—say, 1 pixel. For an agent, the check is: for each group, find the set of unique x-coordinates and y-coordinates for all element edges, and count how many elements have an edge that falls within the tolerance of one of these coordinates.

Where it fails

The fatal flaw is grouping. The DOM provides a structural hierarchy, but design grouping is semantic. An element may be visually part of a group (e.g., a form field and its label) while being structurally distant in the DOM, separated by wrappers or layout modules. Common region compounds this: a border or background fill groups elements by enclosure rather than by distance, which a coordinate-clustering check cannot see. An agent using the DOM tree as a grouping mechanism will misapply the alignment check. An element must be assigned to a group before it can be called misaligned with one, and that assignment is proximity’s unsolved problem, which is the subject of an earlier post on Gestalt geometry.

Proximity: the DOM knows distance, not meaning

The check

Proximity states that objects near each other are perceived as a group. An agent can compute physical distance (Euclidean) between element bounding boxes. A check might measure the fraction of “related” element pairs whose distance is minimal relative to their distance to other elements. A more structural proxy is to use the nearest common ancestor depth in the DOM tree: elements under the same parent are proximate.

Where it fails

The DOM is a tree of meaning, not a map of space. Proximity in design is about perceptual grouping, which can be achieved through layout modules like CSS Grid or Flexbox, placing “distant” DOM nodes visually together. Conversely, two elements may be DOM-siblings but visually far apart due to positioning. The agent has no intrinsic knowledge of which elements are “related.” Any check based on DOM depth or pixel distance is a guess, rewarding code that mimics the visual outcome rather than the semantic relationship. This is the least computable of the C.R.A.P. principles.

The computability grade sheet

Principle Computable Check Selector / Property Threshold False-Positive Risk Grade
Contrast WCAG 1.4.3 & 1.4.11 Ratio getComputedStyle().color, .backgroundColor 4.5:1 (AA text), 3:1 (AA large/non-text) High (composite backgrounds) Computable
Repetition Token Value Match getComputedStyle() vs. token $value 1.0 (all values match a token) Medium (strict equality) Computable (with token file)
Alignment Edge-Coordinate Cluster Element box edges (offsetLeft, offsetTop) ≥0.9 edges within 1px of a group axis High (incorrect grouping) Proxy
Proximity DOM Ancestor Depth or Euclidean Distance Bounding boxes, DOM tree depth Pairwise distance < median Very High (no semantic grouping) Not-computable

The C.R.A.P. Score

To create a single computable metric, we can define a weighted formula. The C.R.A.P. Score is calculated as: Score = 0.35*Contrast + 0.20*Repetition + 0.25*Alignment + 0.20*Proximity. Each sub-score ranges from 0 to 1. Contrast is the fraction of text nodes whose resolved foreground/background pair meets its WCAG minimum. Repetition is the fraction of visual property values matching a declared token $value; this sub-score is null (not 0) when no token file exists. Alignment is the fraction of element edges sharing an x- or y-coordinate within 1px, bucketed per group. Proximity is the fraction of related element pairs whose nearest-common-ancestor depth separates them the same way their nearest on-screen neighbours do.

The weights reflect each principle’s computability and impact. Contrast is the most objectively measurable and critical for accessibility, hence the highest weight. Repetition is also measurable but depends on an external artifact. Alignment is a geometric approximation. Proximity is the weakest sub-score, as grouping is semantic and the DOM only proxies meaning through ancestor structure, so it rewards code that matches the tree rather than the reader.

Verdict: what an agent can and cannot compute

Contrast is a fully computable rule when the background is flat and known. Repetition is a fully computable audit of adherence if a design token file is the ground truth. Alignment is a geometric proxy that depends entirely on a grouping heuristic the agent cannot reliably derive. Proximity is not computable because the agent cannot infer perceptual meaning from DOM structure. This analysis is based on published specifications and documentation; no interface was instrumented for this post. An agent can enforce a styleguide but not judge visual harmony; it can check compliance but not comprehension. For the earlier treatment of the same asymmetry in Nielsen’s ten heuristics, see which design frameworks survive contact with an agent.