Skip to content

[finding] absolute-colspan-discouraged asserts a misalignment that does not happen — measured in Chromium at all three surface widths, and its recommended alternative span: 'full' is the spelling that misrenders #17328

Description

@claude

Summary

absolute-colspan-discouraged (packages/lint/src/validate-form-layout.ts) fires on every authored colSpan on a form field. Its message asserts a rendering consequence:

NAME: field "FIELD" sets absolute colSpan 2 — the form's column count is derived per surface (mobile 1 / modal 2 / page 3-4), so a fixed span only aligns at one width

and its hint recommends an alternative:

Prefer span: 'full' (whole row at any column count), or omit for auto width. The renderer clamps colSpan to the current column count.

That claim had never been tested. hotcrm#1694 was opened to test it, because hotcrm had already cleared all 26 of its absolute-colSpan entries across 11 view files (hotcrm PR #1605) on the strength of the assertion alone.

Measured in Chromium at all three surface widths: the message's premise is false, and the hint's own second sentence is the reason. The renderer does clamp — and because it clamps, a fixed span aligns at every width, not at one. Meanwhile span: 'full', the spelling the hint tells authors to prefer, is the one that renders wrongly at the middle width.

Method

Browser measurement, not source reading (hotcrm#806 is the precedent for why source reading is not acceptable here).

  • App: hotcrm at commit 427c98535de3253ab6b0667716098d9ea0d8e0ad, pinned @objectstack/* 17.4.0, objectstack dev, Chromium 141.0.7390.37 at /opt/pw-browsers/chromium.
  • Surface: crm_knowledge_article record edit form (a modal dialog), URL path /_console/apps/crm_enterprise/crm_knowledge_article/record/Pgz0SIR6NfjLNwVW?form=Pgz0SIR6NfjLNwVW.
  • Site: the authored engagement section, columns: 3, fields helpful_count, not_helpful_count, published_at, last_reviewed_at, related_to_case. This section is authored on hotcrm main today — no scaffold was invented for the test.
  • Same form, same record, same viewports; exactly one attribute changed on the first field (helpful_count) per configuration. Each configuration was applied on a scratch branch, confirmed to have reached the running server by reading the server's own /api/v1/meta/view payload before measuring, then reverted and byte-verified against the HEAD blob. Nothing was landed.
  • Reported geometry is reconstructed from rendered rects (getBoundingClientRect) and resolved computed styles, not from the stylesheet. Every reading was taken twice with a settle in between; all were stable.

The whole form renders as one grid whose column count comes from the field count and is then resolved by container queries (grid-cols-1 @md:grid-cols-2 @2xl:grid-cols-3). So "the three surfaces" are three container widths, and all three are reachable on one form.

Rendered geometry — the helpful_count cell

grid width is the grid's content box; field width is the measured cell; ovf is cell right edge minus grid content width. All values in px.

authored surface viewport rendered cols grid width emitted class computed grid-column field width ovf
(none) = main today mobile 390 1 358 (none) auto 358 0
(none) = main today modal 720 2 586 (none) auto 285 0
(none) = main today page 1700 3 1517 (none) auto 495 0
colSpan: 2 mobile 390 1 358 @md:col-span-2 auto 358 0
colSpan: 2 modal 720 2 586 @md:col-span-2 span 2 / span 2 586 0
colSpan: 2 page 1700 3 1517 @md:col-span-2 span 2 / span 2 1006 0
span: 'full' mobile 390 1 358 @2xl:col-span-3 auto 358 0
span: 'full' modal 720 2 586 @2xl:col-span-3 auto 285 0
span: 'full' page 1700 3 1517 @2xl:col-span-3 span 3 / span 3 1517 0
colSpan: 4 mobile 390 1 358 @2xl:col-span-3 auto 358 0
colSpan: 4 modal 720 2 586 @2xl:col-span-3 auto 285 0
colSpan: 4 page 1700 3 1517 @2xl:col-span-3 span 3 / span 3 1517 0
colSpan: 1 mobile 390 1 358 (none) auto 358 0
colSpan: 1 modal 720 2 586 (none) auto 285 0
colSpan: 1 page 1700 3 1517 (none) auto 495 0

Row structure stayed intact in every configuration: the cell always started at a real column boundary, and overflow was 0px at every width in every configuration — including colSpan: 4 in a 3-column section, the case that would overflow if the clamp did not work.

What the numbers say

1. An absolute colSpan does not misalign at any of the three widths. colSpan: 2 renders as: the whole row at 1 column, exactly 2 of 2 at the modal width (a full row), exactly 2 of 3 on the page. Grid-aligned everywhere, zero overflow. The message's "a fixed span only aligns at one width" is contradicted at all three widths it names.

2. The clamp is real, and it is the reason the premise is false. The span is emitted as a single container-query-scoped Tailwind class (@md:col-span-2), clamped to the section's declared column count. It is simply inert below the breakpoint at which that many columns exist. The hint already says this; the message contradicts the hint.

3. The recommended alternative is the one that misrenders. span: 'full' compiles to @2xl:col-span-3 — a hard-coded span of the declared maximum, gated at the top breakpoint only. At the modal width it renders pixel-identical to writing nothing at all (285px, one column of two). An author who writes span: 'full' and opens that record in a modal does not get a full row. Confirmed visually as well as numerically.

4. colSpan: 4 and span: 'full' emit the identical class (@2xl:col-span-3) and are byte-identical in every rendered measurement. The rule warns about one of them and recommends the other, and they are the same thing.

5. colSpan: 1 emits no class at all and is byte-identical to the control at all three widths — completely inert, yet it produces a warning. Two of the entries hotcrm PR #1605 deleted were exactly this.

Why this is filed here

Per hotcrm AGENTS.md Scope rule 4, a bad platform default is fixed at the default, not compensated for in the tenant repo. hotcrm changed nothing: it authors zero absolute colSpan today, and this measurement landed nothing.

Two halves, and I am deliberately not splitting them myself:

  • The lint rule (packages/lint/src/validate-form-layout.ts) is this repo's. Its message states a rendering consequence that does not occur. As written it also cannot distinguish an inert colSpan: 1 from anything else.
  • The renderer behaviour in finding 3span: 'full' not spanning the full row at intermediate container widths — is emitted by the console bundle (vendored objectui), so the fix for that half probably belongs to an objectui card. Flagging rather than filing, so triage decides.

Suggested shape for the rule half, for whoever picks it up: either retire it, or narrow it to the case it can actually justify and correct the message so it stops asserting a misalignment that the clamp prevents. It should not keep recommending span: 'full' while that spelling measures worse than the thing being warned about.

The measurement is recorded in full on hotcrm#1694. The harness, the per-configuration geometry JSON and the screenshots at all three widths live in that run's scratchpad rather than as attachments; the Method section above is sufficient to reproduce them from scratch against any app on the pinned version.

Refs: hotcrm#1694 (this measurement) - hotcrm#1524 (the card it was split from) - hotcrm PR #1605 (the 26 rewrites made on the untested assertion) - hotcrm#806 (why this was measured in a browser)


Generated by Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions