Barebones CSS for Fluid Images

Zach takes a look at some fundamental HTML+CSS usage for fluid, responsive images. Most of it, I’d say, is what you’d expect, but things get weird when srcset gets involved.

I poked my way through, and in addition to the weird thing Zach noted, wanted to add one more thing. Let’s start like this:

<img src="./img.jpg" alt="" />

With no other CSS involved, this renders at the “intrinsic size” of the image. Say the original image is 400px wide, it renders 400px wide.

We should be putting width and height attributes on images, because it allows the browser to make space for them even before they are downloaded (even when they are fluid, which is super cool). So:

<img src="./img.jpg" alt="" width="400" height="300" />

Also nothing terribly weird there. Even if we slap max-width: 100% in the CSS, that’ll do what we want: preserving space, behave fluidly, and not growing bigger than it should.

But let’s hold off on the max-width: 100% thing for a second. If we just use srcset and set up multiple sources.

<img src="./img.jpg" alt=""
     srcset="./img-200.jpg 200w, ./img-400.jpg 400w" />

BAM, we blow out the width of the thing.

That won’t render at 200px or 400px—it’ll actually render at 100vw, believe it or not. I think that’s because that’s the default sizes value. I normally think of the sizes attribute as not information about anything to do with actual layout, but just information for the browser to choose a source. But that’s not true here. It really does effect layout (in all browsers I tested). Here’s proof:

See the little one below it where all I change is the sizes.

Anyway that’s not what Zach honed in on, but it’s similar. Let’s put back the responsible thing and add in width and height attributes.

<img src="./img.jpg" alt="" width="200" height="137"
     srcset="./img-200.jpg 200w, ./img-400.jpg 200w" />

No more blowout (with or without sizes) but now we have a new weird problem. This is basically like saying max-width: 200px. Even though we have sources that are wider than 200px, we’ve capped the width at 200px. Zach puts it like:

Using max-width: 100% constrains the image to the container, but be careful when you use this with srcset—it may cap smaller than you want when using [width]! Pair with width: auto to fix this.

Zach’s final snippet is this, which I think reigns in all the weirdness:

img {
  max-width: 100%;
}
img[width] {
  width: auto; /* Defer to max-width */
}
img[width][height] {
  height: auto; /* Preserve aspect ratio */
}

/* Let SVG scale without boundaries */
img[src$=".svg"] {
  width: 100%;
  height: auto;
  max-width: none;
}

Direct Link to ArticlePermalink


The post Barebones CSS for Fluid Images appeared first on CSS-Tricks.

You can support CSS-Tricks by being an MVP Supporter.

Workflow Considerations for Using an Image Management Service

There are all these sites out there that want to help you with your images. They do things like optimize your images and help you serve them performantly.

Here's the type of service I mean.

That's a very good thing. By any metric, images are a major slice of the resources on websites, and we're notoriously bad at optimizing them and doing all the things we could to lower the performance hit from them. I'm sitting at a conference right now and Dave just bet everyone in the audience $100 that he could find an unoptimized image on their site. I wasn't about to take him up on it.

So you use some service to help you deliver images better. Smart. Many of them will make managing and optimizing images a lot easier. But I don't consider them a no-brainer. There is a lot to think about, like making choices that don't paint you into a corner.

I should be able to upload images from my own CMS.

I don't want to go to your site to upload my assets. I want to use the media management in my own CMS. So, the service should have an API at a minimum, and possible even officially maintained CMS plugins.

This site uses WordPress. I can drag and drop images into the media library and posts very easily. I can search my media library for images I've uploaded before. I like that, and I want to take advantage of it today, and as it evolves.

The images should be uploaded to my own server.

If it also has to be uploaded to the image service, that's fine. But it should go to my server first, then to the service. That way, I still maintain ownership of the source file.

Images within content should use functional, semantic markup in my CMS.

I'd prefer that the images within content are stored as totally functional HTML in my database:

<img src="/images/flower.jpg" alt="a blue flower">

