Added photos

It sounds silly, but I spent some hours adding <img> tags to my blog, for my previous two posts. Let's write something about Open Graph metadata, alt attributes, lazy loading, async decoding, <picture> and AVIF.

My CMS (which I wrote about in Dutch 15 years ago) obviously already supported uploading images (most clients actually think that's a handy feature). But as I mentioned, every time I'm coding a new website, I get to have fun again on a new frontend, add in new things I've learned and ditch old habits.

In my CMS, each bit of content is its own structured thing, like a block. When “rendering” a page, I add in the HTML details for each “block”. This has a lot of advantages, but also brings some challenges.

Anyway, this is the HTML output I started with for an image:

<picture>
	<source type="image/avif" srcset="/_img/2026/05/cssday-2024.avif">
	<img src="/_img/2026/05/cssday-2024.jpg" width="1600" height="1066" loading="lazy" decoding="async" alt="A photo of 16 people obviously posing; 5 in the front, 11 in the back, all next to a CSS Day branded lectern. Some people in the back are holding large gold balloon letters, spelling “CSS Day”. One guy in the middle in the back is cheekingly looking through the “D”. The background shows more balloons and a large slide showing the CSS Day logo, brand and date, saying “Welcome to our 10th edition!”.">
</picture>

I used a <picture> element, which lets the browser automatically choose the right source. For that one percent of extra reach of WebP I don't think I'm going to add that format. AVIF (AV1 Image File Format) it is.

Those width and height attributes will prevent a janky layout shift once the image is loaded. Jen Simmons has a nice explanation about that. We basically add the width and height of the original image, and that's it. Well, combined with a bit of CSS:

img {
	max-inline-size: 100%;
	block-size: auto;
}

I'm trying to use logical properties more, since they're quite new for me, but in this case I don't know if I should just use max-width: 100% and height: auto, since the HTML markup doesn't use logical properties either.. Something to investigate and improve on later. Eric Portis helped me out with this, so I changed it indeed.

loading="lazy" and decoding="async" are added in automatically. For lazy loading that's not the smartest thing to do, because images are now actually loaded slower, when they're at the top of a post. loading="lazy" tells the browser's preload scanner to ignore that image. But once the pixels need to be drawn, it suddenly figures out it needs to fetch that image. That's one of the challenges I'm going to fix at some point. Maybe give certain images extra priority, which could even add a fetchpriority="high" attribute. I've fixed this just now, while adding loading="lazy" support for <video>.

On to the alt attribute. Many people think of this as a description, but it's really an alternative for that image. For when it doesn't load, or when you can't see it. Nowadays, with “AI” being able to describe images better than I possibly can, I think it's a lost cause, but I'm still holding on to my beliefs.

I'm part of the previous photo, the one cheekingly looking through the “D”. But if you don't know me, or know how I look, you wouldn't know that. An “AI” wouldn't know that. So what should the alt attribute say in this case? Should it include something like “I'm standing in the middle, looking through one of the balloons”? Then the alt attribute might have more information than the photo itself. Should it include the names of the other people then as well? What about a photo with well-known people in them, like in this post? Should that say something like “Jeremy Keith, Roel Nieskens, Sarah Dayan and Miriam Suzanne are breathing in my neck, wondering when they can leave for bitterballs”?

And the last bit, Open Graph metadata. I already added some little things, but now the first image in a post is used as an og:image:

<meta property="og:image" content="https://krijnhoetmer.nl/_img/2024/06/speech-cssday.jpg">
<meta property="og:image:type" content="image/jpeg">
<meta property="og:image:width" content="1600">
<meta property="og:image:height" content="1066">
<meta property="og:image:alt" content="I stood there; a bold dude, wearing a khaki shirt, holding a microphone somewhat confident, behind a lectern with two laptops on it. Behind me some other people—conference speakers, some wearing their lanyard—were standing and looking at me.. Maybe wondering who the hell this guy was..">

Today I learned about og:image:alt as well, and now I wonder which tools use that part.. After asking about it, Kilian told me Polypane helps you out with these sorts of things! I've used Polypane in 2020–2021—also to support Kilian—and I'm recommending it to students nowadays. Might need a new subscription again soon!

Somehow it's weird I'm picking JPG as a default here, even though AVIF support is so widespread. Since the Open Graph protocol doesn't define how “responsive images” are supposed to work there, I'm playing it safe. It would be great if alternative image formats can be shared via Open Graph metadata as well, but I'm sure someone has already figured out how this doesn't work. Or maybe it does, by picking smart defaults in the order of formats. There's no way I'm the first one to think about this, but I might experiment with this in the future.

And another thing on my todo list for this site: play around with different image sizes, especially now sizes="auto" is a thing. I've been messing with srcset and sizes a lot over at RoyalHolidays.eu, but as a hand coder, I'm really happy with this becoming much simpler!

Add a comment