-
Notifications
You must be signed in to change notification settings - Fork 1
Appropriate image sizing #867
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Phase 1 of image optimization strategy (#563): - Fix sizes prop in ImageMedia: change from invalid `w` unit to valid `px` - Add 100vw fallback for viewports larger than breakpoints - Reduce quality from 100 to 80 (industry standard compression) - Add optional quality prop for per-component overrides - Apply same fixes to AvatarImageMedia component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Only keep thumbnail size (300px) for admin panel and site icons. Removes 6 unused sizes (square, small, medium, large, xlarge, og) that were being generated but never used - Next.js handles responsive images via its Image component instead. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add explicit size hints to ImageMedia components so browsers request appropriately sized images. Components updated: - PostPreview: (max-width: 768px) 100vw, 320px - ImageLinkGrid: (max-width: 640px) 100vw, (max-width: 1024px) 50vw, 25vw - ImageText: (max-width: 768px) 100vw, 33vw - MediaBlock: dynamic sizes based on imageSize prop - Header banner/logo: 200px - Footer logo: 200px Phase 3 of image optimization strategy (gh-563). Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…rate image sizing - Add container max-widths to cssVariables.js as single source of truth - Update tailwind.config.mjs to use shared breakpoints and container sizes - Calculate precise sizes attributes in ImageLinkGrid based on column count - Calculate sizes for ImageText based on 4/12 column ratio - Use breakpoint variables in MediaBlock for consistency - Add aspect-ratio-based size calculation for Header/Footer logos - Add proper type guard for logo in Footer component Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…e loading - Add sizes prop to landing page tenant logos (192px fixed) - Add getImageSizes() helper for ImageQuote block (handles md breakpoint and 4/12 column ratio) - Add getImageSizes() helper for ImageTextList block (handles full vs side layout, column count) - Add sizes to SponsorsBlock components (Banner, Carousel, Static) - Add sizes to EventPreview and EventPreviewSmallRow components - Add sizes to PostPreviewSmallRow component - Create getImageWidthFromMaxHeight utility for height-constrained images - Refactor Header, MobileNav, and Footer to use new utility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Migration Safety CheckFound 78 potential issues: 20260115_234107_remove_image_sizes.ts Warning (line 5): DROP keyword detected - review for data loss await db.run(sql`DROP INDEX \`media_sizes_square_sizes_square_filename_idx\`;`)Warning (line 6): DROP keyword detected - review for data loss await db.run(sql`DROP INDEX \`media_sizes_small_sizes_small_filename_idx\`;`)Warning (line 7): DROP keyword detected - review for data loss await db.run(sql`DROP INDEX \`media_sizes_medium_sizes_medium_filename_idx\`;`)Warning (line 8): DROP keyword detected - review for data loss await db.run(sql`DROP INDEX \`media_sizes_large_sizes_large_filename_idx\`;`)Warning (line 9): DROP keyword detected - review for data loss await db.run(sql`DROP INDEX \`media_sizes_xlarge_sizes_xlarge_filename_idx\`;`)Warning (line 10): DROP keyword detected - review for data loss await db.run(sql`DROP INDEX \`media_sizes_og_sizes_og_filename_idx\`;`)Warning (line 11): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_url\`;`)Warning (line 11): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_url\`;`)Warning (line 12): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_width\`;`)Warning (line 12): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_width\`;`)Warning (line 13): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_height\`;`)Warning (line 13): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_height\`;`)Warning (line 14): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_mime_type\`;`)Warning (line 14): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_mime_type\`;`)Warning (line 15): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_filesize\`;`)Warning (line 15): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_filesize\`;`)Warning (line 16): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_filename\`;`)Warning (line 16): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_square_filename\`;`)Warning (line 17): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_url\`;`)Warning (line 17): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_url\`;`)Warning (line 18): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_width\`;`)Warning (line 18): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_width\`;`)Warning (line 19): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_height\`;`)Warning (line 19): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_height\`;`)Warning (line 20): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_mime_type\`;`)Warning (line 20): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_mime_type\`;`)Warning (line 21): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_filesize\`;`)Warning (line 21): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_filesize\`;`)Warning (line 22): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_filename\`;`)Warning (line 22): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_small_filename\`;`)Warning (line 23): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_url\`;`)Warning (line 23): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_url\`;`)Warning (line 24): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_width\`;`)Warning (line 24): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_width\`;`)Warning (line 25): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_height\`;`)Warning (line 25): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_height\`;`)Warning (line 26): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_mime_type\`;`)Warning (line 26): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_mime_type\`;`)Warning (line 27): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_filesize\`;`)Warning (line 27): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_filesize\`;`)Warning (line 28): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_filename\`;`)Warning (line 28): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_medium_filename\`;`)Warning (line 29): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_url\`;`)Warning (line 29): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_url\`;`)Warning (line 30): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_width\`;`)Warning (line 30): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_width\`;`)Warning (line 31): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_height\`;`)Warning (line 31): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_height\`;`)Warning (line 32): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_mime_type\`;`)Warning (line 32): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_mime_type\`;`)Warning (line 33): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_filesize\`;`)Warning (line 33): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_filesize\`;`)Warning (line 34): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_filename\`;`)Warning (line 34): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_large_filename\`;`)Warning (line 35): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_url\`;`)Warning (line 35): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_url\`;`)Warning (line 36): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_width\`;`)Warning (line 36): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_width\`;`)Warning (line 37): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_height\`;`)Warning (line 37): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_height\`;`)Warning (line 38): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_mime_type\`;`)Warning (line 38): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_mime_type\`;`)Warning (line 39): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_filesize\`;`)Warning (line 39): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_filesize\`;`)Warning (line 40): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_filename\`;`)Warning (line 40): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_xlarge_filename\`;`)Warning (line 41): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_url\`;`)Warning (line 41): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_url\`;`)Warning (line 42): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_width\`;`)Warning (line 42): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_width\`;`)Warning (line 43): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_height\`;`)Warning (line 43): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_height\`;`)Warning (line 44): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_mime_type\`;`)Warning (line 44): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_mime_type\`;`)Warning (line 45): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_filesize\`;`)Warning (line 45): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_filesize\`;`)Warning (line 46): DROP keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_filename\`;`)Warning (line 46): ALTER keyword detected - review for data loss await db.run(sql`ALTER TABLE \`media\` DROP COLUMN \`sizes_og_filename\`;`)Review these patterns and add backup/restore logic if needed. See |
|
Preview deployment: https://image-optimization-updates.preview.avy-fx.org |
rchlfryn
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall looks good! This will be wonderful to have cleaned up. Approving but have a few comments that I am curious what you think
src/app/(frontend)/page.tsx
Outdated
| > | ||
| <div className="aspect-square flex items-center justify-center w-48 mx-auto"> | ||
| <ImageMedia resource={logo} imgClassName="w-48" /> | ||
| <ImageMedia resource={logo} imgClassName="w-48" size="192px" /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am confused what size is actually doing here.. I would have expected it to define one size for next to return, but it still looks like it returns a srcset of image sizes
I guess I am learning no matter the size defined (single or an array), next image will always produce srcset.
I wonder if it is worth it to update ImageMedia to use a regular img tag if we define a size.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea great question. And I had to double check myself on this.
Firstly, size is confusing so I just changed that to reflect the actual attribute name: sizes. 6fba3b0
Next.js always generates the srcset which is basically a list of possible images for the browser to download. The sizes attribute indicates which one of those to pick from.
Some good reading:
- https://developer.mozilla.org/en-US/docs/Web/HTML/Guides/Responsive_images#resolution_switching_different_sizes
- https://css-tricks.com/a-guide-to-the-responsive-images-syntax-in-html/#aa-using-srcset-w-sizes
- https://nextjs.org/docs/app/api-reference/components/image#sizes
Re: using a regular img tag - we still want to use NextImage to get optimized images.
Description
This PR removes unused sizes generated by Payload, only keeping the thumbnail size for a more performant Payload admin panel experience. It then adds appropriate sizes (i.e. srcset) attributes for every usage of next/image in our codebase (let me know if I missed any!).
Related Issues
Fixes #563
Key Changes
sizesprop to all ImageMedia usages across the codebasecssVariables.jsas single source of truthsizesprop formula in ImageMedia/AvatarImageMedia (was usingwunits incorrectly)getImageWidthFromMaxHeightutility for height-constrained images (Header, Footer, MobileNav, Carousel)How to test
<img>srcsetattributes for various components to see the size the browser loadsScreenshots / Demo video
Migration Explanation
Removed image sizes from Media collection. These were already unused - we were already only using next.js image optimization.