Multiple background. How to add two background images to one element? Progressive Improvements and Legacy Browsers

). Today we'll talk a little about another interesting feature - using multiple images in the background.

Background composition

There are many reasons why you might want to compose multiple images in the background at all, the most important of which are:

  • saving traffic on the size of images, if individual images weigh less in total than an image with flattened layers, and
  • the need for independent behavior of individual layers, for example, when implementing parallax effects.
There may be other reasonable reasons :)

Classic approach

So we need to place several background images one on top of the other. How is this problem usually solved? It’s very simple: for each background image, a block is created, to which the corresponding background image is assigned. Blocks are either nested inside each other or placed in a row with appropriate positioning rules. Here's a simple example:

A block with the class "fishing" inside "mermaid" is for demonstration purposes only.

Now some styles:
.sample1 .sea, .sample1 .mermaid, .sample1 .fishing ( height:300px; width:480px; position: relative; ) .sample1 .sea ( background: url(media/sea.png) repeat-x top left; ) .sample1 .mermaid ( background: url(media/mermaid.svg) repeat-x bottom left; ) .sample1 .fish ( background: url(media/fish.svg) no-repeat; height:70px; width:100px; left : 30px; top: 90px; position: absolute; ) .sample1 .fishing ( background: url(media/fishing.svg) no-repeat top right 10px; )

Result:

IN in this example three nested backgrounds and one block with fish located next to the “background” blocks. In theory, fish can be moved, for example, using JavaScript or CSS3 Transitions/Animations.

By the way, this example for ".fishing" uses the new syntax for background positioning, also defined in CSS3:
background: url(media/fishing.svg) no-repeat top right 10px;
It is currently supported in IE9+ and Opera 11+, but is not supported in Firefox 10 and Chrome 16. So users of the last two browsers will not be able to catch the fish yet.

Multiple backgrounds

A new option added to CSS3 comes to the rescue - the ability to define multiple background images for one element. It looks like this:

And the corresponding styles:
.sample2 .sea ( height:300px; width:480px; position: relative; background-image: url("media/fishing.svg"), url("media/mermaid.svg"), url("media/sea. png"); background-position: top right 10px, bottom left, top left; background-repeat: no-repeat, repeat-x, repeat-x ; ) .sample2 .fish ( background: url("media/fish.svg ") no-repeat; height:70px; width:100px; left: 30px; top: 90px; position: absolute; )
To define multiple images, you must use the background-image rule, listing the individual images separated by commas. Additional rules, also as a list, you can set positioning, repetitions and other parameters for each image. Note the order in which the images are listed: layers are listed from left to right from topmost to bottommost.

The result is exactly the same:

One rule

If the fish do not need to be separated into a separate block for subsequent manipulations, the entire picture can be rewritten with one simple rule:

Styles:
.sample3 .sea ( height:300px; width:480px; position: relative; background-image: url("media/fishing.svg"), url("media/mermaid.svg"), url("media/fish. svg"), url("media/sea.png"); background-position: top right 10px, bottom left, 30px 90px, top left; background-repeat: no-repeat, repeat-x ; )

I won’t show a picture of the result - believe me, it coincides with the two pictures above. But pay attention to the styles again, especially “background-repeat” - according to the specification, if part of the list at the end is missing, then the browser must repeat the specified list the required number of times to match the number of images in the list.

In this case, it is equivalent to this description:
background-repeat: no-repeat, repeat-x, no-repeat, repeat-x;

Even shorter

If you remember CSS 2.1, it defined the ability to describe background images in a short form. How about multiple images? This is also possible:

Sample4 .sea ( height:300px; width:480px; position: relative; background: url("media/fishing.svg") top right 10px no-repeat, url("media/mermaid.svg") bottom left repeat-x , url("media/fish.svg") 30px 90px no-repeat, url("media/sea.png") repeat-x; )

But note that now you can't just skip values ​​(unless they match the default value). By the way, if you want to set the color of the background image, this must be done in the very last layer.

Dynamic images

If the composition is static or dynamic at most depending on the size of the container, then multiple backgrounds obviously simplify the page design. But what if you need to work with individual elements of the composition independently from javascript (move, scroll, etc.)?
By the way, here is an example from life - a theme with a dandelion in Yandex:


If you look into the code, you will see something like this:
...

Blocks with classes "b-fluff-bg", "b-fluff__cloud" and "b-fluff__item" contain background images that overlap each other. Moreover, the background with clouds constantly scrolls, and dandelions fly across the screen.

Can this be rewritten using multiple backgrounds? In principle, yes, but subject to 1) support for this feature in the target browsers and... 2) read on;)

How to add dynamics to multiple backgrounds? In such a situation, it turns out to be convenient that in the internal representation the browser distributes the individual parameters of the background images according to the appropriate rules. For example, for positioning there is “background-position”, and for shifts it is enough to change only this. However, there is a cost for using multiple images - this rule (and any similar one) requires you to list the position for all backgrounds defined for your block, and you cannot do this selectively.

To add animation to our fish background, you can use the following code:
$(document).ready(function() ( var sea = $(".sample5 .sea"); var fishesX = 30; var fishesY = 90; var fishX = 0; var fishY = 0; var mermaidX = 0; var t = 0; function animationLoop() ( fishesY = 90 + Math.floor(30 * Math.sin(t++ / 180.0)); if(--fishesX< 0) fishesX = 480; mermaidX += 0.5; if(mermaidX >480) mermaidX = 0; fishY = -10 + (10 * Math.cos(t * 0.091)); fishX = 10 + (5 * Math.sin(t * 0.07)); sea.style.backgroundPosition = "top " + fishY + "px right " + fishX + "px, " + mermaidX + "px bottom," + fishesX + "px " + fishesY + "px, top left"; window.requestAnimFrame(animationLoop); ) animationLoop(); ));
Where
window.requestAnimFrame = (function() ( return window.requestAnimationFrame || window.msRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.webkitRequestAnimationFrame || (function(callback) ( window.setTimeout(callback, 1000 / 60 ); )); ))();

And by the way, animations can also be done using CSS3 Transitions/Animations, but this is a topic for a separate discussion.

Parallax and interactivity

Finally, similar maneuvers can easily add parallax effects or interactive interaction with the background:

Multiple background images are useful in such scenarios, since while we are talking only about the background (and not the content), their use allows us to avoid littering the html code and DOM. But everything comes at a price: I can’t access individual composition elements by name, id, class or any other parameter. I must explicitly remember the order of elements in the composition in the code, and for every change in any parameter of any element, in fact, I must glue together a line describing the values ​​of this parameter for all elements and update it for the entire composition.

Sea.style.backgroundPosition = "top " + fishY + "px right " + fishX + "px, " + mermaidX + "px bottom," + fishesX + "px " + fishesY + "px, top left";

I am sure that this can be wrapped in convenient javascript code, which will take care of the virtualization of relationships with individual layers, while leaving the html code of the page as clean as possible.

What about compatibility?

All modern versions Popular browsers, including IE9+, support multiple images (you can check, for example, Caniuse).

You can also use Modernizr to provide alternative solutions for browsers that don't support multiple backgrounds. As Chris Coyier wrote in his post about layer order when using multiple backgrounds, do something like this:

Multiplebgs body ( /* Awesome multiple BG declarations that transcend reality and imsourcess chicks */ ) .no-multiplebgs body ( /* laaaaaame fallback */ )
If you are confused about using JS to provide backward compatibility, you can simply declare background twice, however, this also has its drawbacks in the form of possible double loading of resources (this depends on the implementation of css processing in a particular browser):

/* multiple bg fallback */ background: #000 url(...) ...; /* Awesome multiple BG declarations that transcend reality and imsourcess chicks */ background url(...), url(...), url(...), #000 url(...);

If you've already started thinking about Windows 8, keep in mind that you can use multiple backgrounds when developing metro style applications, since it uses the same engine as IE10.

P.s. On topic: I can’t help but remember the phenomenal article about

Task

Add two background images for a block using CSS3.

Solution

Modern browsers allow you to add an arbitrary number of background images to an element, listing the parameters of each background separated by commas. It is enough to use the universal background property and specify one background for it first and a second one separated by a comma.

For example, consider creating vertical decorative lines to the left and right of the block. To do this, first prepare images that should be repeated vertically without joints. In Fig. 1 shows the background image, which will be displayed on the left edge, and in Fig. 2 picture for display on the right edge.

