diff --git a/hero.js b/hero.js index 3ff6389..13ecc74 100644 --- a/hero.js +++ b/hero.js @@ -207,11 +207,17 @@ const CSS = ` text-shadow: 0 0.12em 1.4em var(--hero-glow); } -/* Behind everything in the header (the header is a stacking context - of its own, so -1 is still above the page). */ +/* The canvas lives in the piece (everything the module adds to the + page goes inside the piece: a node added anywhere else before the + app hydrates throws the hydration off, and with it client-side + navigation) but covers the whole header: fit() sets its height to + the header's box and its top to the piece's offset in it. Behind + everything in the header: the header is a stacking context of its + own, so -1 is still above the page. */ .westra-line { position: absolute; - inset: 0; + top: 0; + left: 0; z-index: -1; width: 100%; height: 100%; @@ -338,10 +344,9 @@ class WestraHero { mark.append(a, b); this.name.append(mark); this.mark = mark; - // The canvas covers the whole sticky header, under everything - // in it; the name sits in the piece, the space above the copy. - (this.hero || container).prepend(this.canvas); - container.append(this.name); + // Both inside the piece, and nothing outside it (see .westra-line). + this.container = container; + container.append(this.canvas, this.name); this.width = 0; this.height = 1; @@ -450,6 +455,11 @@ class WestraHero { // is the fonts'. fit() { this.boxHeight = Math.max(1, this.hero ? this.hero.offsetHeight : this.height); + if (this.hero) { + const offset = this.container.getBoundingClientRect().top - this.hero.getBoundingClientRect().top; + this.canvas.style.top = -offset + 'px'; + this.canvas.style.height = this.boxHeight + 'px'; + } const dpr = window.devicePixelRatio || 1; const scale = Math.min(dpr, Math.sqrt(MAX_PIXELS / (this.width * this.boxHeight))); this.canvas.width = Math.max(1, Math.round(this.width * scale));