Notes from working effectively with Images

Just a guy who loves to write code and watch anime.
These are my notes from working with images.
Aspect Ratio and rendering images
You have a list of images e.g. search results. You wanna render them nicely.
You can use a grid here.
To pseudo code this quickly with html and tailwind:
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="relative overflow-hidden rounded-lg bg-gray-100">
<div className="relative aspect-square w-full">
<img
srcSet={`${image.urls.small} 400w, ${image.urls.regular} 1080w`}
sizes="(min-width: 1024px) 33vw, 100vw"
className="absolute inset-0 w-full h-full object-cover"
/>
</div>
</div>
</div>
We're gonna dive into srcset and sizes in a bit.
The first div -> This is the grid container. Tells how many columns we want.
The second div -> This is the grid item. It's width will be based on the viewport width. If three columns and viewport is 1000px, each column will be 333px.
The third div -> This is the image container. This is one of the common gotchas. We need this extra container to set the aspect ratio. This element will take full width and based on the aspect ratio, the height will be set. This is super neat because with this structure, width is basically due to the grid and grid item, but the height is set by the aspect ratio. In human words, aspect ratio will go "Ok, you gave me my width, let me adjust my height accordingly".
The img tag -> This is the image. It will take the full width and height of the image container. absolute and inset-0 will make it take the full width and height of the image container. object-cover will make the image cover the full container and keep its aspect ratio.
Figure element
Figure element is a semantic element that is used to wrap media content like images, videos, and other media. It's used to provide additional information about the content and make it easier for screen readers to understand.
Blur hash
When you get the an image from the server, the URL, you still have to download the image.
While the image is downloading, you can show a blurred version of the image. This blurred version is created by the server. You may get something like blur_hash: {hashed string} from the server. You would then decode this hash to get the blurred image. Blurred image has similar dimensions and colors as the original image. So when the original image is downloaded, it comes in nicely:
<div className="relative overflow-hidden rounded-lg bg-gray-100">
{/* Aspect ratio container */}
<div className="relative aspect-[3/2] w-full">
{/* Blur hash placeholder */}
{/* `inset-0` in combination with `absolute` makes the element take full width and height of the parent */}
<div className="absolute inset-0">
<Blurhash
hash={image.blur_hash}
width="100%"
height="100%"
resolutionX={32}
resolutionY={32}
punch={1}
/>
</div>
{/* Main image */}
<img
srcSet={`
${image.urls.small} 400w,
${image.urls.regular} 1080w
`}
sizes="(min-width: 1024px) 33vw,
(min-width: 768px) 50vw,
100vw"
src={image.urls.small} // Fallback for older browsers
alt={image.description || "Unsplash photo"}
className="absolute inset-0 w-full h-full object-cover"
loading="lazy"
/>
</div>
</div>
Device Pixel Ratio (DPR)
This is super interesting. Have you ever wondered why images look so crisp and sharp e.g. beyond full hd as 4k?
This boils down to the device pixel ratio. The higher the device pixel ratio, the more pixels the image will have. This is dependent on the device you're on.
This is why not all displays support 4k for example.
srcSet and sizes
sizes -> For each viewport width and above, tell browser how wide the image will roughly be. Browser uses the image width to then understand how much pixels will be needed depending on the DPR.
srcset -> Tell browser the images you have and their widths.
srcSet={`
${image.urls.small} 400w, // "I have a 400-pixel wide version"
${image.urls.regular} 1080w // "I have a 1080-pixel wide version"
`}
sizes="(min-width: 1024px) 33vw, // "On big screens, image takes 33% of viewport"
(min-width: 768px) 50vw, // (not applicable here)
100vw" // (not applicable here)
// Browser's thinking process:
1. "Viewport is 1600px wide"
2. "First sizes condition matches (> 1024px), so image will take 33vw"
3. "33% of 1600px = 533px - this is how wide the image will display"
4. "Device has 2x pixel ratio, so I actually need 1066 pixels (533 × 2)"
5. "Looking at my options (400w or 1080w), I'll choose 1080w"
// 400w would give blurry image (too small)
// 1080w is perfect - slightly larger than needed but will look crisp