Rice. 1. Background picture for border left

Rice. 2. Background image for the border on the right

The block element to which the background is added is usually the tag

due to its convenience and versatility, in order to distinguish it from other elements, the block class is added to it (example 1).

Example 1: Two background images

HTML5 CSS3 IE Cr Op Sa Fx

Two background images

During 11 months of duty, radio operators conducted 8,642 communication sessions with a total volume of 300,625 groups. These are only meteorological and aerial telegrams. Received from the radio station Cape Chelyuskin 7450 groups.

The result of this example is shown in Fig. 3.

Today, almost every website design contains a beautiful background image.

Every layout designer knows that the simplest way to create a design is the best that can be. One of the simple and convenient techniques is, using several lines css code.

It would seem like a small thing, but still, sometimes you need to do something complicated in a simple way. For example, implement several backgrounds with individual parameters, without using auxiliary div blocks. That is, saving .

In this article, we'll look at the code syntax that supports multiple backgrounds in a single element. Here's what it looks like in real life:

CSS code for multiple backgrounds

Multiple background images are implemented using multiple values css parameter background, which are separated by a coma:

#multipleBGs ( background: url(photo1.png), url(photo2.png), url(photo3.png) ; background-repeat: no-repeat, no-repeat, repeat-y; background-position: 0 0, 30px 70px, right top; width: 400px; height: 400px; border: 1px solid #ccc; )

I tried to do the same with a short code. Unfortunately, it doesn't work.

Plus, you can use other background properties (background-attachment, background-clip, background-image, background-origin, background-position, background-repeat, background-size). Same as with CSS gradients.

That's all! I hope you liked this technique of creating multiple backgrounds, without using any auxiliary elements. Pure semantic code.

If you have any questions, comments or suggestions about this technique for creating multiple backgrounds, write in the comments. Also, I would like to test for

). Today we'll talk a little about another interesting feature - using multiple images in the background.

Background composition

There are many reasons why you might want to compose multiple images in the background at all, the most important of which are:

  • saving traffic on the size of images, if individual images weigh less in total than an image with flattened layers, and
  • the need for independent behavior of individual layers, for example, when implementing parallax effects.
There may be other reasonable reasons :)

Classic approach

So we need to place several background images one on top of the other. How is this problem usually solved? It’s very simple: for each background image, a block is created, to which the corresponding background image is assigned. Blocks are either nested inside each other or placed in a row with appropriate positioning rules. Here's a simple example:

A block with the class "fishing" inside "mermaid" is for demonstration purposes only.

Now some styles:
.sample1 .sea, .sample1 .mermaid, .sample1 .fishing ( height:300px; width:480px; position: relative; ) .sample1 .sea ( background: url(media/sea.png) repeat-x top left; ) .sample1 .mermaid ( background: url(media/mermaid.svg) repeat-x bottom left; ) .sample1 .fish ( background: url(media/fish.svg) no-repeat; height:70px; width:100px; left : 30px; top: 90px; position: absolute; ) .sample1 .fishing ( background: url(media/fishing.svg) no-repeat top right 10px; )

Result:

In this example, there are three nested backgrounds and one block with fish located next to the “background” blocks. In theory, fish can be moved, for example, using JavaScript or CSS3 Transitions/Animations.

By the way, this example for ".fishing" uses the new syntax for background positioning, also defined in CSS3:
background: url(media/fishing.svg) no-repeat top right 10px;
It is currently supported in IE9+ and Opera 11+, but is not supported in Firefox 10 and Chrome 16. So users of the last two browsers will not be able to catch the fish yet.

Multiple backgrounds

A new option added to CSS3 comes to the rescue - the ability to define multiple background images for one element. It looks like this:

And the corresponding styles:
.sample2 .sea ( height:300px; width:480px; position: relative; background-image: url("media/fishing.svg"), url("media/mermaid.svg"), url("media/sea. png"); background-position: top right 10px, bottom left, top left; background-repeat: no-repeat, repeat-x, repeat-x ; ) .sample2 .fish ( background: url("media/fish.svg ") no-repeat; height:70px; width:100px; left: 30px; top: 90px; position: absolute; )
To define multiple images, you must use the background-image rule, listing the individual images separated by commas. Additional rules, also a list, can set positioning, repetitions and other parameters for each image. Note the order in which the images are listed: layers are listed from left to right from topmost to bottommost.

