Grow your CSS skills. Land your dream job.

Stacking Order of Multiple Backgrounds

Published by Chris Coyier

Multiple background images is a cool feature of CSS3. The syntax is easy, you just comma separate them. I find it's easiest/best to use the background shorthand property so you can declare the position and repeating and whatnot and keep them all grouped together. What isn't obvious while looking at the syntax is which image is on top in the vertical stacking order when those images overlap. The spec is clear in this regard and browser implimentations follow. The first is on top and they go down from there.

background: 
   url(number.png) 600px 10px no-repeat,  /* On top,    like z-index: 4; */
   url(thingy.png) 10px 10px no-repeat,   /*            like z-index: 3; */
   url(Paper-4.png);                      /* On bottom, like z-index: 1; */

It's like z-index but this isn't z-index, it's parts of one single element.

I think it's slightly confusing, since it's the opposite of how HTML works naturally. If all elements have the same z-index (and are positioned in some way and overlap) the last element will be on top, not the first. Not that big of a deal though, just need to learn it once.

The big thing to remember is that if you were to use one of the background for a fully opaque / fully repeating image, list that one last not first, otherwise it will cover all the others up.

Also remember that while multiple backgrounds is totally radical, the fallback for browsers that don't support it is that it displays nothing at all for the background, so be careful there. The best way to handle it, as always, is Modernizr. They even use it as the demo right on the homepage of their site (adjusted for clarity):

.multiplebgs body {
   /* Awesome multiple BG declarations that transcend reality and impress chicks */
}
.no-multiplebgs body {
  /* laaaaaame fallback */
}

