Multiple.js

An experiment in sharing background across multiple elements using CSS

Surfing over dribbble I stumbled upon a Xonom design by Cosmin Daniel Capitanu. I wondered how to accomplish such "background sharing across multiple elements" effect at HTML/CSS without any coordinates processing by JavaScript. This page is result of my research by this topic.

Check original Xonom and notice how background gradient shares across multiple elements. Note that icons and text at lighter layers have gradient-color from darker layers, creating the illusion of underlying violet layer. In addition to that, layers pass background image (girl) with equal transparency so that layers can not be superimposed on each other. All this things can be implemented at CSS.

Add gap between elements to make sure that background remains at same position

Toggle background image/gradient to get idea how it looks

Miss random layers to make sure that elements are independent

Not peeping into sources, think for a moment about how this effect may be implemented at pure CSS ?

Show me how it works!

Idea is just that simple!

background-attachment: fixed expands background to viewport's size and displays in every element appropriate chunk, exactly what is needed!

But here we stumble upon a problem with mobile devices, as far as they seems to ignore background-attachment: fixed property for performance reasons . Background behaves as with default value background-attachment: scroll. And in addition to that there are even no way to detect support of this property.

So how to handle this flaw at mobile devices? Think a bit on possible workaround and click a button below.

Mobile workaround

I bet the first thing you think was position: fixed; z-index: -1; trick because this is frequent solution for such background-related cases.

Background has been successfully expanded to full viewport size . But we need to display only that chunk of background under .selector element. It turns out that background outside of .selector element must be cropped.

But how to do that? .selector { overflow: hidden; } won't do the trick because it's descendant is position: fixed. Check out by yourself at Codepen

Go further

A little known fact but position: fixedcan be cropped by clip: rect() property! See

But because of that limitation all .selector at mobile devise must be position: absolute while desktop version does not have this restriction. This is not convenient at all. Elements must behave identically for both desktop and mobiles and does not contain extra conditions.

That's why Multiple.js was written, this little JS plugin takes care about all those markup differences, browser specific workarounds, vendor-prefixes, etc.. for you. All you left to do is simply specify selector and background.

If for some reason you decide to avoid JS plugin, want only pick styles and do all markup work by yourself, here are starting material for you:

And, in addition to that I'd like to share thoughts about customizing viewport size.

As you know background-attachment: fixed depends on viewport size, so background fills all screen from top left to bottom right point. Such background does not react on scroll, visually static and always located in the same place. Sometimes this behaviour is not what we need. Let's assume our whole background image must be strictly fit at element with sizes 500px x 500px (when actual viewport is 1920x1080). Or you need background to scroll with the page (as by default).

See examples to understand the difference:

From this (background is stretched to full-page viewport and keeps fixed on scroll while container size is restricted, so that background isn't fit wholly in container)

To this (background is stretched to container size so is fully fit and keeps scrolls with the page)

Any ideas how to do that?

Go ahead

And the answer is: Iframe!

It was a surprise for me to find out that iframe has it's own viewport, I just didn't thought about this from this point of view before. Wrapping the content into iframe and setting iframe specific sizes - and background will fill iframe's size, not parent page viewport size. Check out real examples: without iframe, with iframe. To do that easily may be used convenient iframe-resizer library that observes iframe's inner content height and change iframe height accordingly.

Options

selector

background

Background image/gradient. Should be valid background-image CSS property. Support multiple backgrounds. Must not contain vendor prefixes for gradients, they will be added automatically.

'url(image.png), linear-gradient(pink, violet)'

affectText

Optional

Specifies if background image should affect text instead of background.

P.s. Works only at desktop webkit browsers. As fallback for mobile or other desktop browsers will be shown color specified in this property. See difference at Codepen .

'black'

false

opacity

Optional

Obviously gradient's opacity may be set by RGBA syntax.

But if you are too lazy to convert HEX or RGB to RGBA, you might find this option useful. All HEX (short and long forms) and RGB colors of gradients specified in background option will be converted to RGBA with specified opacity. See difference at Codepen .

opacity supports two types of input:

0.1 - number. Will be set RGBA with specified opacity 0.1

true - boolean. Will be calculated RGBA color with as much transparency as possible over white (in other words looks same as RGB color with transparency and without loss of color)