diff --git a/src/layouts/Base.astro b/src/layouts/Base.astro index 3d335e5..9626d1e 100644 --- a/src/layouts/Base.astro +++ b/src/layouts/Base.astro @@ -165,6 +165,14 @@ const jsonLd = { ); document.querySelectorAll('.reveal').forEach((el) => observer.observe(el)); + // Past the bottom of the page, the footer's colour rather than the theme's. + const footer = document.querySelector('footer'); + if (footer) { + new IntersectionObserver(([entry]) => + document.documentElement.classList.toggle('at-end', entry.isIntersecting), + ).observe(footer); + } + // Besides page views, GoatCounter counts what a visitor came for: a PDF // downloaded (CV, thesis), an email started, or a link followed out. declare global { diff --git a/src/styles/global.css b/src/styles/global.css index 0987824..600fc47 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -106,6 +106,15 @@ html { scroll-behavior: smooth; scroll-padding-top: 80px; + /* What a browser shows past the page's edges: behind Safari's toolbar on + iPhone, and when a scroll bounces. The theme's background at the top, the + footer's green once the footer is on screen (set in Base.astro), so the + page never ends on a band of another colour. */ + background: var(--bg); +} + +html.at-end { + background: var(--closing); } body { diff --git a/tests/site.spec.ts b/tests/site.spec.ts index 50204d5..6229ca8b 100644 --- a/tests/site.spec.ts +++ b/tests/site.spec.ts @@ -238,6 +238,21 @@ test('starts the name near the top on a phone, under a navigation that floats', await expect(page.locator('#nav')).not.toHaveCSS('background-color', 'rgba(0, 0, 0, 0)'); }); +test("paints past the page's edges in the theme's colour, then the footer's", async ({ page }) => { + await page.goto('/'); + const html = page.locator('html'); + const background = (selector: string) => + page.locator(selector).evaluate((el) => getComputedStyle(el).backgroundColor); + + // At the top, what shows past the edge matches the page. + expect(await background('html')).toBe(await background('body')); + + // At the bottom, behind Safari's toolbar, it matches the footer. + await page.locator('footer').scrollIntoViewIfNeeded(); + await expect(html).toHaveClass(/at-end/); + await expect(html).toHaveCSS('background-color', await background('footer')); +}); + test('counts the visit, and the CV, the thesis, an email and a link out', async ({ page }) => { // A stand-in for GoatCounter's script, which records what it is given. await page.route('https://gc.zgo.at/count.js', (route) =>