Layout Scorers API

Deterministic geometry/contrast defect detection measured directly off the rendered page — no LLM, no API key. Detects contrast failures, sibling overlap, clipped content, viewport protrusion (both edges), page-level horizontal overflow, ellipsis text truncation, WCAG-aware target spacing, complete focus obscuration, and rendered text occlusion. Target-size findings apply machine-measurable WCAG 2.5.8 exceptions. The scanner also exercises focusable controls for complete focus obscuration (WCAG 2.4.11) and detects painted DOM elements crossing rendered text, including graph labels. Semantic exceptions remain explicit manual-review fields; the report is not a site-wide conformance claim.

LayoutScorer

class layoutlens.LayoutScorer(*, min_target_px=24, overlap_threshold_px2=200, clip_tolerance_px=2, protrude_tolerance_px=1, contrast_threshold=4.5, occlusion_samples_per_axis=5)[source]

Bases: object

Deterministic layout/geometry scorer over a rendered page.

Parameters:
  • min_target_px (int)

  • overlap_threshold_px2 (int)

  • clip_tolerance_px (int)

  • protrude_tolerance_px (int)

  • contrast_threshold (float)

  • occlusion_samples_per_axis (int)

async detect_overlaps(page)[source]

Return findings for visible siblings whose bounding boxes overlap.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_clipping(page)[source]

Return findings for elements whose content is clipped by hidden overflow.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_protrusion(page)[source]

Return findings for elements protruding past either horizontal viewport edge.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_page_overflow(page)[source]

Return a finding if the whole document scrolls horizontally.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_truncation(page)[source]

Return findings for single-line text actually cut off by an ellipsis.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_small_targets(page)[source]

Return undersized targets that also fail measurable WCAG spacing exceptions.

The spacing, inline, and unmodified user-agent-control exceptions are evaluated automatically. Equivalent-control and essential-presentation exceptions are semantic and remain manual-review fields on every finding.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_text_occlusion(page)[source]

Return rendered text fragments covered by another painted DOM element.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async detect_focus_obscured(page)[source]

Return keyboard-focused components entirely hidden by author DOM content.

This automates the geometric core of WCAG 2.4.11. Whether an occluder was user-opened and can be dismissed without advancing focus can require interaction history, so each finding discloses those manual exceptions.

Parameters:

page (Page)

Return type:

list[LayoutFinding]

async scan_page(page, source=None, viewport='desktop')[source]

Run every detector on an already-loaded page and return a report.

Parameters:
  • page (Page) – A loaded Playwright page.

  • source (str | None) – Optional source label recorded in the report; defaults to the page URL.

  • viewport (str) – Viewport name recorded in the report.

Returns:

The structured layout report.

Return type:

LayoutReport

async scan(source, viewport='desktop')[source]

Scan a URL or local HTML file, owning the browser lifecycle.

Parameters:
  • source (str | Path) – A URL or path to a local HTML file.

  • viewport (ViewportType) – Viewport name or Viewport member.

Returns:

The structured layout report.

Return type:

LayoutReport

Report Types

class layoutlens.LayoutReport(source, viewport, findings, timestamp=<factory>)[source]

Bases: object

Structured deterministic layout report for a single page and viewport.

Parameters:
source

The URL or file path that was scanned.

Type:

str

viewport

The viewport name used for the scan.

Type:

str

findings

All measured layout defects, in detector order.

Type:

list[layoutlens.layout.types.LayoutFinding]

timestamp

ISO-8601 timestamp of when the report was created.

Type:

str

property ok: bool

Return True if there are no findings.

by_class()[source]

Group findings by their defect_class.

Return type:

dict[str, list[LayoutFinding]]

to_json()[source]

Serialize the report to an indented JSON string.

Return type:

str

summary()[source]

Return a compact, human/LLM-readable summary of the report.

Return type:

str

class layoutlens.LayoutFinding(defect_class, selector, bbox, measured, threshold, description, wcag_refs=<factory>)[source]

Bases: object

A single measured layout defect affecting one or two DOM elements.

Parameters:
defect_class

Stable finding class such as "contrast", "overlap", "clipping", "viewport-protrusion", "target-size", "focus-obscured", or "text-occlusion".

Type:

str

selector

A best-effort CSS selector locating the offending element (for overlap, the primary element; the partner is in measured).

Type:

str

bbox

The element’s rounded [x, y, width, height] in CSS pixels.

Type:

list[int]

measured

The measured numbers behind the finding (e.g. the contrast ratio, the intersection area, the overflow in pixels).

Type:

dict[str, Any]

threshold

The threshold(s) the measurement violated.

Type:

dict[str, Any]

description

A human/LLM-readable one-line description.

Type:

str

wcag_refs

Relevant WCAG success-criterion tags where the defect maps to one (contrast -> wcag143, target-size -> wcag258); empty for the ReDeCheck-style geometric defects that are not WCAG SCs.

Type:

list[str]

Contrast Math

layoutlens.contrast_ratio(rgb1, rgb2)[source]

Return the WCAG contrast ratio (1..21) between two sRGB colors (symmetric).

Parameters:
Return type:

float

async layoutlens.check_contrast(page, *, threshold=4.5)[source]

Scan page for text below the WCAG AA contrast threshold.

Reads every visible text element’s computed foreground and effective opaque background, computes the WCAG contrast ratio, and returns a finding for each element under threshold (3.0 for large text, threshold otherwise).

Parameters:
  • page (Page) – A loaded Playwright page.

  • threshold (float) – The AA normal-text ratio to require (default 4.5).

Returns:

One LayoutFinding per low-contrast text element.

Return type:

list[LayoutFinding]