Recently, I was thinking about creating a media queries for my website. Specifically for users on small screen devices and users on the iPad. This is relatively easy using media queries and can be accomplished using the following CSS:

@media screen and (max-width: 600px) { body { background: url(some-image.jpg) } }

The Problem?

My biggest concern with doing this was the current version of my website is very image heavy, especially with the large background-image I'm using. I was worried that code I presented above would actually load the smaller iPad-friendly image, even to users who were on larger monitors, since the image references appear in the stylesheet.

I had previously delved into this underground (see: 'boring') topic in a previous article of mine called CSS Image Preload - :hover Pseudo Selector Parent Of display: none Element where I discovered that browsers do no load background-images on child elements if the parent element is set to display: none;

Having somewhat of an interest in the topic of browsers loading background-images used in stylesheets, I decided to create an full-blown data table on the topic for everyone to enjoy.

Who Cares If The Browser Loads An Image Or Not?

Your users for one. The large background-image on my site is 63kb in size. If a user doesn't actually see that image on their screen, then why waste their time downloading it? Furthermore, if you run a heavily trafficked site, think if a million users had to request that image, only to never see it on their screen.

The Data

I was able to capture whether or not a browser downloaded the background-images in CSS using an external program called Fiddler. Fiddler captures all HTTP traffic on your computer, regardless if it's a browser or an update service running requesting the image. Originally I was going to use each browser's web inspector such as Firebug but I decided to use Fiddler to get the data from a single source.

Comparison of Browser Image Pre-loading (Yes=Image loaded on page load; No=Image not loaded on page load)
Type Of CSS Used Firefox 3.6 Safari 4 Chrome 5 Opera 10.5 Internet Explorer 7
Default (control data)
div { background: url(image.jpg); }
Yes Yes Yes Yes Yes
Element - display: none
div { background: url(image.jpg); display: none; }
No [1] Yes Yes No [1] Yes
Element - visibility: hidden
div { background: url(image.jpg); visibility: hidden; }
Yes Yes Yes Yes Yes
Element - Outside Viewport
div { background: url(image.jpg); left: -9999px; }
Yes Yes Yes Yes Yes
Element - :hover
div:hover { background: url(image.jpg); }
No No No No No
Element - Parent display: none
ul { display: none; }
ul li { background: url(image.jpg); }
No No No No Yes [2]
Single Media Query
div { background: url(image.jpg);
@media screen and (max-width: 600px)
{ div { background: url(image.jpg); } }
No [5] Yes [3] Yes [3] No [5] Unsupported
Multiple Media Queries
div { background: url(image.jpg);
@media screen and (max-width: 600px)
{ div { background: url(image1.jpg); } }
@media screen and (max-width: 500px)
{ div { background: url(image2.jpg); } }
No [5] Yes [4] Yes [4] No [5] Unsupported
  1. [1] Both Firefox and Opera will not load a background-image of an element if it is set to display: none. This means that if the element's display property is later changed to block or inline, the browser will need to fetch the image after page load has occurred.
  2. [2] Internet Explorer seems to break from the trend of the other browsers here by loading the background-image of an element that is nested inside of another element that is display: none;
  3. [3] Both Safari and Chrome load background-images from both the media query & the non-media query element background-image.
  4. [4] Both Safari and Chrome load background-images from both media queries even when the background is trumped by a media query further down in the stylesheet. The image for the non-media query element background-image was also downloaded
  5. [5] Both Firefox & Opera only downloaded the background-image used in the media query. If more than one media query was used, it only requested the last image.

Analyzing My Results

What I found was very interesting. Even amongst the more 'modern' browsers there are differences in how they handle image loading. I'd like to note that the browsers I tested were simply the ones I had installed on my machine at the time of testing.

Default (control data)

My first test, was simply a control. Yeah...I'm a fan of the scientific method.

Element - display: none

Next up I tested elements that are set to display: none i.e.

div { background: url(image.jpg); display: none; }

What I found was interesting. Both Firefox & Opera did not load the image while Safari, Chrome & IE7 did. This might sound like a minor browser difference but consider the following:

div { background: url(image.jpg); display: none; } div:hover { display: block; }

When the DIV is hovered over, both Firefox & Opera need to quickly fetch the image. This causes the evil image flicker. Drawing a conclusion on this is tough. Would you rather have the image ready to use on hover at the expense of your bandwidth or saving some bandwidth and download time for your site's users?

Element - visibility: hidden

I found the results for elements set to visibility: hidden to be the same across all browsers. Every browser downloaded the background-image immediately on page load. This is a key difference between display: none and visibility: hidden for many browsers.

Element - :hover

I found the results for background-image hovers to be the same across all browsers. Every browser waited to download the background-image until the element was hovered on.

Single Media Query

For this test I added a single media query to my page along with a background-image for all users:

body { background: url(body.jpg); } @media screen and (max-width: 600px) { body { background: url(media-query.jpg) } }

The data below breaks down how each browser reacted when I loaded my test page in a browser window that met the requirements of the media query (i.e. the browser window being smaller than 600px.

Images Downloaded On Page Load With Browser Viewport Below 600px
Firefox 3.6 Safari 4 Chrome 5 Opera 10.5
media-query.jpg body.jpg
media-query.jpg
body.jpg
media-query.jpg
media-query.jpg

Notice the differences? Firefox & Opera reacted much differently than Safari & Chrome. Both Firefox & Opera decided not to bother downloading my original background-image. By doing so, should the browser window become larger than 600px, Firefox & Opera would need to quickly download the new background-image.

Multiple Media Queries

body { background: url(body.jpg); } @media screen and (max-width: 600px) { body { background: url(media-query1.jpg) } } @media screen and (max-width: 500px) { body { background: url(media-query2.jpg) } }
Images Downloaded On Page Load With Browser Viewport Below 500px
Firefox 3.6 Safari 4 Chrome 5 Opera 10.5
media-query1.jpg body.jpg
media-query1.jpg
media-query2.jpg
body.jpg
media-query1.jpg
media-query2.jpg
media-query1.jpg

The results for this test were similar to the single media query. The only difference is Safari & Chrome downloaded all media query background-images regardless if they were being used or not.

Takeaway

When using media queries and designing sites for multiple devices, take into consideration how many images your incorporate into your alternate stylesheets. You could potentially force users to download excess files depending on which browser they are using.