Text on the web automatically wraps at the edge of the screen so that it doesn't overflow. Images, on the other hand, have an intrinsic size. If an image is wider than the screen, the image overflows and the user has to scroll horizontally to see all of it.
Fortunately, CSS gives you tools to stop this from happening.
Constrain your images
In your style sheet, you can use max-inline-size
to declare that images can never be rendered at a size wider than their
containing element.
img {
max-inline-size: 100%;
block-size: auto;
}
You can apply the same rule to other kinds of embedded content too, like videos and iframes.
img,
video,
iframe {
max-inline-size: 100%;
block-size: auto;
}
With this rule in place, browsers automatically scale down images to fit on the screen.
Adding a block-size
value of auto means the browser preserves your images' aspect ratio as it
resizes them.
Sometimes, an image's dimensions are set by a content management system (CMS) or
other content delivery system. If your design calls for a different aspect ratio
from the CMS's default, you can use the
aspect-ratio
property to preserve your site's design:
img {
max-inline-size: 100%;
block-size: auto;
aspect-ratio: 2/1;
}
Unfortunately, this often means the browser has to squash or stretch the image to make it fit in the intended space.
To prevent squashing and stretching, use the
object-fit property.
An object-fit value of contain tells the browser to preserve the image's
aspect ratio, leaving empty space around the image if needed.
img {
max-inline-size: 100%;
block-size: auto;
aspect-ratio: 2/1;
object-fit: contain;
}
An object-fit value of cover tells the browser to preserve the image's
aspect ratio, cropping the image if needed.
img {
max-inline-size: 100%;
block-size: auto;
aspect-ratio: 2/1;
object-fit: cover;
}
You can change the position of the image crop using the object-position property. This adjusts the focus of the crop, so you can make sure the most important part of the image is still visible.
img {
max-inline-size: 100%;
block-size: auto;
aspect-ratio: 2/1;
object-fit: cover;
object-position: top center;
}
object-position to crop
only one side of your image.Deliver your images
Those CSS rules tell the browser how you'd like images to be rendered. You can also provide hints in your HTML about how the browser should handle those images.
Hints for sizing
If you know your image's dimensions, always include width and height
attributes. Even if the image is rendered at a different size because of your
max-inline-size rule, the browser still knows the width to height ratio and
can set aside the right amount of space. This prevents your other content from
jumping around when the image loads.
<img
src="image.png"
alt="A description of the image."
width="300"
height="200"
>
Hints for loading
Use the loading attribute to tell the browser whether to delay loading the
image until it's in or near the viewport. For images below the fold, use a value
of lazy. The browser won't load lazy images until the user has scrolled far
down enough that the image is about to come into view. If the user never
scrolls, the image never loads.
<img
src="image.png"
alt="A description of the image."
width="300"
height="200"
loading="lazy"
>
For a hero image above the fold, don't use loading. If your site automatically
applies the loading="lazy" attribute, you can usually set loading to the
default value of eager to prevent images from being lazy loaded:
<img
src="hero.jpg"
alt="A description of the image."
width="1200"
height="800"
loading="eager"
>
Fetch Priority
For important images-such as the LCP image, you can further
prioritize the loading using Fetch Priority by
setting the fetchpriority attribute to high:
<img
src="hero.jpg"
alt="A description of the image."
width="1200"
height="800"
loading="eager"
fetchpriority="high"
>
This tells the browser to fetch the image right away and at high priority, instead of waiting until the browser has finished its layout and would fetch images normally.
However, when you ask the browser to prioritize downloading one resource, like
an image, the browser must de-prioritize another resource such as a script or a
font file. Only set fetchpriority="high" on an image if it's truly vital.
Hints for preloading
It's best to avoid preloading whenever possible by including all images in the initial HTML file. However, some images may be unavailable, such as images added by JavaScript or a CSS background image.
You can use preloading to get the browser to fetch these important images ahead of
time. For really important images, you can combine this preloading with the
fetchpriority attribute:
<link rel="preload" href="hero.jpg" as="image" fetchpriority="high">
Again, use these attributes sparingly to avoid overriding the browser's prioritization heuristics too often. Overusing them can cause performance degradation.
Some browsers support preloading responsive images
based on srcset, using the imagesrcset and imagesizes attributes.
For example:
<link rel="preload" imagesrcset="hero_sm.jpg 1x hero_med.jpg 2x hero_lg.jpg 3x" as="image" fetchpriority="high">
By excluding the href fallback, you can make sure browsers without srcset
support still preload the correct image.
You can't preload images in different formats based on browser support of certain formats. Attempting this can result in extra downloads that waste users' data.
Responsive images with srcset
Thanks to that max-inline-size: 100% declaration, your images can't break out
of their containers. However, if a user has a small screen and a low-bandwidth
network, making them download the same size images as users with larger screens
wastes data.
To fix this issue, add multiple versions of the same image at different sizes,
and use the srcset
attribute to tell the browser these sizes exist and when to use them.
Width descriptor
You can define a srcset using a comma-separated list of values. Each value is
the URL of an image, followed by a space, followed by some metadata about the
image, called a descriptor.
In this example, the metadata describes the width of each image using the w
unit. One w is the width of one pixel.
<img
src="small-image.png"
alt="A description of the image."
width="300"
height="200"
loading="lazy"
decoding="async"
srcset="small-image.png 300w,
medium-image.png 600w,
large-image.png 1200w"
>
The srcset attribute complements the src attribute instead of replacing it.
You still need to have a valid src attribute, but the browser can replace its
value with one of the options listed in the srcset. To save bandwidth, the
browser only downloads the larger image if they're needed.
Sizes
If you're using the width descriptor, you must also use the
sizes
attribute to give the browser more information. This tells the browser what size
you expect the image to be displayed at under different conditions. Those
conditions are specified in a media query.
The sizes attribute takes a comma-separated list of media queries and image
widths.
<img
src="small-image.png"
alt="A description of the image."
width="300"
height="200"
loading="lazy"
decoding="async"
srcset="small-image.png 300w,
medium-image.png 600w,
large-image.png 1200w"
sizes="(min-width: 66em) 33vw,
(min-width: 44em) 50vw,
100vw"
>
In this example, you're telling the browser that in a viewport with a width over
66em, it should display the image no wider than one third of the screen
(inside a three-column layout, for example).
For viewport widths between 44em and 66em, display the image at half the
width of the screen (as in a two-column layout).
For anything narrower than 44em, display the image at the full width of the
screen.
This means that the biggest image won't necessarily be used for the widest screen. A wide browser window that can display a multi-column layout uses an image that fits in one column, which might be smaller than an image used for a single-column layout on a narrower screen.
Pixel density descriptor
You can also use descriptors to provide an alternate version of images to show on high-density displays, to keep images looking sharp at the higher resolutions they provide.
Use the density descriptor to describe the pixel density of the image in
relation to the image in the src attribute. The density descriptor is a number
followed by the letter x, as in 1x or 2x.
<img
src="small-image.png"
alt="A description of the image."
width="300"
height="200"
loading="lazy"
decoding="async"
srcset="small-image.png 1x,
medium-image.png 2x,
large-image.png 3x"
>
If small-image.png is 300 by 200 pixels in size, and medium-image.png is
600 by 400 pixels, then medium-image.png can have 2x after it in the
srcset list.