Generate responsive images on Remix
Sat Feb 03 2024
Unlike many other frameworks, Remix doesn’t have a built-in way to generate
responsive images. This is in keeping with its philosophy of using the web
platform, but it does make it quite a bit more work to get responsive images set
up. A lot of people want something that’s like next/image for Remix. This is
just the place where Unpic shines. If you’ve not met it, Unpic is a
cross-framework library for generating <img>
tags that are responsive,
high-performance and follow modern best practices. While I had used Unpic with
Hydrogen (because Shopify support is built-in and automatic), I hadn’t tried it
yet with local images on Remix. I’m happy to report that it works great! It
literally took my less than five minutes to get it working. Here’s how.
How to generate responsive images on Remix with Unpic
First, install Unpic with the package mananger of choice.
npm install @unpic/react
Then, use it in your page:
import { Image } from "@unpic/react";
// This is a local image import
import viaduct from "../viaduct.jpg";
export default function Page() {
return (
<div>
<Image
src={viaduct}
alt="A viaduct"
width={800}
height={600}
cdn="netlify"
/>
</div>
);
}
Seriously, that’s it. End of blog.
How it works
OK, maybe I’ll explain it a bit more. First, what does it do? In this example, we’re importing a local image using asset imports. This copies the source image into the output directory with a fingerprinted filename, then returns the URL. We can use this directly in Unpic.
Unpic doesn’t resize images itself. Instead it uses your existing image CDN,
recognises the URL and generates the correct attributes for the <img>
tag,
including the full srcset
with all the image sizes. It automatically uses
modern formats like AVIF and WebP if the browser supports it. In this case, I’m
using Netlify’s image CDN which is enabled on all Netlify sites. Vercel works in
the same way. Other CDNs will also work, but may need a few more options.
This is the generated tag. You will see it has everything to create a responsive image. It resizes fluidly, loads the right resolutions depending on the screen size. You’ll also find it gives great scores on Lighthouse and other performance tools.
<img
alt="Viaduct"
loading="lazy"
decoding="async"
sizes="(min-width: 800px) 800px, 100vw"
style="object-fit:cover;max-width:800px;max-height:600px;aspect-ratio:1.333;width:100%"
srcset="
/.netlify/images?w=640&h=480&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 640w,
/.netlify/images?w=750&h=563&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 750w,
/.netlify/images?w=800&h=600&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 800w,
/.netlify/images?w=828&h=621&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 828w,
/.netlify/images?w=960&h=720&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 960w,
/.netlify/images?w=1080&h=810&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 1080w,
/.netlify/images?w=1280&h=960&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 1280w,
/.netlify/images?w=1600&h=1200&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg 1600w
"
src="/.netlify/images?w=800&h=600&fit=cover&url=%2Fbuild%2F_assets%2Fviaduct-N2EIOTOR.jpg"
/>
Using remote images
Unpic also recognises loads of remote image sources, and can generate URLs without needing a local image service. It supports most CMSs, including Contentful, Sanity, DatoCMS and many more, as well as other services like Shopify, Cloudinary and Unsplash.
Here’s an editable example using an Unsplash image. Try it with your own images from your CMS. Just paste in the URL.
// Or try this: "https://res.cloudinary.com/demo/image/upload/dog" <Image src="https://images.unsplash.com/photo-1601418059872-2ac6d694946d" width={400} height={300} alt="Remix" />
Try inspecting the image to see the attributes.
Learn more
This is just using the default options. Take a look at the the docs to see what else is available, including different crop options, props for full-width hero images and fixed-size images like logos.