Skip to content

Respect flex-direction:column when converting flex containers#338

Merged
chubes4 merged 1 commit into
trunkfrom
fix/flex-column-not-columns
Jun 29, 2026
Merged

Respect flex-direction:column when converting flex containers#338
chubes4 merged 1 commit into
trunkfrom
fix/flex-column-not-columns

Conversation

@chubes4

@chubes4 chubes4 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor

Problem

A vertical flex container (display:flex; flex-direction:column — e.g. a hero with eyebrow → title → subhead → buttons stacked vertically) was converted to a horizontal core/columns block. The page rendered a broken side-by-side row instead of a vertical stack. The corpus-diagnostics harness (#337) detects this as layout_direction_misrecognition :: columns_from_vertical_flex.

The transformer recognized any display:flex container with multiple children as core/columns without ever inspecting flex-direction.

Fix (generic, keys off the CSS flex-direction value — never fixture names/classes)

1. ColumnsPattern::looksLikeColumnsContainer — declines a container whose resolved inline style declares display:flex (or inline-flex) and flex-direction: column / column-reverse. The host transformer then routes the element down the existing generic path, emitting a core/group that preserves the container's classes/styles. Row / row-reverse / default flex and grid layouts are untouched, so legitimate horizontal column layouts keep their current behavior.

private function isVerticalFlexContainer(string $style): bool
{
    if ( ! preg_match('/(?:^|;)\s*display\s*:\s*(?:inline-)?flex\b/', $style) ) {
        return false;
    }
    return (bool) preg_match('/(?:^|;)\s*flex-direction\s*:\s*column(?:-reverse)?\b/', $style);
}

2. StyleResolutionTrait::layoutAttribute — emits an explicit orientation: vertical for column-flex containers. A core/group flex layout otherwise defaults to a horizontal Row in WordPress, so without this the children would still render side-by-side. Horizontal flex stays { "type": "flex" } (implicit horizontal).

Before / after

Input: <div class="hero" style="display:flex;flex-direction:column;gap:1rem">…</div>

  • Before: core/columnscore/column children laid out horizontally (broken side-by-side row).
  • After: core/group with layout: { "type": "flex", "orientation": "vertical" } → children stack vertically.

Horizontal flex (display:flex, row/default) still converts to core/columns — unchanged.

Tests

  • Baseline composer test:canonical + composer parity green before changes.
  • New parity fixtures: html-vertical-flex-column-becomes-group (vertical flex → vertical core/group, asserts no wp:columns) and html-horizontal-flex-stays-columns (row flex → core/columns).
  • Updated tests/unit/corpus-detectors.php: detector logic now exercised with a stubbed verifier, plus a live-transformer regression guard (case 4e/4f) asserting vertical flex emits a vertical core/group and horizontal flex stays core/columns.
  • Full composer test green: contracts, unit (CorpusDetectors 27 passed), parity 175 fixtures, packaging proof. php -l clean on all changed files.

Harness cluster delta (composer corpus-diagnostics)

Metric Before After
layout_direction_misrecognition :: columns_from_vertical_flex 21 (17 files) 0
total findings 7247 7222
native_rate 97.9% 97.9%

No other cluster regressed.

AI assistance

  • AI assistance: Yes
  • Tool(s): Claude Opus 4.8 via Claude Code
  • Used for: Diagnosis, implementing the flex-direction check, fixtures/tests, and verification.

A flex container with `flex-direction: column` / `column-reverse` is a
vertical stack, but the HTML transformer converted any `display:flex`
container with multiple children to a horizontal `core/columns` block.
Hero stacks (eyebrow, title, subhead, buttons) rendered side-by-side
instead of stacked — the corpus-diagnostics
`layout_direction_misrecognition :: columns_from_vertical_flex` cluster.

Key off the CSS `flex-direction` value, never fixture names or classes:

- ColumnsPattern::looksLikeColumnsContainer now declines a container whose
  resolved style declares `display:flex` with a column main axis, so the
  host transformer routes it to the generic vertical `core/group` path.
  Row / row-reverse / default flex and grid layouts are untouched, so
  legitimate horizontal columns are preserved.
- layoutAttribute emits an explicit `orientation: vertical` for column-flex
  containers. A `core/group` flex layout otherwise defaults to a horizontal
  Row, so without this the children would still render side-by-side.

Adds parity fixtures for both directions (vertical flex -> vertical
core/group; horizontal flex -> core/columns), updates the corpus-detector
unit test to assert the live transformer now stacks vertically, and drives
the columns_from_vertical_flex cluster from 21 to 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@chubes4 chubes4 merged commit 591ec39 into trunk Jun 29, 2026
1 check passed
@chubes4 chubes4 deleted the fix/flex-column-not-columns branch June 29, 2026 01:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant