在过去的几年里,HTML5 和 CSS3 颠覆了我们的世界以及我们处理常见网站问题的方式。似乎每隔几天就会出现一些新奇的代码片段或方法,改变着游戏规则。今天可能就是其中之一(有点)。
HTML5 中一个鲜为人知的功能是作用域 CSS。它是一种用于样式块的属性,可能会改变我们将来解决某些样式挑战的方式。
更新:据我所知,<style scoped>
已从规范中删除,甚至支持它的浏览器也已将其删除。即使在我写这篇更新(2017 年 8 月)时,作用域样式也比以往任何时候都更受欢迎和更受欢迎。Vue 文件 支持这里描述的概念,还有许多其他支持该概念的库正在出现。原生浏览器可能正在考虑将 Shadow DOM 作为该想法的替代方案。
作用域的实现很简单。让我们看看一个未经样式化页面的代码,其中所有文本默认为黑色
<div>
<style scoped>
h1 { color: FireBrick; }
p { color: SaddleBrown; }
</style>
<h1>This is an H1 in a scoped div. Regardless of global styles the text should be "FireBrick".</h1>
<p>This is a paragraph in a scoped div. The text should be "SaddleBrown".</p>
</div>
<p>This is another paragraph, that will unaffected by the scoped style and remain black.</p>
带有 scoped
属性的 style
块将覆盖通常在 head 中找到的全局样式(无论是在样式块中还是在链接样式表中),但仅限于相同父元素中的同级/后代元素。在本例中,包装 div 中的所有内容都将获得一些新的标题和段落颜色。正如 w3.org 所说 “如果存在 scoped 属性,则用户代理必须仅将指定的样式信息应用于样式元素的父元素(如果有的话),以及该元素的子节点。”

