SMACSS、语义类名和嵌套元素

Posted

技术标签:

【中文标题】SMACSS、语义类名和嵌套元素【英文标题】:SMACSS, Semantic Class Names and Nested Elements 【发布时间】:2012-08-22 10:34:32 【问题描述】:

我刚刚阅读了Scalable and Modular Architecture for CSS,它让我思考了一些事情。 Snook 的两条原则是:

    增加一段 HTML 和内容的语义价值 降低对特定 HTML 结构的期望

因此,这意味着使用语义类名称而不是依赖非语义元素类型进行定位。例如,我可能不针对.someClass h5,而是针对.someClass-title,这样如果将h5换成其他东西,事情就不会中断。

就我个人而言,我发现以元素的名称对元素的层次结构进行编码有点令人不快(即使它在语义上是正确的)。我宁愿做.someClass .title。但是要使用像标题一样通用的类,您需要接受这个类将在许多不同的上下文中使用。

如果我知道它会被选择器中的前一个项目命名,那么在完全不同的上下文中使用同一个类有什么问题吗?

例如,假设我的网站中有三个不同的地方,其中一类“标题”是有意义的:

HTML

<header class="pageHeader">
   <h1 class="title">Some Title</h1>
</header>

...

<article class="leadArticle>
   <h3 class="title">Some Article Title</h3>
</article>

...

<ul class="productPreviews">
   <li class="product">
      <h5 class="title">Some Product Name</h5>
   </li>
</ul>

CSS

.pageHeader .title




.leadArticle .title




.productPreview .product .title



编辑:正如Alohci 在下面的回答中提到的那样,标题标签并非没有语义,所以也许这不是最好的例子。

显然,在这些上下文中,我可能会做一些与标题完全不同的事情,但标题对于它的模块命名空间来说绝对有意义,而且我从来没有打算将标题用作通用选择器。

这似乎符合所有条件。它语义丰富,与实现完全解耦。例如,如果将最后一个示例更改为 ol 或一堆 div,则不会出现任何问题,如果将 title 包装在 div 中,它仍然会成为目标。

这对我来说很有意义,但我没有看到这种方法被广泛使用,我想知道为什么。一个明显的缺点是您在选择器中链接类,但我认为这比命名每个类名更可取。

【问题讨论】:

“……我从来没有……”——著名的遗言 【参考方案1】:

我认为这没什么好说的。你所做的很好,尽管它不是为 CSS 组织标记的唯一方法。要理解的重要一点是类名不是 CSS 的一部分,它们是 html 的一部分。

因此,应用于元素的类在 HTML 术语中不是由它们在 DOM 树中的祖先“命名空间”,而是独立存在的。因此,在示例中使用“title”作为每个元素的类名是合理的,因为它们在标题方面都是相似的。

一个相反的例子是使用类名“note”,在一个元素上它表示一种注释,但在另一个元素上是一个音符,然后假设它们的含义可以通过检查来区分一个祖先元素。 HTML 类不应该这样工作。

注意到&lt;h5&gt; 并没有什么不合语义的东西也很有效。在 CSS 选择器中使用元素名称只是描述要设置样式的元素之间关系的另一种方式。 .product h5 作为选择器意味着“在类 'product' 的子树的上下文中设置第五级标题,如下所示......”。这与.product .title 的声明不同,.product .title 的意思是“类 'title' 的样式元素在类 'product' 的子树的上下文中......”。这两种说法都很有用。

【讨论】:

感谢您的回答。我来自面向对象的背景,所以我想在某种程度上我试图将它强加到 CSS/HTML 上,我无法摆脱组件和变量的类比。我还没有看到一个跨站点的命名约定对我来说是正确的解决方案。他们似乎总是在某一点之后崩溃,变得过于复杂或难以理解。我完全同意 h5 没有什么不合语义的。可能“标题”不是我能给出的最好的例子。【参考方案2】:

我更喜欢使用 .title 之类的类,而不是只选择 h5 元素,因为我觉得它更多地将 HTML 与 CSS 分离。如果出于某种原因,您认为 h4 或 h6 更适合文档大纲或其他一些元素/原因,那么如果您选择 element(h5) 与选择 class(.标题)。

这就是为什么我更喜欢将 ALL THE THINGS 与元素选择器分类的原因,因为标记可能会随着时间而改变。如果您在一个没有看到很多更新的较小站点上工作,这可能不是问题,但最好注意这一点。

