From 40a25c160d259dc779067629349f0da2b7976a68 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 15:03:59 +0000 Subject: [PATCH] Stop the frame jumping when a reader switches page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The bar landed on three pages that centre in three different containers - 64rem here, 1180px on Learn, 62rem on Controls - so the brand, the heading and the first card moved sideways on every switch. Three widths read as three sites, which is the opposite of what a shared bar is for. One column now: 1180px with a 24px gutter, so 1132px of content on all three. The masthead joins the bar as a shared block - the full-bleed header, its .inner, the eyebrow, the h1 scale and the lede - so this page gains the gradient band the learning path already had. Only the words differ now; the note about the missing playground button and the smaller lede the packages section uses are still this page's own. gives up its side padding, because the gutter has to belong to the containers for a full-bleed header to reach the window edge. --wide stops being 64rem and becomes that one column. The block no longer reads --family-* tokens. With one column everywhere there is nothing left for a page to vary, so it carries the two numbers itself and is self-contained - one less way for a copy to drift. Two things the measuring turned up: the eyebrow was uppercased, so every page shouted ABAP2UI5, which is the one place a page must not get its own name wrong; and the results grid asked for a 23rem minimum track, which a 390px screen cannot give once the gutter is 24px - it pushed the page 2px sideways, and every card grid here now guards its minimum with min(…, 100%). Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_014QKMsbCiREgnpdfVvQYsa2 --- web/stack.css | 133 +++++++++++++++++++++++++++++--------------------- 1 file changed, 78 insertions(+), 55 deletions(-) diff --git a/web/stack.css b/web/stack.css index cbf32a3..0c40b4a 100644 --- a/web/stack.css +++ b/web/stack.css @@ -27,15 +27,13 @@ --warn-soft: #fdf1de; --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace; --radius: 10px; - --wide: 64rem; - /* The three measurements the shared family blocks at the end of this file - * read. They are the only thing about those blocks that is allowed to differ - * between the three sample repositories, because the three pages are built - * around containers of different widths. */ - --family-width: var(--wide); /* what .masthead and main centre in */ - --family-gutter: 0rem; /* those have no side padding of their own */ - --family-bleed: 1.25rem; /* has this much, and the bar undoes it */ + /* The container every one of the three sample pages centres in, and its + * gutter. Identical in all three - a reader switching page must not see the + * column move. The shared blocks at the end of this file hard-code the same + * two numbers; these are here for the rules above. */ + --wide: 1180px; + --gutter: 24px; } @media (prefers-color-scheme: dark) { @@ -62,7 +60,9 @@ body { margin: 0; - padding: 0 1.25rem 4rem; + /* No side padding: the gutter belongs to the containers, so the masthead and + the bar above it can run to the edge of the window like the sibling pages. */ + padding: 0 0 4rem; background: var(--bg); color: var(--ink); font: 16px/1.55 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; @@ -86,34 +86,12 @@ code { /* ------------------------------------------------------------- masthead */ -.masthead { - max-width: var(--wide); - margin: 0 auto; - padding: 2.5rem 0 1.5rem; -} +/* .masthead, .brand, h1 and .lede are shared with the two sibling pages and + live at the end of this file. What follows is this page's own: the smaller + lede the packages section uses, and the note about the missing playground + button, which neither of the others has. */ -.brand { - margin: 0 0 .35rem; - font: 600 .8rem/1 var(--mono); - letter-spacing: .04em; - text-transform: uppercase; -} -.brand a { color: var(--ink-faint); text-decoration: none; } -.brand a:hover { color: var(--accent); } - -.masthead h1 { - margin: 0 0 .5rem; - font-size: clamp(1.7rem, 4vw, 2.4rem); - line-height: 1.15; - letter-spacing: -.02em; -} - -.lede { - max-width: 46rem; - margin: 0; - color: var(--ink-soft); -} -.lede.small { font-size: .9rem; } +.lede.small { font-size: .9rem; max-width: 46rem; } .masthead .note { max-width: 46rem; @@ -124,7 +102,7 @@ code { /* --------------------------------------------------------------- panel */ -main { max-width: var(--wide); margin: 0 auto; } +main { max-width: var(--wide); margin: 0 auto; padding: 0 var(--gutter); } .panel { position: sticky; @@ -256,7 +234,7 @@ main { max-width: var(--wide); margin: 0 auto; } #results { display: grid; - grid-template-columns: repeat(auto-fill, minmax(23rem, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(min(23rem, 100%), 1fr)); gap: .9rem; } @@ -452,7 +430,7 @@ mark { #pkgcards { display: grid; - grid-template-columns: repeat(auto-fill, minmax(19rem, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr)); gap: .7rem; margin-top: 1rem; } @@ -498,7 +476,7 @@ mark { footer { max-width: var(--wide); margin: 3rem auto 0; - padding-top: 1.2rem; + padding: 1.2rem var(--gutter) 0; border-top: 1px solid var(--line); font-size: .82rem; color: var(--ink-faint); @@ -515,25 +493,28 @@ footer p { margin: .4rem 0; } /* family-nav:start * - * The bar that ties the three sample pages together, and the card strip at the - * end of the page that says why you would go next door. Both are IDENTICAL in + * The frame the three sample pages share: the bar that ties them together, the + * masthead they all sit under, and the card strip at the end. IDENTICAL in * abap2UI5/samples, abap2UI5/samples-controls and abap2UI5/samples-stack - - * change them in all three repositories or in none. `npm run check:family-nav` + * change it in all three repositories or in none. `npm run check:family-nav` * fails when a copy drifts. * - * They read three tokens each page sets for itself in :root and nothing else - * of their own: --family-width (the container the rest of the page centres - * in), --family-gutter (that container's own side padding) and --family-bleed - * (the side padding on , which the bar breaks out of to reach the edge). - * Every colour comes from the palette above, so light and dark come free. + * It is self-contained: two constants of its own (1180px, the container every + * page centres in, and its 24px gutter - so the content column is 1132px + * everywhere) and otherwise nothing but the palette above, so light and dark + * come free. Every page therefore has to leave unpadded and give its own + * containers the same 1180px/24px, or the bar and the page under it will not + * line up. + * + * That alignment is the whole point. Three pages centring in three different + * widths made the brand, the heading and the first card jump sideways on every + * switch, which reads as three sites rather than one. * * The bar is deliberately NOT sticky: two of the three pages already stick * their filter panel to the top, and a second sticky strip above it would eat * a phone screen twice over. */ .family { - margin: 0 calc(var(--family-bleed) * -1); - padding: 0 var(--family-bleed); background: var(--panel); border-bottom: 1px solid var(--line); } @@ -543,9 +524,9 @@ footer p { margin: .4rem 0; } flex-wrap: wrap; align-items: center; gap: .1rem; - max-width: var(--family-width); + max-width: 1180px; margin: 0 auto; - padding: .35rem var(--family-gutter); + padding: .35rem 24px; } .family-brand { @@ -615,6 +596,48 @@ footer p { margin: .4rem 0; } .family-brand { margin-right: .35rem; } } +/* ------------------------------------------------------------- masthead */ + +/* Shared for the same reason as the bar: a reader switching pages should see + * the words change and nothing else. Each page fills the frame with its own + * title, lede and actions - what sits BELOW the lede is the page's own + * business and is styled in its own stylesheet. */ + +.masthead { + background: linear-gradient(160deg, var(--accent-soft), transparent 70%), var(--panel); + border-bottom: 1px solid var(--line); +} +.masthead .inner { + max-width: 1180px; + margin: 0 auto; + padding: 34px 24px 30px; +} + +/* NOT uppercased. The product is written abap2UI5, and an eyebrow that + * shouts ABAP2UI5 is the one place on the page that gets its own name wrong. */ +.brand { + margin: 0 0 14px; + font: 600 .8rem/1 var(--mono); + letter-spacing: .04em; +} +.brand a { color: var(--ink-faint); text-decoration: none; } +.brand a:hover { color: var(--accent); } + +.masthead h1 { + margin: 0 0 10px; + font-size: clamp(1.7rem, 3.6vw, 2.5rem); + line-height: 1.15; + letter-spacing: -.02em; +} + +.lede { + max-width: 62ch; + margin: 0; + color: var(--ink-soft); + font-size: 1.03rem; +} +.lede strong { color: var(--ink); } + /* --------------------------------------------------------- three pages */ /* The bar at the top answers "where am I". This answers "why would I go @@ -622,12 +645,12 @@ footer p { margin: .4rem 0; } * is done with this page arrives. */ .three { - max-width: var(--family-width); + max-width: 1180px; margin: 3rem auto 0; /* A rule above it, because on one of the three pages this lands directly * under another prose section that has one, and without it the strip reads * as that section's tail rather than as its own thing. */ - padding: 1.4rem var(--family-gutter) 0; + padding: 1.4rem 24px 0; border-top: 1px solid var(--line); } .three > h2 { margin: 0 0 .3rem; font-size: 1.15rem; } @@ -640,7 +663,7 @@ footer p { margin: .4rem 0; } .three-cards { display: grid; - grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr)); gap: .7rem; }