Skip to content

fix(website-builder-react): stack Grid columns via CSS media query - #5603

Closed
adrians5j wants to merge 5 commits into
release/6.4.9from
claude/trace-breakpoint-init
Closed

fix(website-builder-react): stack Grid columns via CSS media query#5603
adrians5j wants to merge 5 commits into
release/6.4.9from
claude/trace-breakpoint-init

Conversation

@adrians5j

@adrians5j adrians5j commented Aug 26, 2026

Copy link
Copy Markdown
Member

Problem

Grid column stacking is resolved in JS from the runtime viewport breakpoint (breakpoint === stackAtBreakpoint) and applied as inline styles.

On SSR the breakpoint is always desktop, so the served HTML renders columns side-by-side and only corrects once the client hydrates and re-resolves the breakpoint. That causes a layout flash — and stays broken entirely when the content subtree doesn't hydrate (e.g. content rendered via next/dynamic({ssr:true})), which is how this surfaced on an OpenNext/SSG frontend: a grid set to stack at mobile stayed 2-column at mobile width.

Fix

Emit stacking as a scoped CSS media query in the rendered HTML, so the browser applies it by the real viewport width — no JS, no hydration dependency, no flash.

  • Grid renders a scoped class wb-grid-<element.id> plus a <style> block:
    @media (max-width: <breakpoint-width>px) {
      .wb-grid-<id> { flex-direction: column !important; }
      .wb-grid-<id> > .wb-grid-col { flex: 0 0 100% !important; max-width: 100% !important; }
    }
  • The stack width is read from the theme's breakpoint definition (no hardcoded widths).
  • ContentSdk.init now populates viewportManager breakpoints on the server too (the resize listener stays client-only), so SSR has the real widths to generate the media query.
  • CSS/class string building lives in gridStyles.ts (createGridClass, createGridStackingCss), not inline in the component.

Screenshot

image

Scope

Grid stacking only. Multiple grids and nested grids are safe (unique per-id class + direct-child combinator). Deliberately out of scope, as follow-ups:

  • Per-breakpoint styles for all elements (e.g. responsive rowGap/columnGap, spacing, visibility) — same JS→@media treatment, generalized.
  • Per-breakpoint content (text/RTE per breakpoint) and responsive images (<picture>/srcset).
  • The content-hydration gap and SSG draftMode behavior (orthogonal bugs).

Testing

  • Verified the @media block is present in the SSR HTML and the browser stacks columns at the breakpoint width with no client JS.
  • Builds clean; changed files formatted (oxfmt) and linted (oxlint).

🤖 Generated with Claude Code

webiny-bot and others added 5 commits September 1, 2026 06:48
Empty commit to allow PR creation.
…ators

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…age converter

Return undefined instead of throwing when a dynamic zone value
references a template that no longer exists. Filter out undefined
entries in the list case to prevent undefined array items.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Grid column stacking was resolved in JS from the runtime viewport
breakpoint (`breakpoint === stackAtBreakpoint`) and applied as inline
styles. On SSR the breakpoint is always "desktop", so the served HTML
renders columns side-by-side and only corrects once the client
hydrates and re-resolves the breakpoint — causing a layout flash, and
staying broken entirely when the content subtree does not hydrate.

Stacking is now emitted as a scoped CSS media query in the rendered
HTML, so the browser applies it by the real viewport width with no JS,
no hydration dependency, and no flash.

- Grid renders a scoped class (`wb-grid-<id>`) plus a `<style>` block
  with `@media (max-width: <breakpoint-width>) { ... }`.
- The stack width is read from the theme's breakpoint definition.
- ContentSdk now populates `viewportManager` breakpoints on the server
  too (the resize listener stays client-only), so SSR has the real
  widths to generate the media query.
- String/CSS building lives in `gridStyles.ts`, not the component.

Scope: Grid stacking only. Per-breakpoint styles/content for other
elements are follow-ups.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@adrians5j

Copy link
Copy Markdown
Member Author

Superseded — recreating against release/6.4.10.

@adrians5j
adrians5j force-pushed the claude/trace-breakpoint-init branch from 97dd4f9 to 2ba6434 Compare September 2, 2026 08:20
@adrians5j adrians5j closed this Sep 2, 2026
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.

2 participants