Instant
December 26, 2024

Another step in recapturing content: Bringing photos back in-house.
With the ongoing enshittification of the platforms we once trusted, I took another step towards untangling myself from corporate social media. I finally committed to stop posting on Instagram and return to posting my photos on my own site.
Background
After years of immersing these platforms into out digital lives, it’s unsurprisingly tedious to extract yourself from their tangled grasp. I’ve been dutifully moving certain projects off of Instagram and over to their own pages. The one big theme that is still hanging around is…the more general “photo” theme.
Design
Nothing too fancy in terms of the page design: fit into the site’s theme, basic full width grid for the photos and easy to update. Luckily, I’ve been enamored with the square aspect ratio for a while, so the layout was simple. Letting the photos stand on their own was also the point, so there’s no titles or copy to account for in the design.
Development
Since the design is so simple, I did want to add a bit of complication to the development side. I’ve been playing around with a few image gallery options, but didn’t really want to add the overhead of Javascript. Instead, I decided to use the page as an opportunity to once again tackle the image srcset property. Now, I’ve used srcset in production before with the picture element, but it’s always been confusing. In this case, I wasn’t interested in art directing the photos across viewport sizes or layouts, but merely trying to provide alternative sizes for better performance. This made adding the srcset property to the img element the best option.
As I mentioned, the spec for the property never seems to stick in my head. The production part is easy enough: create different sizes of each photo based on what size is needed in the layout for different viewports. For the code itself: add a list of source paths to the images along with media queries in the sizes attribute to give the browser a hint as to which image to use. Plus, provide a default fallback image path. It looks fairly straight forward, but there’s a bunch of interacting parts that always confuse me. Here’s my initial attempt with two image sizes for 480px wide and 720px wide. (Don’t forget the alt text either!)
<img srcset="blue-420w.webp 420w, blue-720w.webp 720w"
sizes="(max-width: 768px) calc(100vw - 4rem), calc(100vw - 6rem - 224px)"
loading="lazy" src="blue-420w.webp"
alt="A dark blue sky in the top left with the silhouette of bare trees coming in from the bottom right.">
But…once you try to test it out, things start getting more complicated. Looking at the browser dev tools as you resize the window appears to load the correct image, but it also seems to show the incorrect size when you hover over the img element. The dev tools network tab does a better job, but still doesn’t adjust on resize or provide any insight into how the browser is processing the srcset setup.
It’s worth mentioning that the other reason I started with two sizes is…laziness. The performance value of srcset (and the picture element) run up against the additional production work of creating all the different image sizes. After 14 years on Instagram, the sheer volume of photos to process is daunting. Even discounting some of the other themes and culling many photos altogether, it was a bit to much to think about at the start. Starting small, cherry picking just a few images and just tackling two sizes kept the project moving.
Right. Basic layout and images formatted and set up in the HTML. Now on to that testing conundrum. It quickly became clear that the combo of my two images sizes and the media queries weren’t really helping anything. Turns out the layout didn’t really help simplify things either. The three column layout necessitated smaller images at larger viewport widths and the one column layout (below 768px wide) required large images initially — and then smaller images as the viewport shrank. So…two layouts needing three (or more) media queries to load two (or more) image sizes. This is where my head starts to hurt and I start to think, “there should be a tool for this”.
A bit of research and luckily, I was able to find this linter for responsive images to help my debug and build better media queries. Just run the bookmark (or Chrome extension) on your page and it will run through the images and conditions to make recommendations. In looking at my page, it recommended two different sets of potential image sizes and a new set of media queries. As I suspected, it meant creating more than just two image sizes, so I relented and braced myself for more production work. I went with the more lengthy size list recommended by the linter which meant abandoning my previous two sizes. Here’s the new code:
<img srcset="blue-256w.webp 256w,
blue-609w.webp 609w,
blue-888w.webp 888w,
blue-1240w.webp 1240w,
blue-1510w.webp 1510w,
blue-1740w.webp 1740w,
blue-1940w.webp 1940w"
sizes="(min-width: 780px) calc(33.33vw - 32px),
(min-width: 380px) calc(100vw - 64px),
calc(60vw + 80px)"
loading="lazy" src="img/photos/blue-609w.webp"
alt="A dark blue sky in the top left with the silhouette of bare trees coming in from the bottom right.">
So now there are seven image sizes to pair with the three media queries. A bunch more production work indeed. This immediately took me back to using the picture element in production, i.e., creating tons of different sizes for each image. I ran the linter again and it was happy, but I’m still not satisfied with the testing scenario. I think there’s an opportunity for browsers to really clarify which condition is being met and why it’s choosing a particular image size. Maybe I just need to start using a browser just for development.
The linter did seem to get confused on a couple of occasions. The first issue occurred as I added more and more images. Using the bookmarklet in Firefox caused the linter to hang and eventually crash. I suspect it’s just trying to handle too many options and runs out of memory. Switching over to Chrome and using the extension worked fine and didn’t crash. The other issue was a bit more esoteric. For a few of the images, the linter gets confused and thinks I’m using the srcset image list for art direction (using images with different content) when I’m not.
Images in srcset attribute must not be different
It seems the image name-609w.webp doesn’t show the same contents as name-1940w.webp does, the determined difference is 5%.
This is an issue I wasn’t able to resolve. Recreating the image sizes didn’t help. I can only suspect that the linter is choking on the pixels values between the small and large sizes. Perhaps it has something to do with the compression.
From there, it was just a ton of art direction to curate the next row of images, size them all, compression, format swap, update the HTML and repeat, repeat, repeat. Perhaps at some point, I set up a Photoshop action or Automator workflow to batch process the images, but that’s another project. I think the hardest part has actually been finding the original files. I end up cross referencing my phone with my export from Instagram and various external hard drives only to often discover a specific photo is only in one or two of those locations. Sigh.
Testing & Next Steps
Looking at the PageSpeed performance and it seems like Google is happy. Here’s the desktop score. The mobile score is almost identical with only the performance score being a tiny bit lower at 94.

PageSpeed is still mad at me (naturally) as the volume of photos keeps adding up to a large payload, but whatever, it’s my page, the images are set to lazy load and hopefully visitors are taking their time to actually look at the photos. Perhaps, I’ll limit the amount of images on initial page load and add a “show more” button to reveal more. Might be a good UX update to play around with in a future update.
I’m also not sure if PageSpeed is accurately evaluating the responsive images sizes. It’s still saying I need to size the images properly. Admittedly, I will need to go back and work on the image compression again to help reduce the overall page weight. I suspect I may need to add another image size to the srcset list and adjust the media queries to handle it. I’m just not convinced its working at it’s optimal best yet. I’ll also do more extensive performance testing with other tools to get comparison metrics.
Looking ahead, there’s still many more photos to process, so like the virtual library, I’ll add this page to my monthly backlog to update as I find time. I’m sure I’ll also need to adjust the layout for photos with different aspect ratios as I’m hoping to dive back into actual film photography soon. For now, this page is just one small step ahead to reclaim my content so keep checking back to see what I post.