【问题标题】:Is there a current or proposed way to set individual layers of multiple backgrounds?是否有当前或建议的方法来设置多个背景的各个层?
【发布时间】:2013-01-04 15:05:22
【问题描述】:

有人知道使用 CSS 更改多层背景的一层的方法吗?

我一直在四处寻找,但找不到任何提及当前甚至未来提议的规范。我的想法是可能不会有,但现在网络如此庞大,我确信有人在某处拥有这些信息或讨论的链接。

以下示例在应用于不同元素时显然会出现优先顺序问题:

.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>

显然,上述问题有许多解决方法,但没有一个是理想的,尤其是当您开始谈论许多不同的“层状态”和许多不同的“纹理”时:

初步解决方案

组合类

这是最优化的后备方案,但当您开始考虑供应商前缀并处理超过两层时,它会变得很荒谬。

.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);
}

分离元素

在本地运行一些测试时,我发现多层背景比使用子元素执行得更快。事实上,对于大多数现代浏览器来说,即使引入一个简单的孩子(没有应用背景)也会大大降低渲染速度。

<div class="building-texture">
  <div class="shade-dark"></div>
</div>

JavaScript 生成

为了克服手动输入第一个选项(组合类)的痛苦,可以使用 JavaScript 来生成样式表。但是你仍然有长类名的尴尬。另外,当您想要更改组合类的一个应用效果(例如移除阴影)时,您必须编写脚本以根据命名约定来确定如何执行此操作。

通过 JavaScript 的样式属性

另一个选项是通过.style 在每个元素上动态重写整个背景。我没有对此进行测试,但我的头脑告诉我这将是相当低效的,因为我确信浏览器在处理预设类时能够进行很多优化(即通过按分类对元素渲染进行分组)。虽然我可能是错的。

为什么...

我正在玩 CSS 3D 变换(启用透视)以及如何以简单快速的方式最好地纹理/照亮此类结构(示例代码):

http://pebbl.co.uk/wote/


(来源:pebbl.co.uk

在生成我满意的 CSS 解决方案失败后,我目前正朝着基于 Canvas 的解决方案前进,该解决方案将预先构建我可能想要的所有纹理以及它们不同的阴影状态,然后生成一个作为单层背景附加的缓存数据 URI。我的测试表明这是最佳的。但是,我真的很想尽可能多地使用基于浏览器的原生解决方案,因为使用画布涉及更多的代码,而且,因为今天的浏览器改进得如此之快,重新发明任何轮子、引擎、或道路网络。

即使可能会认为我所做的不是对 CSS 的“正确”使用,但在我看来,每个背景项目都是它自己的单元——对我来说,应该有一些特定的方式是有道理的单独修改每个单元......即使它在未来很遥远。

我会对任何带有这些讨论链接的答案感兴趣。

【问题讨论】:

  • 我确定有人在mailing lists 中对此进行了讨论。
  • 据我所知,背景不需要供应商前缀。我会选择“组合课程”
  • @One Trick Pony:我认为他指的是渐变前缀。
  • @OneTrickPony 好点,我指的是应用渐变。忽略了这一点。道歉。
  • 好的,但这不会增加太多的 CSS 代码(一些额外的字节)。如果你使用像 SASS 或 Less 这样的预处理器,你仍然会拥有一个紧凑的源代码。

标签: css background-image


【解决方案1】:

不幸的是,在常规 CSS 中没有办法做到这一点。您只能更改整个属性,而不是其中的一部分。这就是为什么我们有单独的属性,例如background-imagebackground-color。但没有比这更细粒度的了。

正如 ScottS 所建议的,伪元素可能是一种可行的方法,但您可能会遇到与多个单独的 div 元素相同的问题。

如果您的主要目标是避免一遍又一遍地输入代码,那么一个好的解决方案是使用 CSS 预处理器,例如 SASS。您的 SCSS 将是这样的:

$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;
}

它会编译成更庞大的 CSS(带有完整的 URL 定义),但您肯定会节省很多开发时间。 SASS 还可以帮助您使用 mixins 生成供应商前缀(还有 Compass 将其添加到 SASS)。

事实上,有一个upcoming CSS variables spec,您将来可能可以使用它,但我认为目前还没有任何浏览器支持它。

【讨论】:

  • 是的,我没有提到它,但无论情况如何,我都会使用 SASS 或 LESS 在任何“大规模”上执行此操作,就像 OP 所希望的那样。您的解决方案绝对是一种可行的方法,我也曾想过提供一种方法,但采用了伪元素的想法。 +1 的贡献。
【解决方案2】:

用伪元素抽象

我还不知道有什么方法可以“交换”单个背景。一种解决方法是基于“分离元素”技术,但内部元素是伪元素。我不知道渲染速度。它还有一个缺点是它不适用于 IE8,如you cannot apply filter to pseudo-elements。但是,由于您将这个想法与 CSS3 透视等结合使用,因此 IE8 警告对您来说不是问题。

这实现了从阴影中抽象出纹理。它甚至可以通过:after 伪元素添加另一层,如果需要/需要,它仍然可以在这三个中的每一个中使用多个背景。

Here is the fiddle.

示例代码:

HTML

<div class="texture"></div>
<div class="texture light"></div>
<div class="texture medium"></div>
<div class="texture dark"></div>

CSS(核心)

.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%);
}

【讨论】:

  • 不幸的是,这种方法确实会影响性能,但这是一个好主意,并且浏览器可能会随着时间的推移改进它们的支持,所以我会密切关注它并将其标记为满足我需求的最佳答案,但 SASS 也是一个很好的建议@DisgruntledGoat (+1)。谢谢。
猜你喜欢
  • 2023-01-17
  • 2015-08-25
  • 1970-01-01
  • 2015-04-19
  • 1970-01-01
  • 1970-01-01
  • 2017-07-07
  • 1970-01-01
  • 2019-05-21
相关资源
最近更新 更多