这太棒了!虽然页面上的所有其他文本可能都是黑色,但在这个 div 中,我们可以自由地进行样式化,而不必担心更改我们网站上其他任何地方类似元素的样式。这可能是一个非常强大的工具。
为什么这很酷?
“但是 Arley,”你说,用一个连词开始一个句子,“为什么不只是在那个 div 上使用一个类或 ID 并像 #foo h1
和 #foo p
那样进行样式化?这不是只是有组织的内联样式吗?” 在某些情况下,我能想到很多情况下作用域 CSS 都是一个不错的选择
- 将特定交互元素的 CSS 与 HTML 保持在一起可能很理想。如果所讨论的元素在网站上是唯一的(例如复杂滑块),则将其与全局样式缓存没有任何优势。
- 为了组织而将 CSS 与 HTML 保持在一起可能具有价值。
- 在与团队合作时,这可能是一种很棒的方法,可以允许同时开发网站的不同区域,而无需担心全局 CSS 的状态——我认为这可以作为短期解决方案。
- 如果您的文章被其他网站聚合,则可以自定义其他网站上的样式,否则这些样式将超出您的全局样式表的范围。
- 如果您在网站的评论部分启用标签,您就可以让读者有能力自定义他们的... 算了,这可能是一个糟糕的主意。
- 在第三方网站的小部件中使用,这些网站的 CSS 未知,并且小部件内的样式不应影响其他任何地方。尽管能够重置小部件内的样式是这场战斗的另一半。
- 最后(对我来说最令人兴奋的是),作用域 CSS 非常适合在内容管理系统中工作,在内容管理系统中,您对向通用模板区域添加唯一标记的灵活性要低得多,或者无法访问现有样式表。
我想更详细地讨论 CMS 的优势。
使用 CMS
当我们在 CMS 中构建网站时,我们正在构建约束以确保元素和模板的可重用性,以及维护整个网站的一致性。CMS 是让比您笨拙得多的人创建和管理内容的完美工具,而无需担心破坏任何网站组件。CMS 的一个限制是无法对唯一区域进行一次性调整。
我在企业级 CMS 中遇到了这个问题。根据最初的样机和网站范围,我们构建的 CMS 具有一致的统一外观和感觉。推出几个月后,对更大灵活性的需求出现了:添加第二种更详细的语言,以及特殊的营销活动为样式化带来了新的挑战。
我的第一个挑战是制作更大的文本块(有趣的事实:加拿大设计师在为双语设计时的一般规则是,在需要法语设计时,要留出 50% 的额外空间!)。我查看了我的页面,以及我的样式表:即使我做出的任何微小更改都意味着在整个网站上进行数小时的测试和质量保证,以确保其他区域没有因此而被破坏。后果是灾难性的!由于没有时间这样做,我发明了“穷人版的作用域 CSS”,或“代码块”,因为它后来被称为。从技术上讲,代码块只是用 ID 将 div 包裹在内容周围,然后有一个相邻的样式块来进行必要的更改(虽然这听起来很简单,但对于这项 CMS 工作来说有点超出了范围)。由于此 CSS 只适用于此页面,因此将这些样式添加到全局样式中没有任何意义。这很完美。样式块不会影响网站的任何其他区域。双语和营销活动内容变得易于开发和测试。
值得庆幸的是,作用域 CSS 将比我的拼凑解决方案更简洁和更容易实现。将不需要特殊的 ID,实际上能够使用像“p”这样非常简单的选择器将使您的 CSS 看起来非常简洁。
实践操作
您是否曾经想过让您流中的某个特定帖子以某种方式脱颖而出?即使您的 CMS 不允许在编辑器中进行编码,您仍然可能拥有选项,这得益于作用域 CSS。
WordPress 是 CMS 的一个示例,它将限制您可以在内容区域中输入的代码。WordPress 原生会从所见即所得编辑器中删除许多标记,这实际上是一件非常非常好的事情,因为它会清除新手用户可能意外引入的任何杂乱代码。让用户访问 CMS 中的代码相当于让他们访问破坏网站的权利!过多的关闭 div 标签将意味着完全混乱的布局!
通过一些前期工作,您可以创建一个“代码块”自定义字段,它将允许您将作用域 CSS 直接注入到该帖子中。如果您真的想变得花哨,您可以使用来自 Custom Field Template 等插件的功能,让即使是最不精通的用户也能通过简单的表格做出样式选择,从而轻松地利用此功能!
在下面的 WordPress 演示中,我创建了一个 Twenty Eleven 子主题(这意味着我完全依赖默认的 WordPress 模板,除了我进行了一些小调整的三个页面)。我所做的更改很少且简单(我可能还应该提到,在撰写本文时,还有另一个微不足道的问题需要考虑,但我将在稍后保存)。为了让作用域 CSS 正常工作,我只是将一小段逻辑添加到 content.php 和 content-single.php 中,以查找“scopedcss”自定义字段,然后将其弹出到样式块中。我只是将此代码放在相关内容循环的 <article>
块中
<?php
$scopedcss = get_post_meta($post->ID, 'scopedcss', false);
foreach($scopedcss as $css) {
echo '<style scoped>'.$css.'</style>';
}
?>
然后,在我的 WordPress 帖子中,我只是添加了“scopedcss”自定义字段,并写下了我想要为此帖子写的任何样式。

