Skip to content

.sf-equal is implemented as a grid duplicate — it was meant to be CSS multi-column flowing layout #502

Description

@jackgranatowski

Updated diagnosis (supersedes original report below)

Original report correctly found that .sf-equal and .sf-grid--fit generate the identical auto-fit/minmax() grid pattern. Further discussion clarified the actual bug: .sf-equal was never meant to be a grid at all.

The intended behavior — confirmed with the author — is CSS multi-column flowing layout (column-width/column-count/column-gap): content (FAQ entries, text blocks) should flow between columns like a newspaper/magazine layout, filling the first column top-to-bottom before continuing at the top of the next one. CSS Grid cannot do this — it places each child into one fixed cell, it never lets content flow across cell boundaries.

Verified: greping the whole repo (core/, optional/, including staged/commented blocks in optional/components.css) for column-count, column-width, columns:, column-span returns zero real hits — only unrelated grid-template-columns matches. So .sf-equal today does not, and never did, implement the flowing-column behavior its name promises.

Side finding: docs/token-annotations.json has an orphaned token category, "CSS multi-column" — "column-rule widths" — and docs/migration.md:315-316 mentions multi-column tokens being "merged" at some past version. No column-rule token exists in core/tokens.css today. This category has been empty/aspirational for a while; this fix will finally fill it in.

Fix

Re-implement .sf-equal on real CSS multi-column properties instead of grid:

.sf-equal {
  column-width: var(--sf-equal-min-col);
  column-gap:   var(--sf-equal-gap);
  column-rule:  var(--sf-equal-rule-width) var(--sf-equal-rule-style) var(--sf-equal-rule-color);
}
.sf-equal--2 { column-count: 2; }
.sf-equal--3 { column-count: 3; }
.sf-equal--4 { column-count: 4; }
.sf-equal--6 { column-count: 6; }

.sf-equal > * { break-inside: avoid; }
  • column-width acts as the same kind of breakpoint-free minimum threshold --sf-grid-min already provides for grid — reuses the existing --sf-equal-min-col token, semantics carry over unchanged.
  • The numbered --sf-equal-min-col-2/-3/-4/-6 width-tuning tokens are replaced by a direct column-count per modifier — more literal than before (.sf-equal--3 now guarantees 3 columns rather than indirectly hoping a tuned width threshold produces 3).
  • New tokens: --sf-equal-rule-width (default 0, off), --sf-equal-rule-style (solid), --sf-equal-rule-color (var(--sf-color-border)) — fills the previously-orphaned "CSS multi-column" token category. Off by default, consistent with how other optional decorations (shadows, etc.) default to inert in this framework.
  • .sf-grid/.sf-grid--fit are untouched and remain the discrete-cell-per-item primitive — this is no longer a duplication question, the two serve genuinely different purposes (discrete grid cells vs. flowing multi-column content).

Scope

  • core/tokens.layout.css — replace --sf-equal-min-col-2/-3/-4/-6 with --sf-equal-rule-width/-style/-color
  • core/layout.css — rewrite .sf-equal block per above
  • tests/layout.spec.js — rewrite .sf-equal assertions to check column-count/column-width instead of grid-template-columns
  • configurator/src/components/panels/LayoutPanel.svelte — update the Equal-columns section to match the new token set
  • docs/layout.md, docs/llm-guide.md — update .sf-equal description and token list

Original report (superseded above, kept for history)

.sf-equal (core/layout.css:438-446) and .sf-grid--fit (core/layout.css:205-207) generate the exact same CSS pattern:

grid-template-columns: repeat(auto-fit, minmax(min(<min-width-token>, 100%), 1fr));

The only difference is which custom property feeds the minmax() floor — --sf-equal-min-col vs --sf-grid-min. .sf-grid without the --fit modifier uses auto-fill instead (leaves empty tracks), but once --fit is applied, it is mechanically identical to .sf-equal.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions