Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions src/blocks/InlineMedia/Component.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import type { InlineMediaBlock } from '@/payload-types'

import { Media } from '@/components/Media'
import { cssVariables } from '@/cssVariables'
import { cn } from '@/utilities/ui'

const { breakpoints } = cssVariables

type Props = Omit<InlineMediaBlock, 'blockType' | 'id'>

const widthClasses = {
Expand All @@ -19,6 +22,15 @@ const verticalAlignClasses = {
baseline: 'align-baseline',
}

// Maps percentage width to a sizes attribute, using container-relative pixel
// estimates so the browser picks an appropriately sized image in narrow containers.
const sizesForWidth: Record<string, string> = {
'25': `(max-width: ${breakpoints.sm}px) 25vw, 192px`, // ~25% of a ~768px container
'50': `(max-width: ${breakpoints.sm}px) 50vw, 384px`, // ~50% of a ~768px container
'75': `(max-width: ${breakpoints.sm}px) 75vw, 576px`, // ~75% of a ~768px container
'100': `(max-width: ${breakpoints.sm}px) 100vw, 768px`, // full container width
}

type WidthSize = keyof typeof widthClasses

function isWidthSize(size: string): size is WidthSize {
Expand Down Expand Up @@ -50,8 +62,7 @@ export const InlineMediaComponent = ({
} else if (isWidthSize(resolvedSize)) {
sizeClass = widthClasses[resolvedSize]
imgSizeClass = 'w-full h-auto'
// Approximate sizes hint for responsive images
sizes = `${resolvedSize}vw`
sizes = sizesForWidth[resolvedSize] ?? '100vw'
} else if (isFixedHeight) {
imgSizeClass = 'h-full w-auto'
sizes = '96px'
Expand Down
19 changes: 11 additions & 8 deletions src/blocks/Media/Component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,16 @@ export const MediaBlockComponent = (props: Props) => {
const bgColorClass = `bg-${backgroundColor}`
const textColor = getTextColorFromBgColor(backgroundColor)

// Container query breakpoints (@sm, @md, @lg) so sizing tracks the parent
// container width rather than the viewport, e.g. when embedded in a post layout.
const getImageSizeClasses = () => {
switch (imageSize) {
case 'small':
return 'max-w-xs md:max-w-sm lg:max-w-md'
return 'max-w-xs @sm:max-w-sm @lg:max-w-md'
case 'medium':
return 'max-w-sm md:max-w-lg lg:max-w-2xl'
return 'max-w-sm @sm:max-w-lg @lg:max-w-2xl'
case 'large':
return 'max-w-md md:max-w-2xl lg:max-w-4xl'
return 'max-w-md @sm:max-w-2xl @lg:max-w-4xl'
case 'full':
return 'max-w-full'
case 'original':
Expand All @@ -52,16 +54,16 @@ export const MediaBlockComponent = (props: Props) => {
}
}

// sizes prop hints to browser what image width to request based on imageSize setting
// Uses breakpoints from cssVariables for consistency with other image components
// Hints the image width to request, using conservative estimates based on the
// container size the block actually occupies rather than the full viewport.
const getSizesForImageSize = () => {
switch (imageSize) {
case 'small':
return `(max-width: ${breakpoints.md}px) 100vw, 384px` // max-w-sm = 24rem = 384px
return `(max-width: ${breakpoints.sm}px) 100vw, 384px` // small caps at max-w-md = 28rem = 448px
case 'medium':
return `(max-width: ${breakpoints.md}px) 100vw, 672px` // max-w-2xl = 42rem = 672px
return `(max-width: ${breakpoints.sm}px) 100vw, 672px` // medium caps at max-w-2xl = 42rem = 672px
case 'large':
return `(max-width: ${breakpoints.md}px) 100vw, 896px` // max-w-4xl = 56rem = 896px
return `(max-width: ${breakpoints.sm}px) 100vw, 896px` // large caps at max-w-4xl = 56rem = 896px
case 'full':
return '100vw'
case 'original':
Expand All @@ -75,6 +77,7 @@ export const MediaBlockComponent = (props: Props) => {
<div
className={cn(
isLayoutBlock && 'container py-10',
'@container',
'flex flex-col',
alignContent === 'left' && 'items-start',
alignContent === 'center' && 'items-center',
Expand Down
Loading