diff --git a/web/public/assets/graphics/grisemonster-1280.png b/web/public/assets/graphics/grisemonster-1280.png new file mode 100644 index 0000000..f1324a2 Binary files /dev/null and b/web/public/assets/graphics/grisemonster-1280.png differ diff --git a/web/public/assets/graphics/grisemonster-2048.png b/web/public/assets/graphics/grisemonster-2048.png new file mode 100644 index 0000000..fee56b4 Binary files /dev/null and b/web/public/assets/graphics/grisemonster-2048.png differ diff --git a/web/public/assets/graphics/grisemonster-800.png b/web/public/assets/graphics/grisemonster-800.png new file mode 100644 index 0000000..0c1101d Binary files /dev/null and b/web/public/assets/graphics/grisemonster-800.png differ diff --git a/web/public/assets/graphics/grisemonster-note.txt b/web/public/assets/graphics/grisemonster-note.txt new file mode 100644 index 0000000..ec1983d --- /dev/null +++ b/web/public/assets/graphics/grisemonster-note.txt @@ -0,0 +1,51 @@ +grisemonster image variants +=========================== + +Source: grisemonster-lossless-original.png (2048x1024 RGBA PNG, 2.0M) + +Files in use +------------ +grisemonster-2048.png 443K desktop (>1280px viewport) +grisemonster-1280.png 227K tablet (601-1280px) +grisemonster-800.png 97K mobile (<=600px) + +The previous single grisemonster.png was 624K served to every device. +Mobile now downloads 97K (-84%); desktop downloads 443K (-29%). + +How they were generated +----------------------- +For each width W in {2048, 1280, 800}: + + magick grisemonster-lossless-original.png -resize ${W}x base.png + pngquant 64 --quality=50-80 --speed 1 --output grisemonster-${W}.png base.png + oxipng -o max --strip safe grisemonster-${W}.png + +pngquant reduces to a 64-colour palette (the image is a flat +illustration with very few distinct colours, so this is visually +lossless at the displayed scale). oxipng then does a lossless +re-encode pass to squeeze the PNG further. + +Wired up in src/components/layout/footer.module.scss via two +min-width media queries on `.pigPattern`'s background-image. + +Why PNG, not WebP/AVIF +---------------------- +Tested at 2048 width: + + PNG (pngquant 64 + oxipng) 443K <-- chosen + PNG (pngquant 256 + oxipng) 522K + AVIF q50 493K + AVIF q60 598K + AVIF q75 718K + WebP q75 829K larger than current PNG + WebP q85 903K larger than current PNG + WebP lossless 1.0M larger than current PNG + +For this kind of content -- a flat, limited-palette illustration with +large transparent regions -- palette PNG is the smallest format. +WebP and AVIF are tuned for photographic content and lose to a +well-quantised PNG here. Visual quality of the three PNG/AVIF options +above was indistinguishable at the rendered scale. + +Conclusion: the win came from responsive sizing, not from changing +format. Stayed on PNG to keep the CSS simple (no image-set() needed). diff --git a/web/public/assets/graphics/grisemonster.png b/web/public/assets/graphics/grisemonster.png deleted file mode 100644 index 39bc602..0000000 Binary files a/web/public/assets/graphics/grisemonster.png and /dev/null differ diff --git a/web/src/components/layout/footer.module.scss b/web/src/components/layout/footer.module.scss index 4e62c86..e514665 100644 --- a/web/src/components/layout/footer.module.scss +++ b/web/src/components/layout/footer.module.scss @@ -101,7 +101,7 @@ .pigPattern { background-color: var(--color-background); - background-image: url("/assets/graphics/grisemonster.png"); + background-image: url("/assets/graphics/grisemonster-800.png"); background-size: 100% auto; background-position: 0 100%; background-attachment: fixed; @@ -111,6 +111,14 @@ position: relative; z-index: 700; + @media (min-width: 601px) { + background-image: url("/assets/graphics/grisemonster-1280.png"); + } + + @media (min-width: 1281px) { + background-image: url("/assets/graphics/grisemonster-2048.png"); + } + @media (orientation: landscape) { background-size: 100% auto; } @@ -142,7 +150,7 @@ } .visit { grid-column: span 1; - + .visitContent { display: flex; flex-wrap: wrap; @@ -154,7 +162,7 @@ min-width: 12rem; } } - + } .social { ul { @@ -172,4 +180,4 @@ padding-right: 2rem; } } -} \ No newline at end of file +}