Is anyone aware of a way to change one layer of a multi-layered background using CSS?
I've been searching around but can't find any mention of current, or even proposed future specification. My thinking says there probably wont be, but the net is so vast now I'm sure someone, somewhere, has information or links to discussions along these lines.
The following example would obviously have problems with regard to the order of precedence when applied to different elements:
.building-texture {
background: transparent, url(image/building-side.png);
}
.shade-dark {
background: url(image/shade-dark.png), unchanged;
}
.shade-mid {
background: url(image/shade-mid.png), unchanged;
}
.shade-light {
background: url(image/shade-light.png), unchanged;
}
<div class="building-texture shade-dark"></div>
Obviously there are a number of workarounds for the above, but none are ideal, especially when you start talking about a lot of different 'layer states' and a number of different 'textures':
This is the most optimal of the fallbacks, but gets ridiculous when you start to take vendor prefixes into account and when dealing with more than two layers.
.building-texture-shade-dark {
background: url(image/shade-dark.png), url(image/building-side.png);
}
.building-texture-shade-mid {
background: url(image/shade-mid.png), url(image/building-side.png);
}
.building-texture-shade-light {
background: url(image/shade-light.png), url(image/building-side.png);
}
When running through some tests locally, I found that multi-layered backgrounds performed faster than using sub-elements. In fact for most modern browsers, even introducing a simple child (with no background applied) slowed the rendering down quite a bit.
<div class="building-texture">
<div class="shade-dark"></div>
</div>
To get over the pain of hand-typing the first option (combined classes), JavaScript could be used to generate the stylesheet. But you still have the awkwardness of the long class names. Plus when you want to change one applied effect of the combined class (e.g. remove shading), you have to script an ability to work out how to do so based on naming convention.
The other option is to dynamically rewrite the entire background via .style
on each element. I haven't tested this, but my head tells me that this will be rather inefficient, as I'm sure the browsers are able to do quite a few optimisations when dealing with preset classes (i.e. by grouping element rendering by classification). Although I could be wrong.
I'm playing around with CSS 3D transforms (with perspective enabled) and how best to texture/light such structures in a simple and fast manner (example code):
http://pebbl.co.uk/wote/
(source: pebbl.co.uk)
After failing at producing a CSS solution I was happy with, I'm currently heading toward a Canvas-based solution that would pre-build all the textures I may want—along with their different shaded states—which would then generate a cached data URI to be attached as a single layer background. My tests have shown this to be optimal. However, I'd really like to use as many native browser-based solutions as possible, because with canvas there is a lot more code involved, and, because today's browsers are improving so quickly, it seems foolish to reinvent any wheels, engines, or road networks.
Even if it might be deemed that what I'm doing is not a 'proper' use of CSS, in my opinion, each background item is it's own unit—and to me it makes sense that there should be some specified way to modify each unit separately... even if it's way off in the future.
I'd be interested in any answers with links to discussions along these lines.
Double-click the Background layer in the Layers panel. Choose Layer > New > Layer From Background. Select the Background layer, and choose Duplicate Layer from the Layers panel flyout menu, to leave the Background layer intact and create a copy of it as a new layer.
Selecting multiple layers To select multiple layers, select your first layer, hold ⇧ and click on another. You can also hold ⇧ and click on a layer you've already selected to remove it from the selection. Alternatively, click-and-drag from an empty area on the Canvas to select any layers within your selection area.
A background is an image that is placed on a web page to add color or design to the page. A layered background adds one or more images. The majority of these layouts are created with nested tables. Images add load time to a page so be careful how you use them.
Select all the layers, press Ctrl + G to put them all in one group. Double click on the Group folder or right click on it and select Blending Options . Select Color Overlay in the list on the left, click on the red box to select the color you want. No copy or pasting required.
Unfortunately there is no way to do that in regular CSS. You can only change an entire property, not part of it. Which is why we have separate properties like background-image
, background-color
to start with. But nothing more fine-grained than that.
As ScottS suggested, pseudo-elements could be a way to go but you will probably have the same problems as multiple separate div elements.
If your main goal is to avoid typing code over and over, a good solution would be to use a CSS preprocessor like SASS. Your SCSS would then be something like this:
$img-side: url("image/building-side.png");
$img-dark: url("image/shade-dark.png");
$img-mid: url("image/shade-mid.png");
$img-light: url("image/shade-light.png");
.building-texture {
background: transparent, $img-side;
}
.shade-dark {
background: $img-dark, $img-side;
}
.shade-mid {
background: $img-mid, $img-side;
}
.shade-light {
background: $img-light, $img-side;
}
It would compile down to the more bulky CSS (with full URL definitions) but you certainly save a lot on development time. SASS can also help you generate the vendor prefixes using mixins (there is also Compass which adds that to SASS).
In fact, there is an upcoming CSS variables spec which you may be able to use in future, however I don't think any browsers support it yet.
I am not aware of any way to "swap" a single background yet. One workaround is based off the "separate elements" technique, but the inner element is a pseudo-element instead. I have no idea about rendering speed. It also has the drawback that it will not work for IE8, as you cannot apply filter
to pseudo-elements. However, since you are using the idea in conjunction with CSS3 perspective and such, the IE8 caveat is not an issue for you.
This achieves the abstraction of the texture from the shading. It could even add another layer through an :after
pseudo-element, and it still could use multiple backgrounds in each of the three if needed/desired.
Sample Code:
HTML
<div class="texture"></div>
<div class="texture light"></div>
<div class="texture medium"></div>
<div class="texture dark"></div>
CSS (core)
.texture {
position: relative;
background: url(http://www.dummyimage.com/12x16/ff0000/ffffff.png&text=X++) top left repeat;
}
.light:before,
.medium:before,
.dark:before {
content: '';
position: absolute;
top:0;
right: 0;
bottom:0;
left: 0;
}
.light:before {
background: -moz-linear-gradient(left, rgba(0,0,0,0.3) 0%, rgba(0,0,0,0.1) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,0.3)), color-stop(100%,rgba(0,0,0,0.1)));
background: -webkit-linear-gradient(left, rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
background: -o-linear-gradient(left, rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
background: -ms-linear-gradient(left, rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
background: linear-gradient(to right, rgba(0,0,0,0.3) 0%,rgba(0,0,0,0.1) 100%);
}
.medium:before {
background: -moz-linear-gradient(left, rgba(0,0,0,0.6) 0%, rgba(0,0,0,0.2) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,0.6)), color-stop(100%,rgba(0,0,0,0.2)));
background: -webkit-linear-gradient(left, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
background: -o-linear-gradient(left, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
background: -ms-linear-gradient(left, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
background: linear-gradient(to right, rgba(0,0,0,0.6) 0%,rgba(0,0,0,0.2) 100%);
}
.dark:before {
background: -moz-linear-gradient(left, rgba(0,0,0,0.8) 0%, rgba(0,0,0,0.3) 100%);
background: -webkit-gradient(linear, left top, right top, color-stop(0%,rgba(0,0,0,0.8)), color-stop(100%,rgba(0,0,0,0.3)));
background: -webkit-linear-gradient(left, rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
background: -o-linear-gradient(left, rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
background: -ms-linear-gradient(left, rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
background: linear-gradient(to right, rgba(0,0,0,0.8) 0%,rgba(0,0,0,0.3) 100%);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With