注意:如果您对每个帖子使用此艺术指导的想法感兴趣,但还没有准备好使用作用域样式,请查看此插件,它为您提供了用于声明样式的元框,但它们不会被作用域化,您需要像常规 CSS 一样具体。
一句警告
我自己使用“穷人版”的经验并非全是阳光和玫瑰;这种方法和作用域 CSS 存在一个主要弱点:组织变得非常困难——您最终会到处都有样式!作用域 CSS 能够拯救世界,但如果有可能,您应该使用 ID 选择器和链接样式表。
这是我们应该避免内联样式的主要原因之一,它们很混乱,它们增加了页面权重,而这些权重可能应该被缓存,它们很难被覆盖,它们会使故障排除变得复杂,最重要的是,它们很难维护。与内联样式一样,作用域样式也有其用武之地,并且可以成为一个强大的工具。明智地使用它们。
更大的警告
使用作用域样式没有适当的 polyfill 非常危险。在不支持作用域样式的浏览器中,你声明的样式将影响整个页面。 想象一下,你使用作用域样式在一个网站文章的 h1 标题中使用图像替换技术。你的网站 logo 也是 h1,因此在不支持作用域样式的浏览器中,logo 也会被替换。结果是级联样式的反向灾难。
请注意,作用域样式是一个非常有用的想法,但是没有 polyfill 的情况下使用它们的日子还很遥远。
jQuery 解决方案
由于缺乏原生浏览器支持,如果今天没有这个由 Simon Madine 制作的伟大的 jQuery Polyfill,这将是一个令人失望的演示。为了让我的演示在 WordPress 中工作,我还
- 将 jQuery 加入到我的 WordPress 主题中。
- 将以下代码添加到主题的页脚(主题文件夹中的 footer.php)。
<script src="<?php bloginfo( 'stylesheet_directory' ); ?>/jquery.scoped.js"></script>
<script>
$.scoped();
</script>

想要玩吗?
在撰写本文时,Chrome 20 是唯一支持作用域样式的浏览器。Chrome 20 目前处于 Canary 阶段,这是一个预发布版本,你可以与稳定的 Chrome 并行运行,没有任何问题。要使用它,你需要启用一个标志,方法是
- 访问 URL chrome://flags/
- 在页面中搜索“scoped”
- 点击“启用”

Chrome 的更新速度很快,因此在撰写本文后的 12 周左右(2012 年 7 月中旬),Chrome 20 应该会稳定下来。该功能是否会启用发布是另一个问题(我们还不知道)。
演示
不久的将来,作用域 CSS 将在浏览器中原生实现,无需额外的 JavaScript 就能完成这些演示中看到的令人惊叹的功能。在此之前,你可以梦想着它,阅读关于它的信息 在 w3.org 上,并查看这些演示
- 一个简单的 HTML 演示,展示了作用域 CSS 的正确实现(在撰写本文时不起作用)
- 一个简单的 HTML 演示,由于 jQuery 的作用,它确实起作用了
- 一个可工作的 WordPress 演示
作用域样式,除了提供上述功能外,还将在 Web Components 中非常强大,这是一个 W3C 的提案,用于在下一代 Web 应用中定义可重用的小部件。令人兴奋的事情。
这个功能看起来非常有用,我可以看到自己经常使用它,特别是集成到 WordPress 自定义字段中。
你提到 Chrome 20 是目前唯一支持这个功能的浏览器。你对其他浏览器的影响/输出有什么想法吗?
我希望这个功能能够尽快在其他浏览器中实现!
如果我没记错,在不支持“scoped”的浏览器中,样式块就像其他样式块一样:它会影响整个文档。
我在 Firefox 11 上测试了一下:http://dabblet.com/gist/2419401。第二个也是 SaddleBrown,即使它不在包含作用域样式块的范围内。
不知道!目前,使用旧浏览器的用户已经很多了,所以我建议还是使用 jQuery 修复。新浏览器的缓慢采用意味着我们可能在几年内都无法依赖原生支持(没有回退) :(
我只是讨厌 WordPress。臃肿且过于复杂。
解释一下?我知道它有一些缺点,但总的来说,我认识的大多数人(包括我自己)都并不介意它,也绝对不讨厌它。
就 CMS 而言,WordPress 非常易于使用,而且非常轻量级。每当小客户需要 CMS 时,我总是选择 WordPress。我也很想听听你的解释。
PyroCMS 是 WordPress 笨拙的一个很好的反例。它轻量级,并且提供定制功能,而且无需进行太多操作。
WordPress 很好,但由于 PyroCMS 的模块化、优异的灵活性和速度以及代码简洁性,我们打算将其用于新客户。
我不太喜欢 polyfill 的概念:它们没有必要。最简单、最有效的回退是你描述的“穷人范围”。
没有 JavaScript?没问题。
这几乎不比不使用作用域好。
比单独使用作用域并将整个页面毁掉(或者毁掉别人的页面:毕竟,
scoped
的主要目的就是聚合;而且当你不知道你的 feed 会在哪里结束时,你就不能依赖 polyfill)。这个解决方案
1. 现在起作用,
2. 在所有主流浏览器中,并且
3. 没有意外的副作用,
4. 没有依赖关系(polyfill/特性检测),而且
5. 无论 JavaScript 是否启用。
除了更加健壮之外,它也比使用 polyfill 更轻量级,而且它为其他用途(例如脚本)提供了自然挂钩。
就我个人而言,我也认为这是一件好事,因为它提醒你(开发人员)结构和浏览器限制。不管你喜欢与否,你目前还不能“直接使用它”。从长远来看,这种做法不需要额外的努力,并且会对支持开发过程中的迁移有所帮助。
我喜欢!很棒的想法!
有趣的功能,但我必须说我永远不会使用它,因为上面提到的原因。它会让维护更困难,你将样式与结构混合在一起,页面会膨胀,等等。它感觉就像在普通 CSS 中使用 !important……它在边缘情况下有其用途,但大多数情况下,当我发现自己写 !important 时,就该回去看看原因,并更改其他 CSS,使其不再需要。我对使用这个功能也有同样的感觉。
我同意。我开始认为这和内联样式一样?难道我们不是试图摆脱内联样式吗?
虽然我不太喜欢这个概念(感觉像新式的内联样式,我知道我肯定遗漏了一些要点,但这只是我的感觉 :)),但我非常喜欢在合适的地方使用合适的功能。
而不是这个
来引用样式表目录,可以改为使用这个
使用这个的好处是它可以在 SSL 环境下正常工作。
综上所述,或许应该将这个脚本加入到主题功能插件或该主题的 functions.php 文件中。
在 WordPress 的帖子中以及针对那些“不熟悉 php”的人,你可以在“HTML 视图”中直接在帖子中编写 CSS 代码。
此外,这种方式速度更快,因为 WordPress 不需要处理自定义字段,特别是当你有很多自定义字段时,而且你无需修改 Wp 主题和 php 文件。
我喜欢 php,也喜欢“穷人范围”的自定义字段解决方案,但我知道有些人讨厌它。
感谢 Arley 分享……
呃,内联样式不好,懂吗?
“警告”段落很好地总结了这一点,希望我永远不需要使用任何内联样式 :)
完全同意。我也不喜欢内联样式。
除此之外,我认为我还没有找到使用作用域样式的“真正”用例。这只是为了解决问题,不是吗?
是的,我不会使用它,也不会允许我的客户使用它。祝那些选择使用它的人好运。
ps。它一点都不酷,它只是违背了我们多年来一直反对的一切(内容与呈现)。
我觉得作用域样式与内联样式的优势并没有那么具体。虽然我确实认为这有一些用途,但我认为它们非常边缘化,不值得添加。
话虽如此,我非常希望能够在样式表中声明某些内容为作用域,这样它将忽略所有外部样式并充当它自己的“命名空间”,如果你愿意的话。它可能会减少 css 文件的大小,同时仍然保持不同的抽象层。
Chrome dev 也可用:(20.0.1105.0 dev-m)
“启用 . Mac、Windows、Linux、Chrome OS
尊重元素中的“作用域”属性。”
也许只有我太累了,无法理解这种作用域样式有多么出色,但是这与通过(当然是用 PHP)在 WordPress 的 body/post 中添加一个独特的类并赋予该特定帖子一些独特的样式有什么区别?
我相信 Chris Coyier 和 Jeff Starr 的 BLANK WordPress 主题具有该功能,允许人们执行
我在以前版本的网站上多次使用过它来为每个帖子提供独特的触感,而且我不需要花费天文数字的时间来做这件事。:)
这样做可以让我在一个样式表环境中继续工作,但我确实看到了作用域样式的潜力。嗯,我想我咖啡因和睡眠不足。:P
Arley,这是一篇很棒的文章,读起来也很棒。:)
我认为重点是,如果你想能够在每个帖子基础上定制样式(人们喜欢在艺术导向的博客上这样做),那么虽然你可以用一种样式表的方式来做,但最终你会得到一个巨大的样式表,其中大部分样式只与一个页面相关。例如,在主页上,你将加载数十个它不需要的自定义样式。
作用域方法允许你将这些样式保持在它们所需的页面上,而不会使你的主要样式表膨胀,也不必为所有其他页面加载它们。
我认为作用域样式本身并不是一个坏主意,但它们可能以不好的方式使用。我想这取决于具体情况。
Arley,很好的概述。
很多评论都说这太接近“内联样式”了,他们没有看到太多好处。你在“为什么这很酷”部分提到了我认为最重要的优势,我认为 Jeremy Keith 在这里很好地总结了这一点
http://www.html5forwebdesigners.com/semantics/index.html#scoped_styles
他说
因此,主要优势是可移植性。也就是说,能够获取一个单独的内容块并将其放在任何网站的任何位置,并且它仍然具有相同的样式。因此(当此功能变得更加普遍时),如果开发人员开始像使用内联样式一样使用它,那么这应该是一个警告,表明可能需要采用不同的方法。
啊,我明白了……但是我们如何避免错误使用作用域属性呢?
提醒一下,网络是一个多大陆系统,法语在加拿大以外的地方也有使用……
世界上除了北美还有其他地方;)
说得对!我做过的所有双语工作都是加拿大的。有趣的是,我有一些法裔加拿大人朋友最近去了巴黎,说没有人能理解他们!
我将为一家跨国公司(与我的雇主一样,总部位于英国)的全球不同地区构建 28 个网站。
一些国家(如加拿大)有 2 种主要语言,比如比利时(弗拉芒语/瓦隆语),一些国家多达 4 种,比如瑞士(德语、法语、意大利语、罗曼什语),英国的语言比你想象的要多(英语、威尔士语、苏格兰盖尔语、阿尔斯特语、康沃尔语),每种语言都有自己的怪癖,尽管通常英语和威尔士语是全国范围内唯一得到照顾的两种语言。法语和挪威语在所需空间方面的差异相比,法语简直是小巫见大巫!
现在再加上这些语言使用的不同字符集,所有这些就开始加起来。坦白地说,这就像一个雷区,但我认为我不会使用作用域样式来处理所有这些,对我来说,这一切都是关于灵活的垂直方向 :)
所以,正如你所看到的,当你走出北美,世界变得复杂得多。
关于高级 CSS 的信息丰富的文章。事实上,这些都是鲜为人知的硬核技巧和窍门。
你链接到 JQuery 替代品真是太棒了!
谢谢!
很棒的文章。如果我最终需要拯救我的工作,我可能会使用这种技术。你的 WordPress 示例非常棒,切中要害。
顺便说一句:在魁北克,我们不需要为双语内容容器分配多 50% 的空间,因为我们已经在法语中设计了!;-)
无论我最终是否会使用它,拥有另一个技巧在手总是很酷的。
你知道什么真的超级酷吗?承认使用 CMS 系统时遇到的特殊挑战。克里斯,我真的很感谢你。那些从未处理过(通常写得很糟糕的)无法修改的第三方 HTML,以及(通常写得很糟糕的)无法修改或阻止加载的样式表的人,根本不知道。
与其成为一个雕塑家,精心塑造我的网站的各个方面,不如说我是一个瘦弱的摔跤手,与一个又一个笨重的野蛮人搏斗,在这个过程中筋疲力尽。糟糕的比喻,但我认为你明白了意思。
我一直想向 ShopTalk 播客发送一个关于这方面的问题——你们可以谈谈使用 CMS 时遇到的特殊挑战和方法吗?也许我还是会这样做的。总之,感谢你分享这篇文章!
我明白你的意思,Jessi。CMS 摔跤给我留下了很多伤痕。
我很想在即将到来的 ShopTalk 中听到一些关于使用 CMS 时 CSS 组织/常见错误避免策略的信息。
干杯!
感谢你的声援,Brandon!也许这个周末我会提交一些东西到 ShopTalk。不过,请随意先于我!
我向克里斯而不是阿雷·麦克布莱恩致歉。赞美你,阿雷!
内联 CSS 的绝佳替代方案……它几乎就是内联 CSS。
是的,我同意你的观点,朱利安,但它也是对 A:HOVER 内联问题的替代方案。
阅读“警告”和第一条评论让我对这感到担忧。我看到它可能成为一种拐杖,一种让网站未来管理变成噩梦的拐杖。
我们都接触过布满了内联样式的网站,它们不好用。此外,我们正处于 CMS 的时代,这意味着将这些作用域样式粘贴到你的数据库中,或者使用大量的模板文件,或者在你的模板文件中构建很多逻辑。
9
哦,我记得几年前你有一个类似的教程。是关于你博客中的一个页面。在那同一周,你只使用了 Safari。好记性,对吧?而且页面是白色的(不像你当时的当前主题),有两张大图片,是的……它们来自 Google 图片,一张是 Mozilla 的,另一张是 Safari 的……嗯!
酷的是你实际上有很好的 JS 脚本,所以它们可以在所有浏览器中运行。
祝你好运。
http://chriscoyier.net/2009/12/15/the-safari-challenge/
是的!
也许我只是“不明白”,但这看起来与我们多年来抛弃的内联样式非常相似。
他们似乎可以通过允许像这样的外部版本让它更酷 20%
style.css
index.html
当你定义一个作用域元素时,全局样式还会级联到它里面吗,还是会给你一个“空白画布”?如果后者,我可以看到它非常有用,因为它允许你创建页面中真正独特的元素,没有*任何*全局样式。例如,如果你想在你的页面或文章中展示其他人 CSS 的片段,而不必诉诸 iframe 或 javascript 片段来清除你自己的网站的样式声明,你懂我的意思吗?
“WordPress 是一个 CMS 的例子,它会限制你可以在内容区域输入的代码。”
我使用 MODX 就是为了这个原因:我不想有限制,也不想浪费任何时间在后端四处奔波。
我只想编写代码和样式,而不必动脑筋去想如何才能重用它并保持它的可管理性。
解决方案是模板变量 (TV),或者 WordPress 所谓的小部件。但小部件太......什么?2001 年?1997 年?
有了 TV,我可以在模板的任何地方放它。TV 可以是我想要的任何东西,它可以像我需要/想要的那样“笨”或“聪明”。
我经常以各种方式做你在这里描述的事情(感谢这篇文章),我只是不必思考、担心或压力管理它。有了过度的 ACL,我也不必担心其他内容创建者和编辑覆盖我的 TV。
感谢你发表这篇文章,我可以想到几个案例,如果我知道有这样的东西,我的生活会轻松很多。将它整合到 WordPress 中也是一个非常有趣的想法。
不幸的是,它很可能会从 Blink (Chrome) 中移除:https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/R1x18ZLS5qQ
这篇文章应该更新,因为似乎 Blink 正在移除对它的支持:https://twitter.com/ebidel/status/476026012610748416
亲爱的,我想在一个页面中使用多个 jquery UI 主题,这怎么可能做到简单呢?
我试过从 jquery 主题下载范围文件,但当我打开它的演示文件时,它不工作,我也无法在我的网页上实现它。
所以请写点关于它的东西。