至于在完全不同的上下文中使用同一个类有什么问题,如果你知道它会被选择器中的前一个项目命名,我对此有不同的想法。

一方面,我想到了一些问题,例如,如果没有父选择器,.title 的使用/含义/角色可能为空。 (.pageHeader .title) 虽然我认为 .title 是一个非常好的类名,但其他开发人员可能很难理解它的含义来自像 .pageHeader .title 这样的父选择器

另一个问题是,如果您将 .title 类用于模块中的多个“标题”实例,则可能会遇到问题。基本思想是,如果试图在模块中扩展 .title 的可重用性,则提供的局部范围后代选择器有时可能会受到太大限制。我设置了一个代码演示来展示我在说什么here。

另一方面,后代选择器是最常用的选择器之一,特别是为了它们的作用域目的。

Tim Murtaugh 是 A List Apart 的开发人员之一(不确定他是否是首席开发人员),他在个人网站上的大部分 styles 都使用后代选择器。

我最近一直在探索这个和 BEM,并且同意你的结论,“这比命名每个类名更好。”

我更喜欢 .pageHeader .title... 与 .pageHeader__title... 但在某些情况下,一种方法可能比另一种方法更有利。

与大多数事情一样,这取决于,但我认为如果你不让嵌套太深并且考虑如何使用它们,后代选择器是提供本地范围样式的强大且良好的解决方案,同时还提供全局范围样式的解决方案。

例如:

/* Globally scoped styles for all .title(s) */
.title
   font-family: serif;
   font-weight: bold;


/* Locally scoped styles for individual .title(s) */
.pageHeader .title 
    color: #f00;


.leadArticle .title 
    color: #00f;


.productPreview .product .title 
   color: #0f0;

【讨论】:

我也已经开始对所有事物进行分类,尽管对我来说这更像是一种指导而不是规则。当涉及到内容时,与布局相反,我需要我的 CSS 来反映我对编辑器强制执行的标记的简单性 - H3、H4、H5(广告等)在内容块中都是无类的。 很好的答案。自从发布这个问题以来,我一直在对所有东西进行分类(除了像 s 这样包装 s 的必要家具,并且依赖后代选择器而不是命名空间。 【参考方案3】:

需要注意的一个非常重要的事情是,浏览器读取 CSS 是从右到左,而不是从左到右,因此如果您将选择器的结构设置为几层深度,那么浏览器要做的工作就更多了。

.pageHeader .title 
.leadArticle .title 
.productPreview .product .title 

所以这是一个 .title 但在不同的上下文中。浏览器在渲染时会检查子元素是否放置在特定的父元素内,然后应用相应的规则。

.pageHeader-title 
.leadArticle-title 
.productPreview .product-title 

这里我们有 3 个非常不同的标题(不是一个!),所以浏览器不会做任何额外的计算,也不会检查孩子是否是特定父母的孩子。我们这里还有更扁平的模块结构,这总是很好。

永远记住,嵌套选择器并以相同的方式命名它们但在不同的上下文中会影响性能数以百万计的浏览量,那么了解如何正确构建您的标记非常重要。

【讨论】:

【参考方案4】:

它有时被称为“父子关系”(http://thesassway.com/advanced/modular-css-naming-conventions),通常建议使用.page-header-title

在您的情况下,.page-header 可以被视为一个组件,.title 可以被视为一个组件。 RCSS (https://github.com/rstacruz/rscss/) 标准倡导者.page-header &gt; .title。我个人认为这不是一个好主意。考虑以下:

<header class="page-header">
<h2 class="title">
  <span class="tooltip">
    <span class="title">..</span>
  </span>
</h2>
</header>

.tooltip &gt; .title 无意中继承自 .page-header &gt; .title

所以我会选择.page-header-title

如果您确实打算从基类继承标题,只需将类添加到 HTML 元素

<header class="page-header">
<h2 class="page-header-title title">
</h2>
</header>

现在page-header-title 包含组件特定样式,title 增加了抽象标题样式。是的,它很冗长,但很安全。在这里,如果有兴趣的话,我对如何保持风格级联的理智和清晰明了的抽象的详细意见https://github.com/dsheiko/pcss

【讨论】:

以上是关于SMACSS、语义类名和嵌套元素的主要内容,如果未能解决你的问题,请参考以下文章

h5语义化标签学习笔记

编译原理—语义分析语法制导翻译翻译模式中间代码生成

web语义化理解

HTML5 语义元素

HTML5语义元素总结

HTML5语义化元素你真的用的正确吗