The result is exactly the same:

One rule

If the fish do not need to be separated into a separate block for subsequent manipulations, the entire picture can be rewritten with one simple rule:

Styles:
.sample3 .sea ( height:300px; width:480px; position: relative; background-image: url("media/fishing.svg"), url("media/mermaid.svg"), url("media/fish. svg"), url("media/sea.png"); background-position: top right 10px, bottom left, 30px 90px, top left; background-repeat: no-repeat, repeat-x ; )

I won’t show a picture of the result - believe me, it coincides with the two pictures above. But pay attention to the styles again, especially “background-repeat” - according to the specification, if part of the list at the end is missing, then the browser must repeat the specified list the required number of times to match the number of images in the list.

In this case, it is equivalent to this description:
background-repeat: no-repeat, repeat-x, no-repeat, repeat-x;

Even shorter

If you remember CSS 2.1, it defined the ability to describe background images in a short form. How about multiple images? This is also possible:

Sample4 .sea ( height:300px; width:480px; position: relative; background: url("media/fishing.svg") top right 10px no-repeat, url("media/mermaid.svg") bottom left repeat-x , url("media/fish.svg") 30px 90px no-repeat, url("media/sea.png") repeat-x; )

But note that now you can't just skip values ​​(unless they match the default value). By the way, if you want to set the color of the background image, this must be done in the very last layer.

Dynamic images

If the composition is static or dynamic at most depending on the size of the container, then multiple backgrounds obviously simplify the page design. But what if you need to work with individual elements of the composition independently from javascript (move, scroll, etc.)?
By the way, here is an example from life - a theme with a dandelion in Yandex:


If you look into the code, you will see something like this:
...

Blocks with classes "b-fluff-bg", "b-fluff__cloud" and "b-fluff__item" contain background images that overlap each other. Moreover, the background with clouds constantly scrolls, and dandelions fly across the screen.

Can this be rewritten using multiple backgrounds? In principle, yes, but subject to 1) support for this feature in the target browsers and... 2) read on;)

How to add dynamics to multiple backgrounds? In such a situation, it turns out to be convenient that in the internal representation the browser distributes the individual parameters of the background images according to the appropriate rules. For example, for positioning there is “background-position”, and for shifts it is enough to change only this. However, there is a cost for using multiple images - this rule (and any similar one) requires you to list the position for all backgrounds defined for your block, and you cannot do this selectively.

To add animation to our fish background, you can use the following code:
$(document).ready(function() ( var sea = $(".sample5 .sea"); var fishesX = 30; var fishesY = 90; var fishX = 0; var fishY = 0; var mermaidX = 0; var t = 0; function animationLoop() ( fishesY = 90 + Math.floor(30 * Math.sin(t++ / 180.0)); if(--fishesX< 0) fishesX = 480; mermaidX += 0.5; if(mermaidX >480) mermaidX = 0; fishY = -10 + (10 * Math.cos(t * 0.091)); fishX = 10 + (5 * Math.sin(t * 0.07)); sea.style.backgroundPosition = "top " + fishY + "px right " + fishX + "px, " + mermaidX + "px bottom," + fishesX + "px " + fishesY + "px, top left"; window.requestAnimFrame(animationLoop); ) animationLoop(); ));
Where
window.requestAnimFrame = (function() ( return window.requestAnimationFrame || window.msRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.webkitRequestAnimationFrame || (function(callback) ( window.setTimeout(callback, 1000 / 60 ); )); ))();

And by the way, animations can also be done using CSS3 Transitions/Animations, but this is a topic for a separate discussion.

Parallax and interactivity

Finally, similar maneuvers can easily add parallax effects or interactive interaction with the background:

Multiple background images are useful in such scenarios, since while we are talking only about the background (and not the content), their use allows us to avoid littering the html code and DOM. But everything comes at a price: I can’t access individual composition elements by name, id, class or any other parameter. I must explicitly remember the order of elements in the composition in the code, and for every change in any parameter of any element, in fact, I must glue together a line describing the values ​​of this parameter for all elements and update it for the entire composition.

Sea.style.backgroundPosition = "top " + fishY + "px right " + fishX + "px, " + mermaidX + "px bottom," + fishesX + "px " + fishesY + "px, top left";

I am sure that this can be wrapped in convenient javascript code, which will take care of the virtualization of relationships with individual layers, while leaving the html code of the page as clean as possible.

What about compatibility?

All modern versions of popular browsers, including IE9+, support multiple images (you can check, for example, Caniuse).

You can also use Modernizr to provide alternative solutions for browsers that don't support multiple backgrounds. As Chris Coyier wrote in his post about layer order when using multiple backgrounds, do something like this:

Multiplebgs body ( /* Awesome multiple BG declarations that transcend reality and imsourcess chicks */ ) .no-multiplebgs body ( /* laaaaaame fallback */ )
If you're concerned about using JS to provide backwards compatibility, you can simply declare background twice, although this also has its drawbacks in the form of possible double loading of resources (this depends on the implementation of css processing in a particular browser):

/* multiple bg fallback */ background: #000 url(...) ...; /* Awesome multiple BG declarations that transcend reality and imsourcess chicks */ background url(...), url(...), url(...), #000 url(...);

If you've already started thinking about Windows 8, keep in mind that you can use multiple backgrounds when developing metro style applications, since it uses the same engine as IE10.

P.s. On topic: I can’t help but remember the phenomenal article about .

Today we will work on background images, which are set using the background property and its additional values. Let's look at a couple of practical examples of installing multiple backgrounds for the same element.

This can be useful in many cases and moments. Especially the use of pseudo elements in this case, since they are very flexible in parameters.

Lots of background images

In order not to create a block within a block, the easiest way is to add one line of rules to the main element and thus get the desired result. We can consider this a laconic option, especially since it eliminates the need to once again go into source. Everything will be done using CSS alone.

Blockimg( background: url("img/img2.png"),/*topmost background and then sequentially*/ url("img/img3.png"), url("img/img1.jpg"); background-position :370px center, 120px 150px, center center;/*position of images*/ background-repeat: no-repeat;/*repeat picture*/ background-color: #444;/*if background color is needed*/ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1); margin: 100px auto 15px; box-sizing: border-box; padding: 25px; width:700px; min-height: 300px; ) /*shortened version*/ .blockimg ( background: url("img/img2.png") no-repeat 370px center, url("img/img3.png") no-repeat 120px 150px, url("img/img1.jpg") no-repeat center center ; margin: 100px auto 15px; box-sizing: border-box; padding: 25px; width:700px; min-height: 300px; )

Explanation. We give the element a background image, indicating the path to its location. Separated by commas, we are given the opportunity to enter many more backgrounds, as can be seen in the code above. The order of their numbers determines which image will be on top of the others. That is, the first background is higher than all the others, and then the sequence follows the principle of a regular graphic editor.

Next, additional parameters are specified through individual properties: position, repetition, size, and, if necessary, color. Please also note that all parameters are written separated by commas, in the same order as the number of the picture.

And one last detail. The entire code can be shortened by using just one generic property, background . There is a second option in the code example that shows how this is done.

Background image via pseudo element

Also don't forget about alternative options as such are the before and after pseudo-elements. There is a positive advantage in their use - the image can be moved beyond the edge of the element, so that it does not disappear at the border, but is on top of it. This technique will come in handy if you need to create something like a 3D effect.

Blockimg( background: url("img/img1.jpg") no-repeat;/*element background*/ position:relative;/*positioning area*/ margin: 200px auto 15px; box-sizing: border-box; padding: 25px; width:700px; min-height: 300px; ) .blockimg::before( background: url("img/img1.png") no-repeat center center; bottom: 0; content: ""; height: 295px; left: 0; position: absolute;/*absolute positioning*/ right: 0; top: -150px; )

Explanation. In fact, everything is very simple. We set the background to the main element in the usual way. Next comes the key property position: relative; , which defines the area for moving another element that is in the main element and has the property position:absolute; .

Instead of another element, although formally it goes as a separate area, we use a pseudo-element. We give it an absolute position and position it in the place we need.