It's a very common situation - you have an image that needs to fit its content box without losing the aspect ratio. It seems that the easiest way to solve the problem is to insert your picture via CSS background-image
and give it the background-size: cover
property. There are also other background-*
properties that can help you with positioning and styling.
However, inserting images with CSS is not always the most appropriate choice. It's how the purely decorative images should be handled. When it comes to the images that are providing any kind of meaningful information, 👉 object-fit
gives us the ability to manipulate the content inside the <img> tag in a very similar way as background-size
does with CSS-inserted background images.
TL;DR: Don't use background-*
for images, videos or other replaced elements that are providing any kind of information, concepts or functionality. 👉 Use inline images and style them in CSS with object-fit
and object-position
instead.
For the sake of brevity, I will write mostly about handling images, instead referring to each kind of replaced elements separately. The main idea is the same, though.
Summary
👉 background-* vs object-fit
👉 Background images are not accessible
👉 Background images are not SEO-friendly
👉 Are there any performance issues with background images?
👉 Conclusion
Background vs object-fit
object-fit
is used to fit image or video (and every other replaced element) to its content box. Images with non-decorative content should be inserted like this into the HTML document and further styled in the CSS stylesheet 👇
<!--index.html-->
<img src='meaningful-image.jpg' alt='this text describes the image'
class='.my-html-image'/>
/*style.css*/
.my-html-image {
object-fit: cover;
object-position: left 10%, top 15%;
}
Check the CodePen demo below for working example of object-fit
values:
Decorative background images should be inserted like this into the CSS stylesheet 👇
/*style.css*/
.my-div {
background-image: url(my-special-image-url.jpg);
background-repeat: no-repeat;
background-position: left 10% top 15%;
background-size: cover;
}
As you can see, it's not the amount or the complexity of code that makes a difference between those two ways of inserting images. The thing is that using background-*
for non-decorative content have some serious drawbacks.
Background images are not accessible
Background images are meant to be purely decorative and it would be incorrect to make them "audible". It can be tempting to simply build a pie chart with conic gradient in CSS, but by doing it you are probably excluding people who cannot see the chart.
Screen readers and other assistive technologies rely on structural markup, and therefore, it is your responsibility as the developer to ensure that your HTML is semantically correct in describing the functional purpose of the content. Background images don't have a corresponding markup element - you set them in CSS directly - so, they are 'invisible' to the screen readers.
Besides proper HTML structure, there are other important accessibility features, like alt attributes for images, that cannot be used with background-*
properties.
Browsers do not provide any special information on background images to assistive technology. This is important primarily for screen readers, as a screen reader will not announce its presence and therefore convey nothing to its users. 👉 If the image contains information critical to understanding the page's overall purpose, it is better to describe it semantically in the document.
-MDN, https://developer.mozilla.org/en-US/docs/Web/CSS/background
Background images are not SEO-friendly
Google parses the HTML of your pages to index images, but doesn't index CSS images. 👉 If you want your images to rank in Google Image search then you best use <img> tag with the src attribute pointing at the image. That said, it would be a shame to hide your visual content behind the background-image
, especcially if it's a custom content that is additionally backing up your message.
As previously mentioned, background
is purely CSS property and doesn't have a corresponding HTML tag or attributes. 👉 For good SEO results images should be placed near relevant text, have alt tags and maybe a caption - you can't do any of those with background-*
.
Are there any performance issues with background images?
Yes, but there is hope on the horizon. There are some significant shortcomings regarding performance of background images:
👉 Background images are discovered by browser only after all CSS in page's <head> element has been downloaded and parsed. If there is a substantial amount of CSS, it may cause slower loading of the background image.
👉 Likewise, it is impossible to provide high-res images without writing a bunch of device pixel ratio media queries, which is a non-standard feature.
image-set() is a new feature that allows us to use different background images for different screen densities (just like srcset attribute in <img> tag) - hence solving the second problem. Even more so, image-set() can be used with the new preload feature 👇
The preload value of the <link> element's rel attribute lets you declare fetch requests in the HTML's <head>, specifying resources that your page will need very soon, which you want to start loading early in the page lifecycle, before browsers' main rendering machinery kicks in. 👉 This ensures they are available earlier and are less likely to block the page's render, improving performance.
- MDN, https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
So, hopefully, if the browser support ever gets just a bit better for both image-set() and preload, we can consider both issues solved.
For more information, read this article on Google Developers.
Conclusion
Background images are not "bad" per se, they just have some shortcomings when implemented in the incorrect way. You should definitely choose them for abstract background pattern, background color / gradient, or some blurry, decorative image. But for your hero image or any other meaningful content, you might consider the <img> and <picture> tags, together with object-fit
and object-position
. The latter provides much more opportunities for accessible, easily discoverable and performant images.
Top comments (1)
Just a tip that images displayed through the CSS background property can be lazy loaded.