It could be fancier than that, like using srcset (but probably not sizes as that will change as the design changes), or be contained within <picture> or <figure> elements... whatever you like that makes sense as semantic HTML. The most important thing being that the content in my database has fully functional HTML with a src on the image that points to a real image on my real server.

The implementation of the image service will involve filtering that HTML to do whatever it needs to do, like replace the URLs to generate fancier responsive image markup and whatnot.

Between having functional HTML and images on my server, that enables me to turn off the image service if I need to. Services have a habit of coming and going, or changing in ways that make them more or less palatable. I don't want to be locked-in; I want freedom. I want to be able turn off the service and have a perfectly functional site with perfectly functional images, and not be obstructed from moving to a different service — or no service at all.

Even if I didn't use the service in the past, I want all my images to benefit from it.

I just mentioned filtering the HTML for images in my database. That should happen for all the images on my site, even if they were uploaded and used before I started using the image service.

This probably means the services offers a URL-based "get" API to optimize images on-the-fly pulled from their canonical locations.

I shouldn't have to think about format or size.

I want to upload whatever I have. Probably some huge un-optimized screenshot I just took. If I think about it at all, I want to upload something much too big and much too high-quality so that I know I have a great original version available. The service will create optimized, sized, and formatted images as needed.

I also want to upload SVG and have it stay SVG (that's also optimized).

The images will ultimately be served on a CDN.

CDNs are vital for speed. Australians get images from servers hosted in Australia. Canadians get images from servers hosted in Canada. The servers are configured to be fast and cookie-less and all the fancy over-my-head things that make an asset CDN scream.

The images should serve in the right format.

If you serve images in WebP format to browsers that support it, you'll probably get as much or more performance out of that optimization than serving re-sized images with responsive images syntax. It's a big deal.

I want the service to know what the best possible format for any particular image for any particular browser and serve the image in that format. This is going to change over time, so I want the service to stay on top of this so I don't have to.

I know that involved formats like JPEG-XR and JPEG-2000 three years ago. Is that still the case? I have no idea. This is a core value proposition for the service.

It should optimize the images and handle quality.

This is perhaps the most obvious feature and the reason you reach for an image service in the first place. Images need optimization. There are perhaps dozens of image optimization tools/algorithms that aim to squeeze every last byte out of images. The image service probably uses those or even has its own fancy tech for it. Ideally, the default is to optimize an image the most it possibly can be without noticeably hurting the quality, but still allowing me to ratchet it down even more if I want to.

Don't shame me for using high-pixel density images.

A lot of image services have some sort of tester tool where you drop in a URL and it tells you how bad you're doing with images. Many of them test the size of the image on the rendered page and compare the dimensions of the original image. If the original image is larger, they tell you could have had savings by sizing it down. That's obnoxious to me. High-pixel density displays have been around for a long time and it's no crime to serve them.

It should help me serve the right size for the device it's on and the perfect responsive syntax if needed.

Not all images benefit from the same responsive breakpoints. Check out the site Responsive Image Breakpoints. It generates versions of the image that are best depending on the image itself. That's the kind of help I like to see from an image service. Take something hard and automate it for me.

I know I'll probably need to bring my own sizes attribute because that is very dependant on my own CSS and how the design of the site plays out. It's still important, and makes me wonder if an image service could step up and help me figure out what my optimal sizes attribute should be for certain images. Like loading my site at different sizes and seeing how large the image renders with my CSS and calculating it from there to use later.

Just me.

This is just my own list of requirements. I feel like it's fairly reflective of "normal" sites that have a bunch of images and want to do the right thing to serve them.

I didn't go into all the fancy features image services offer, like being able to tell you that an image contains a giraffe facing west and hasn't eaten since Thursday while offering to recolor its retinas. I know those things are vital to some companies. This is more about what seems to me the widest and most common use case of just hosting and delivering images in the best way current technology allows.

The post Workflow Considerations for Using an Image Management Service appeared first on CSS-Tricks.

Getting Netlify Large Media Going

I just did this the other day so I figured I'd blog it up. There is a thing called Git Large File Storage (Git LFS). Here's the entire point of it: it keeps large files out of your repo directly. Say you have 500MB of images on your site and they kinda need to be in the repo so you can work with it locally. But that sucks because someone cloning the repo needs to download a ton of data. Git LFS is the answer.

Netlify has a product on top of Git LFS called Large Media. Here's the entire point of it: In addition to making it all easier to set up and providing a place to put those large files, once you have your files in there, you can URL query param based resizing on them, which is very useful. I'm all about letting computers do my image sizing for me.

You should probably just read the docs if you're getting started with this. But I ran into a few snags so I'm jotting them down here in case this ends up useful.

You gotta install stuff

I'm on a Mac, so these are the things I did. You'll need:

  1. Git LFS itself: brew install git-lfs
  2. Netlify CLI: npm install netlify-cli -g
  3. Netlify Large Media add-on for the CLI: netlify plugins:install netlify-lm-plugin and then netlify lm:install

"Link" the site

You literally have to auth on Netlify and that connects Netlify CLI to the site you're working on.

netlify link

It will create a .netlify/state.json file in your project like this:

{
	"siteId": "xxx"
}

Run setup

netlify lm:setup

This creates another file in your project at .lsfconfig:

[lfs]
	url = https://xxx.netlify.com/.netlify/large-media

You should commit them both.

"Track" all your images

You'll need to run more terminal commands to tell Netlify Large Media exactly which images should be on Git LFS. Say you have a bunch of PNGs and JPGs, you could run:

git lfs track "*.jpg" "*.png"

This was a minor gotcha for me. My project had mostly .jpeg files and I got confused why this wasn't picking them up. Notice the slightly different file extension (ughadgk).

This will make yet another file on your project called .gitattributes. In my case:

*.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.jpeg filter=lfs diff=lfs merge=lfs -text

This time, when you push, all the images will upload to the Netlify Large Media storage service. It might be an extra-slow seeming push depending on how much you're uploading.

My main gotcha was at this point. This last push would just spin and spin for me and my Git client and eventually fail. Turns out I needed to install the netlify-credential-helper. It worked fine after I did that.

And for the record, it's not just images that can be handled this way, it's any large file. I believe they are called "binary" files and are what Git isn't particularly good at handling.

Check out your repo, the images are just pointers now

Git repo where a JPG file isn't actually an image, but a small text pointer.

And the best part

To resize the image on-the-fly to the size I want, I can do it through URL params:

<img 
  src="slides/Oops.003.jpeg?nf_resize=fit&w=1000"
  alt="Screenshots of CSS-Tricks and CodePen homepages"
/>

Which is superpowered by a responsive images syntax. For example...

<img srcset="img.jpg?nf_resize=fit&w=320 320w,
             img.jpg?nf_resize=fit&w=480 480w,
             img.jpg?nf_resize=fit&w=800 800w"
      sizes="(max-width: 320px) 280px,
             (max-width: 480px) 440px,
             800px"
        src="img.jpg?nf_resize=fit&w=800" alt="Elva dressed as a fairy">

The post Getting Netlify Large Media Going appeared first on CSS-Tricks.

Tips for rolling your own lazy loading

You may have heard (or even issued the call) that “we can just use lazy loading!” when looking for a way to slim down a particularly heavy web page.

Lazy loading is a popular technique for gradually requesting images as they come into view, rather than all at once after the HTML of the page has been parsed. It can reduce the initial page weight, and help us hit our performance budgets by requesting images when they're needed.

It can be effective. But it also comes with some baggage of its own. We’ll get to that! In fact, Rahul Nanwani did an extensive write-up that hits several lazy-loading methods and illustrates just how complex some are.

In this post, we’ll look at an implementation that's already been covered in brief detail in this post by Preerhi. We're going to expand on that so you can add your own implementation of lazy loading to your site site as I’ve done on this little demo site.

We’ll cover these topics along the way:

Continue reading "Tips for rolling your own lazy loading"