Skip to content

Instantly share code, notes, and snippets.

@maltesa
Last active July 18, 2022 16:16
Show Gist options
  • Select an option

  • Save maltesa/7a866131ec824180daf536f38dc849e1 to your computer and use it in GitHub Desktop.

Select an option

Save maltesa/7a866131ec824180daf536f38dc849e1 to your computer and use it in GitHub Desktop.
Custom Image component using images.weserv.nl
/* eslint-disable jsx-a11y/alt-text */
/* eslint-disable @next/next/no-img-element */
import type { DetailedHTMLProps, ImgHTMLAttributes } from 'react'
interface OptimizationOptions {
width: number
height?: number
dpr?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8
format?: 'png' | 'jpg' | 'webp'
}
function optimized(src: string, { width, height, dpr, format }: OptimizationOptions) {
const encodedSrc = encodeURIComponent(src)
let url = `https://images.weserv.nl/?url=${encodedSrc}&w=${width}`
if (height) url = `${url}&h=${height}&fit=cover&a=attention`
if (dpr) url = `${url}&dpr=${dpr}`
if (format) url = `${url}&output=${format}`
return url
}
type HTMLImagePropsWithoutSrc = Omit<
DetailedHTMLProps<ImgHTMLAttributes<HTMLImageElement>, HTMLImageElement>,
'src'
>
interface Props extends HTMLImagePropsWithoutSrc {
src: string
width?: number // Should be the maximum width the image is displayed at
height?: number
responsive?: boolean
}
export function CustomImage({
src,
width = 1280,
height,
responsive = true,
loading = 'lazy',
...imgProps
}: Props) {
const isPng = src.endsWith('.png')
const fallbackFormat = isPng ? 'png' : 'jpg'
const fallbackSrc = optimized(src, { width, height, format: fallbackFormat })
return (
<picture>
<PrimarySources src={src} width={width} height={height} responsive={responsive} />
<source srcSet={fallbackSrc} type={fallbackFormat} />
<img src={fallbackSrc} width={width} height={height} loading={loading} {...imgProps} />
</picture>
)
}
interface PrimarySourcesProps {
src: string
width: number
height?: number
responsive: boolean
}
function PrimarySources({ src, width, height, responsive }: PrimarySourcesProps) {
if (src.endsWith('.svg')) {
return <source srcSet={src} type="image/svg+xml" />
} else if (!responsive) {
const webpUrl = optimized(src, { width, height, format: 'webp' })
return <source srcSet={`${webpUrl}`} type="image/webp" />
} else {
const widthSm = Math.round(width / 2)
const heightSm = height && Math.round(height / 2)
const widthMd = Math.round(width / 1.5)
const heightMd = height && Math.round(height / 1.5)
const webpUrlSm = optimized(src, { width: widthSm, height: heightSm, format: 'webp' })
const webpUrlMd = optimized(src, { width: widthMd, height: heightMd, format: 'webp' })
const webpUrlXl = optimized(src, { width, height, format: 'webp' })
const webpUrlSm2x = optimized(src, { width: widthSm, height: heightSm, format: 'webp', dpr: 2 })
const webpUrlMd2x = optimized(src, { width: widthMd, height: heightMd, format: 'webp', dpr: 2 })
const webpUrlXl2x = optimized(src, { width, height, format: 'webp', dpr: 2 })
return (
<>
<source
media="(max-width: 640px)"
srcSet={`${webpUrlSm} 1x, ${webpUrlSm2x} 2x`}
type="image/webp"
/>
<source
media="(max-width: 768px)"
srcSet={`${webpUrlMd} 1x, ${webpUrlMd2x} 2x`}
type="image/webp"
/>
<source srcSet={`${webpUrlXl} 1x, ${webpUrlXl2x} 2x`} type="image/webp" />
</>
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment