Fixing images in Ruby

I love the Ruby theme, but a I've been adding more and more posts to the front page, my PageSpeed number dropped - a lot. I dug into the issue and here's what I learned.

Fixing images in Ruby
📰
As you might guess from the image above, this post is about a previous version of Ruby, on a previous version of my site. It may not apply to you today if you're installing a fresh copy of Ruby – there's been a lot of change in the last year!

I love the Ruby theme, but as I added more and more posts to the front page, my PageSpeed number dropped - a lot. I dug into the issue and here's what I learned.

1) Ruby wasn't offering WEBP format. (Which means image file sizes are bigger than they need to be, which means slower loads.)

2) Ruby was not offering a srcset for featured post images. (Which meant really big images getting packed into the grid for any featured posts.)

3) Ruby was serving the biggest possible image, despite a srcset. (So the problem in #2 was a problem for all posts, although it looked like it shouldn't have been.)

Here's what I'm currently using (this is the top of partials/loop.hbs:

<article class="{{post_class}} u-shadow"{{#if primary_tag.accent_color}} style="--tag-color: {{primary_tag.accent_color}};"{{/if}}>
<a class="post-link" href="{{url}}">
    {{#if feature_image}}
        {{#if featured}}
            <img
                class="post-image u-object-fit"
                srcset="{{img_url feature_image size="s"}} 400w,
                            {{img_url feature_image size="m"}} 750w,
                            {{img_url feature_image size="l"}} 960w"
                sizes="600px"
                src="{{img_url feature_image size="m"}}"
                alt="{{title}}"
                
            >
        {{else}}
        <figure class="post-media">
            <div class="u-placeholder same-height rectangle">
                <picture class="post-image u-object-fit">
                <source 
                    srcset="{{img_url feature_image size="s" format="webp"}} 400w,
                            {{img_url feature_image size="m" format="webp"}} 750w,
                            {{img_url feature_image size="l"format="webp"}} 960w"
                    sizes="600px"
                    src="{{img_url feature_image size="m" format="webp"}}"
                    alt="{{title}}"
                    loading="lazy"
                    type="image/webp"
                    >
                <img
                    class="post-image u-object-fit"
                    srcset="{{img_url feature_image size="s"}} 400w,
                            {{img_url feature_image size="m"}} 750w,
                            {{img_url feature_image size="l"}} 960w"
                    sizes="600px"
                    src="{{img_url feature_image size="m"}}"
                    alt="{{title}}"
                    loading="lazy"
                >
                </picture>
            </div>
        </figure>
        {{/if}}
    {{/if}}

I didn't offer webp format for the featured image because I only have one featured image, but there's no reason not to. For more normal use, you'll want to replicate the lower chunk of code in the upper. I also took off the lazy loading on featured images, because I always serve my featured posts first, so the one featured post is always "above the fold".

I've removed any option for images bigger than 'l' in loop.hbs, because otherwise my phone and laptop web browser were both getting served XXL images. Yikes. (Bug reported here, hoping someone will help me debug it.) There's no use for larger images on index.hbs in Ruby. At some point, I should sit down, read the css, and do the math to figure out what the maximum grid size is. And I'd really like to get this working right, instead of just kludged, because I find I'm almost always getting served the largest image from the list. It's just not as bad as it was...

Recommended reading:

Responsive images - Learn web development | MDN
That’s a wrap for responsive images — we hope you enjoyed playing with these new techniques. As a recap, there are two distinct problems we’ve been discussing here:
Ghost Handlebars Theme Helpers: img_url
Calculate image URLs efficiently with the img_url handlebars helper. Read more about Ghost themes!

Hey, before you go... If your finances allow you to keep this tea-drinking ghost and the freelancer behind her supplied with our hot beverage of choice, we'd both appreciate it!