From 674fbc9e461453f6b75c581f52cef3514482bcc0 Mon Sep 17 00:00:00 2001 From: Ilja Melnicenko Date: Thu, 6 Aug 2026 13:30:53 +0200 Subject: [PATCH] design-parity skill v1.3: t3b_core spacing system Add a dedicated section on where spacing is resolved (Spacing.yaml -> per-site spacing.yaml -> tx_t3b_spacing) and why a spacing fix in the custom SCSS partial silently disables the editor-facing field: the utility class it emits is (0,1,0) and loses to any contextual rule. Also covers the first/last-position leak into container columns, the fact that the system has no notion of "has a background" (so seemingly contradictory spacing complaints are two different cases), when SCSS is still the right tool (per-column, not per-element), and how to verify from the emitted markup instead of the rendering. Co-Authored-By: Claude Opus 5 (1M context) --- typo3-t3bootstrap-live-design-parity/SKILL.md | 59 ++++++++++++++++++- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/typo3-t3bootstrap-live-design-parity/SKILL.md b/typo3-t3bootstrap-live-design-parity/SKILL.md index 2e24a53..0883458 100644 --- a/typo3-t3bootstrap-live-design-parity/SKILL.md +++ b/typo3-t3bootstrap-live-design-parity/SKILL.md @@ -1,9 +1,9 @@ --- name: typo3-t3bootstrap-live-design-parity -description: "Match a TYPO3 v14 t3bootstrap-based build (local DDEV) to a reference LIVE site page by page — the frontend/design phase after a v11->v14 upgrade. Use when making an upgraded TYPO3 site look like its old/live counterpart, when doing per-page visual parity against a reference URL, when content that exists in the DB isn't rendering after a v11->v14 migration, or when customizing a t3bootstrap sitepackage's templates/SCSS/settings. Covers: the Playwright compare loop (computed style + CSS rule), the settings-vs-SCSS decision, recurring structural fixes (stranded colPos, missing templateLayout partials, template partialRootPaths precedence/shadowing, on-demand component CSS, unregistered CTypes), a full visual-parity checklist (layout/width, typography, colors, links/buttons, equal-sizing, icons, borders, footer, header/nav, hero carousel), and cache-safe techniques (full-bleed bands, image-border restyle, responsive crop variants, client-side randomisation, FAL-via-DataHandler). Assumes the site already boots on v14 (see the v11->v14 upgrade skill)." +description: "Match a TYPO3 v14 t3bootstrap-based build (local DDEV) to a reference LIVE site page by page — the frontend/design phase after a v11->v14 upgrade. Use when making an upgraded TYPO3 site look like its old/live counterpart, when doing per-page visual parity against a reference URL, when content that exists in the DB isn't rendering after a v11->v14 migration, or when customizing a t3bootstrap sitepackage's templates/SCSS/settings. Covers: the Playwright compare loop (computed style + CSS rule), the settings-vs-SCSS decision, the t3b_core spacing system (spacing.yaml / tx_t3b_spacing) and why spacing must never be fixed in SCSS, recurring structural fixes (stranded colPos, missing templateLayout partials, template partialRootPaths precedence/shadowing, on-demand component CSS, unregistered CTypes), a full visual-parity checklist (layout/width, typography, colors, links/buttons, equal-sizing, icons, borders, footer, header/nav, hero carousel), and cache-safe techniques (full-bleed bands, image-border restyle, responsive crop variants, client-side randomisation, FAL-via-DataHandler). Assumes the site already boots on v14 (see the v11->v14 upgrade skill)." metadata: author: Wappler - version: "1.2" + version: "1.3" --- # TYPO3 v14 t3bootstrap — live-design parity @@ -64,6 +64,61 @@ placeholders below from the site you're matching; keep a per-project log of what --- +## Spacing (margin/padding) — a THIRD place, and NEVER your SCSS partial +`t3b_core` ships an **editor-facing** spacing system. Writing a spacing fix into your custom SCSS +silently disables it for that element — this is the single easiest way to break the backend field +without any error appearing. + +**Where spacing is resolved**, weakest → strongest: +1. `EXT:t3b_core/Configuration/Yaml/Spacing.yaml` — the steps (`none/xs/s/m/l/xl/xxl`, rem values) + and global defaults (typically `padding_top`/`padding_bottom` = `l`). +2. `config/sites//spacing.yaml` — per site, itself a cascade: + `defaults:` → `first:` / `last:` (position in the column) → `ctypes.:` → + `containers.:` (each of the latter two may carry its own `defaults/first/last`). + Field keys: `padding_{top,right,bottom,left}`, `margin_{top,bottom}`. Values: a step key, or a + per-breakpoint map. There is also a backend module that writes this file. +3. `tt_content.tx_t3b_spacing` — per element, TCA `type: json`, rendered as the "Spacing/Abstände" + box-model palette: `{"padding_top":"none"}` or `{"padding_top":{"xs":"none","md":"l"}}`. + +All of it ends up as `t3b-{p,m}{t,r,b,l}-` utility classes on the frame element. + +- **THE TRAP.** A rule such as + `.page-content > .frame-type-header:first-child + .frame { padding-top: 0 }` has specificity + (0,4,0) and beats the utility class `.t3b-pt-l` (0,1,0). The editor then picks a spacing step and + **nothing happens** — no warning, the field simply appears broken. Confirm by simulating an editor: + swap the class in the browser to the strongest step and read the computed value; if it stays put, + a CSS rule is winning. → Express spacing in `spacing.yaml` (defaults) or `tx_t3b_spacing` + (exceptions), never in the SCSS partial. +- **Positional rules leak into containers.** `first`/`last` is computed per + `(pid, colPos, language, tx_container_parent)`, so a `ctypes..first` rule ALSO matches elements + that are first inside a *container column*. Measure the blast radius before writing the rule: + `SELECT parent.CType, COUNT(*) FROM tt_content c JOIN tt_content parent ON parent.uid=c.tx_container_parent + WHERE c.CType='' AND c.deleted=0 AND c.tx_container_parent>0 GROUP BY parent.CType;` + Neutralise with `containers..first:` re-asserting the extension defaults (harmless + for other CTypes, since it only restates what they already inherit). +- **The system has no notion of "has a background".** The same frame padding is dead whitespace on a + plain element but becomes the *inner padding of a band* once the element carries a `bg-*` class — + so one positional default cannot serve both, and requirements like "less gap under the page title" + and "more gap inside the grey box" only *look* contradictory. Keep the default, and set the + exception per element (`{"padding_top":"none"}`) — it stays visible and editable in the backend. + Find the elements needing it (first element after a page-title header, no band class): + `… WHERE c1.CType='header' AND c1.colPos=0 AND c2.element_classes NOT LIKE '%bg-%' …` — do this + before estimating effort, the count is usually far smaller than it looks. +- **When SCSS IS still correct:** the spacing system works per content ELEMENT, never per column. A + two-column element where one column must stay flush (a background-media image) while the other + needs an inset can only be solved in CSS — target the inner column (e.g. `.ce-bodytext`), not the + frame, so you are not overriding anything the editor could have set. +- **Verify from the emitted markup, not the rendering:** + `curl -s "?cb=$RANDOM" | grep -o 't3b-pt-[a-z]*'`. `spacing.yaml` is read at render time and + the result is page-cached → `cache:flush` after editing it, and mind the browser's cached + `main.css` (see the cache section). + +**General principle this is an instance of:** when a theme offers an editor-facing control for +something, configure *that* control; a CSS override of it is invisible to the editor, outranks their +input, and turns a self-service setting into a support ticket. + +--- + ## Layer 1 — Structural fixes (content that won't render). Do these FIRST. These are v11→v14 migration artifacts, not design; they recur across many pages.