Do hidden elements load background images?

One thing I have always pondered about is whether elements that are hidden will load any images associated with it, either inline or through CSS, directly at page load. And apparently, my colleague Jonatan Larsson has as well.

Jonatan and I discussed this back and forth, how it actually works and how we’d want it to work. Both he and I felt fairly certain that if an element, for instance, had a background image associated with it but was hidden (i.e. has display: none), it wouldn’t load its background image until it was shown.

So, Jonatan set about on doing some tests and his findings were that images for hidden elements, set via CSS or inline in the element, would load every time – contrary to what we thought/expected.

Part of me thinks this is good that when the element is shown, everything is already loaded and will look good, but the performance fan in me is thinking that a web browser should only load what is actually displayed.

What would you want or expect? And do you have any other findings

20 Comments

  • Daniel Grace says:

    I would prefer that the images do load, for the reasons that you outlined.

    However, as a slight tweak to somewhat alleviate your concerns, the browser could load that element last. You would still incur the bandwidth and slight CPU hit, but the apparent speed of the page loading would be the same as if the element had not loaded.

  • Interesting. I have been pondering about this as well. Even though I also have been to lazy to actually try it out I also expected hidden images to not load until visible (but I suspected that that wasn't really the case).

  • If I remember it correctly, Opera is the the only browser around not loading background-images for hidden elements.

    Anyway, I think the current behavior is correct. The CSS file should neither have the power nor the responsibility to lazy-load background images. I think WAI-ARIA or something similar should make this work, much like how the DEFER attribute is used for .

    I would like a way to flag an element as "initially hidden, paint and fetch backgrounds only when needed" on the HTML level. It would be appreciated if the mechanism for this also supported "only initially hide this element when JavaScript is available".

    My brief thoughts.

  • Rob says:

    It makes sense to me that they would load because, in the grand scheme of things, having an element with a background image on a web page is there for the purpose of being displayed eventually.

  • You have tested with background images. But what about img elements?

  • Bob Holt says:

    That's what I would expect: everything called in the markup is loaded.

    But the performance issues are annoying. The ideal solution that would allow me to serve things dynamically from external pages while still being accessible and non-javascript compatible.

  • Leonid Lezner says:

    Browsers load hidden images. If is in your markup, it will be loaded.

  • Andreas says:

    I would like it to load but "asynchronously". I mean just load content with prio one first and then just load "hidden" images in the background.

  • Bleyder says:

    In this particular case I think the images shouldn't be downloaded. Why spent my time waiting images that I will never see?

  • Andreas says:

    Bleyder: it's very uggly when you toggle the visibility of elements and they start to load the images after the element has been displayed. Therefor I opt it should load in the background, after visible stuff has loaded.

    I mean this discussion could extend to stuff below your screen that you need to scroll to see. You dont want to load that initially but the user probably is going to scroll so load it before the he/she does so…

  • Tino Zijdel says:

    The fact that they are loaded when they're in the HTML (regardless of visibility or display) gives you the choice: if you don't want them to be loaded you should dynamically add the background-image (through inline style or by setting a class or id) when you make the element visible.

  • Berserk says:

    I would expect all images to load. If I don't want them to load I'll add them with JS on demand. I don't want browsers to be "clever" about what will be shown. The downsides far outweigh the upsides.

    Remember images with javascript-controlled image-changing on hover when the onhover image wasn't loaded? You never want to have that. If browsers don't load images up front I would force-download them with JS onload.

  • Robert Nyman says:

    Good feedback everyone. I like that, no matter the opinion, I feel an urge to agree completely with every comment. πŸ™‚

    I think I can live with that they are boing loaded, but like Andreas said, I'd prefer it asynchronously when idle, or at the least loaded last in the document.

    Tino's and Berserk's option is also good with loading it via JavaScript then, but I'd like to make it as easy for everyone and sort of have it automatically taken care of.

  • Gerben says:

    This made me wonder whether or not all background images in your CSS are loaded. After a quick check I found out that that, thankfully, wasn't the case. Only background images in rules that match some element are loaded.

  • Robert Nyman says:

    Gerben,

    Yes, that would have been scary if it had been the case. πŸ™‚

  • Dan says:

    If it's in the markup or the CSS, it should be loaded. That doesn't mean you can't do lazy loading – but you'll need JS to do it.

    For example: put in a div or something and only assign it a background-image once it's positioned inside the viewable area via JS. If that image isn't just for decoration, i still wouldn't like that, since you can't put an alt-attribute on it. But there's still the title attrib, so i might be able to live with it.

    On the other hand: people without JS could never see those images. So if they convey some meaning you better stay away of this.

  • Robert Nyman says:

    Dan,

    Right, there are definitely approaches to deal with it. I just don't like the dependency of JavaScript, though, because it might be turned off or blocked (by proxy servers, anti-virus programs, web browser extensions etc).

  • Berilac says:

    You say it loads the images if they are defined in CSS. But as far as I see it doesn’t load them till the browser has to display them, even if they are defined in CSS.

    As most of us need, I’d like the background images from hidden elements to be loaded in the browser, so that when the users do some actions which causes some elements change, the image to be changed “instantly”, not showing a white area for a few moments.

  • Berilac says:

    BUT there’s good news: I’ve found a very nice way to do the “trick”: Just set the z-index as -100 or some “negative infinite” value and change it on user actions. Et voila! πŸ™‚

  • Robert Nyman says:

    Berilac,

    This blog post is nearly two years old, so I can imagine that the behavior in web browsers might have changed over time.

    If you want them to load, though, using position: absolute and placing it off screen seems more reliable than a negative z-index.

Leave a Reply to Robert Nyman Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.