diff --git a/web/next.config.mjs b/web/next.config.mjs index 2170784..3ffcc6c 100644 --- a/web/next.config.mjs +++ b/web/next.config.mjs @@ -25,6 +25,9 @@ const nextConfig = { images: { remotePatterns: remotePatterns(), formats: ["image/avif", "image/webp"], + // 90 is for editorial images (ImageFigure); AVIF at the default 75 is + // visibly soft on photos. Qualities not listed here are rejected. + qualities: [75, 90], minimumCacheTTL: 7 * 24 * 60 * 60, // 7 days // smoke tests build in production mode against a mock CMS on 127.0.0.1; // the flag is serialized into the build, so it must be set at build time diff --git a/web/src/components/blocks/ImageWithTextBlock.tsx b/web/src/components/blocks/ImageWithTextBlock.tsx index 313e83f..b36d5c1 100644 --- a/web/src/components/blocks/ImageWithTextBlock.tsx +++ b/web/src/components/blocks/ImageWithTextBlock.tsx @@ -13,6 +13,15 @@ const ImageWithTextBlockFragmentDefinition = graphql(` } `); +// "original" is left out: it renders at its intrinsic size, where next/image's +// default 1x/2x srcset is the right one. +const IMAGE_FORMAT_SIZES: Record = { + bleed: "100vw", + // viewport minus --spacing-sitepadding-inline on both sides + fullwidth: + "(min-width: 1800px) calc(100vw - 20rem), (min-width: 1400px) calc(100vw - 12rem), (max-width: 600px) calc(100vw - 2rem), calc(100vw - 4rem)", +}; + export function ImageWithTextBlock({ block, }: { @@ -28,6 +37,7 @@ export function ImageWithTextBlock({ attribution={image.attribution} caption={block.text} imageFormat={block.imageFormat} + sizes={IMAGE_FORMAT_SIZES[block.imageFormat]} /> ); } diff --git a/web/src/components/general/Image.tsx b/web/src/components/general/Image.tsx index 6c44408..ac3e92b 100644 --- a/web/src/components/general/Image.tsx +++ b/web/src/components/general/Image.tsx @@ -35,7 +35,7 @@ export function ImageFigure(props: ImageProps) { className={`${styles.image} ${imageFormat ? styles[imageFormat] : ""}`} >
- + {attribution &&
{attribution}
}
{caption &&
{caption}
}