Comments

  1. Alexander
    Permalink to comment#

    Clear and simple explanation. Thanks.

  2. Noah
    Permalink to comment#

    It would be interesting if they allowed another value for a z-index like effect.

    Like:
    background: url(number.png) 600px 10px 5 no-repeat

    • Possibly… but that might be overly complicated. What advantages does that bring over just changing the order?

    • Noah
      Permalink to comment#

      Switching background layers with javascript? That’s about all I can come up with.

      But that leads me to another question. How does this change how jquery targets it with .css() ?

    • While you bring it up… I would love to see a simple property for these backgrounds in css for a couple things (I know they are possible, but a simpler syntax would be awesome).

      For lack of a better example, lets say a black and gray checkered background, with two soid block images. Such as a “checker” property of even a “fade-left: value;” type of thing, for faded images.

      I dunno but it would be crazy.

  3. Alexander
    Permalink to comment#

    Think allowed transparency would be cool and creative stuff. Tried rgba color on top. Not possible.

    • JulienW
      Permalink to comment#

      I heard it’s coming ;-)

      You’ll be able to put lots of things in a “image()” expression, especially rgba colors; and “image()” expressions can then be used anywhere an image is legal.

  4. Permalink to comment#

    Modernizr isn’t necessary for fallback. Add a standard background before the multi-background property. Modern browsers will use the last read declaration while older browsers should ignore the one they don’t understand.

    body {
    
    /* Fallback for <IE9 and other older browsers */
    background: url(back.png) 0 0 no-repeat;
    
    /* Multi-background supporting browsers */
    background:
       url(top.png) 0 0 no-repeat,
       url(middle.png) 100% 0 no-repeat,
       url(back.png) 0 100% no-repeat;
    }
    • Beat me to it!

    • Nicholas Boll
      Permalink to comment#

      The only problem with that approach is newer browsers will get penalized by having to load the fallback even if they don’t need it. A modern browser will only load resources if a selector matches an element, so the modernizr selector will not match for newer browsers and the fallback image will not be loaded.

      Modernizr’s approach is to give developers a way only penalize non-conforming browsers by loading polyfills or some sensible fallback.

    • Pablo Ziliani
      Permalink to comment#

      I totally prefer the petty penalty to newer browsers caused by a duplicated property than depending on javascript to have a css fallback.

    • MichaƂ Czernow
      Permalink to comment#

      Some browsers would download this extra graphic, some wouldn’t.

      Once upon a time a tried to make web2.0 pretty buttons with mixture of gradients. So I used CSS3 gradients for webkit and gecko. I needed two fallbacks. For Opera I used multiple backgrounds (gradients in png.), and for older browsers I used one background.

      In the image background case there was no penalization, because I used the same images that created wanted gradientish background. Fallback in this case was only narrowing the number of the images, so buttons were simpler.

      In the gradient background case Chrome and FF didn’t download fallback images (those for Opera), but Safari did :P.

      Downloading and initializing JS script (Modernizer) is not penalization?

    • Permalink to comment#

      Requiring Javascript for functionality always bothers me. Especially when it’s simply used for deprecation.

      It seems to me that people who use older browsers are most likely to have JS disabled by default.

    • ayush
      Permalink to comment#

      Cool

  5. Regarding fallbacks for browsers that don’t have support for multiple backgrounds, it’s not necessary to rely on Modernizr. You can create an effective fallback by simply declaring two background properties in the same declaration.

    Example:

    body {
    	/* Fallback */
    	background:#333;
    
    	/* Multiple Backgrounds */
    	background: url(), url(), url() ;
    }
  6. Alrighty I tested that out and you fellas are correct.

    http://jsbin.com/egabe5/2/edit

    I tested it in Firefox 2 which doesn’t support multiple BG’s and it does snag the first declaration. That’s a great way to go. I was long under the assumption that the second would overwrite the first (being the same property) and show nothing. Not the case.

  7. Permalink to comment#

    It seems that Chris becomes so engaged with the new possibilities of CSS that he forgets the very basics of it ;)

  8. Permalink to comment#

    very nice..thanx!!

  9. Thanks for this Chris, I couldn’t figure out why an extra rgba(255,255,255,.3) bg on hover wasn’t working.

  10. Permalink to comment#

    ah man you always make things so much easier than i think it would be. thanks dude. you have really helped my progress.

  11. Permalink to comment#

    In my opinion, the existing order of stacking actually makes more sense. Given that CSS was developed to separate design from markup, it makes sense that it would follow a “designer-ish” paradigm rather than a markup paradigm. In this case, it’s akin to layers in graphics packages like Photoshop, where the “top” layer is the one that has priority/visibility.

  12. Jarod Billingslea
    Permalink to comment#

    Thanks for the tip. I always did this:


    body {
    /*...background*/
    margin: 0; padding: 0;
    }

    #border-wrapper {
    /*...background*/
    margin: 20px; padding: 20px; /*optional*/
    }

  13. Alistair Chisholm
    Permalink to comment#

    Something I tried recently was putting one background on the HTML element and another on the BODY.
    Bingo, this works like a charm. I tried using a tiled bg on HTML and for example, a centered transparent png (something like an alpha gradient) on BODY. This method seemed to work flawlessly on pretty much any browser alongside dd_belated png fix. Would be interested to know if anyone else has used this method, please correct me if I am wrong

  14. Permalink to comment#

    Is it possible to see an example somewhere? I’m struggling to imagine it? It sounds cool, though!

  15. Yeah, the stacking order tripped me up when I was trying to create multiple background images with a background gradient underneath it all. For a while I couldn’t figure out why only the gradient was showing up (it was listed first, then the other images applied).

    As you said, every developer I’ve talked to has found this counter-intuitive, but it’s just one of those things you only have to learn once; though it makes me wonder why the people writing the spec created that order.

  16. Sam
    Permalink to comment#

    Interestingly, it’s not just images that can be layered, but css gradients too.

  17. kalith
    Permalink to comment#

    I had problem in IE 8 .

    will not display

    -moz-border-radius
    -moz-box-shadow

    • I hope you do know those are vendor specific CSS selectors that only work in Firefox, hence the prefix “moz” of “Mozilla”.

  18. Missy
    Permalink to comment#

    The Standard doesn’t make sense to me.

    I would say the first declared should be at the lowest level. An artist doesn’t paint the top layer first then try and add layers below.

    Logically we tend to start with backgrounds, laying down (say) an image, then perhaps a 100% div over the top with a semi-transparent image, and so on.

    Obviously the people who wrote this part of the Spec aren’t designers or artists. Or Vulcans, for that matter ;-)

  19. Permalink to comment#

    It would be nice if there was a way to add a second background without repeating the whole attribute.

    example:

    Imagin generating cards through css, you have a frame with images and a pattern

        .cards {
        background:
    
        url(frame.png) no-repeat center center 100% 100%,
        url(pattern.png)
    
        }
        And now I want to "stack" a background to a particular card
    
        .cards.heart_ace {
    background[stackposition]: url(heart.png) no-repeat center center;
    
        }
    

    Is there a way today** to accomplished that whithout js**?

  20. Rajesh
    Permalink to comment#

    how to get the css3 multiple background property if there have to be used for a same tag with different property to be used.

Leave a Comment

Current day month ye@r *

*May or may not contain any actual "CSS" or "Tricks".