我最近在 一篇博文 中使用此选择器作为示例
.article #comments ul > li > a.button {
/* Crazy town */
}
有几条评论认为这似乎完全合理。我认为如果我们倒过来一步步分析,疯狂之处就会更加明显。
- 它是一个具有
button
类的元素。 - 但它必须是一个锚链接,否则将无法匹配。
- 并且它必须是列表项的直接子元素。该列表项最好不要包含段落标签,否则将无法匹配。
- 该列表项必须是无序列表的直接子元素。它最好不要是有序列表,否则将无法匹配。
- 该无序列表需要位于具有
comments
ID 的元素内。请记住,只有当它位于具有article
类的元素内时,此规则才适用,否则将无法匹配。
所以,您是否有属于 button
类的元素,它们是列表项的直接子元素,而这些列表项又是无序列表的直接子元素,这些无序列表是 #comments
的子元素,并且是 .article
的子元素,但不是锚链接,因此需要以不同的方式进行样式设置?太疯狂了。
很有可能,选择器应该是
.button {
/* Happy town */
}
如果您以后需要更改按钮样式,可以编写比这稍微更具体的样式来覆盖。
article .button {
/* Buttons within articles are slightly different */
}
或者,为按钮添加一个额外的类以使其更具体。
<input type="submit" class="button big-button">
<!-- I have mostly the styles of buttons but a few overrides to make me bigger -->
非常相关:Harry Roberts 的 Shoot to kill; CSS selector intent。
Harry Roberts (@csswizardry) 昨天发布了一篇关于此主题的精彩文章:http://csswizardry.com/2012/07/shoot-to-kill-css-selector-intent/
完全正确。这就是我在最后链接它的原因 =)
哎呀!应该仔细阅读的,是吧?:P
最好指定您的类而不是选择器
a href=”” class=” button button_big icon_arrow-right ”
然后像这样编写 CSS:
.button { background:blue; height:30px }
.button_big { height:60px }
.icon_arrow-right { background-image:url(icon_arrow-right.png); background-position: center left }
然后您可以像 class=”button icon_arrow-right” 这样组合,以及各种变体
这是我们工作中使用的一种技术,即细粒度的 CSS。当我们将项目交给那些懂一点 CSS 但又很危险的网页制作人员时,这确实很有帮助。
如果您有专业的內容创建者(例如,了解 CSS 和 HTML 并且接受过您系统培训的人员),这绝对是最佳方法,但在许多组织中,业余人员将创建内容,您不能依赖他们使用 *任何* 类,更不用说多个类了。
我认为这就是选择器有时变得荒谬的原因。
我理解选择器意图,但我也觉得社区中有一些混淆的信息。
一方面,人们说您应该尽可能详细地指定元素以提高效率——这是一个合理的论点。
另一方面,人们说您应该利用语义标记,并且为了可重用代码的目的,不要“过度使用类”或“过度使用 ID”——另一个合理的论点。
我阅读了像 @csswizardry 的帖子这样的文章,我想知道是否应该有一个关于找到折衷方案的警告。
但是,语义标记与类名几乎没有任何关系。我认为语义标记和使用细粒度的类可以共存。
对我来说,语义标记意味着在正确的位置使用正确的元素,并且不包含额外的元素。它不应该与您使用多少或如何使用类名有任何关系。
根据我的经验,使用更多类名和更少的深度选择器实际上可以提高可维护性和灵活性。您可以更容易地重复使用 `.button`,而 `.foo li a` 需要一个非常特定的 HTML 子部分才能重复使用。更长的选择器还会将您的 CSS 和 HTML 更紧密地耦合在一起,这最终会造成麻烦。
+1
绝对的。这些概念不需要互相冲突。
Chris、Mark——你们误解了 Fluidbyte 帖子的重点。他指的是“类泛滥”,这是专家多年来一直反对的东西。
来自著名的书籍 CSS Mastery
“由于类的灵活性,它们可以非常强大。同时,它们也可能被过度使用甚至滥用。新手 CSS 作者经常尝试为所有内容添加类,以期对样式获得细粒度的控制。”
在 Google 上快速搜索“类泛滥”,就会出现一个关于如何识别此情况的链接
“如果样式主要由类组成(即“.className”),而祖先选择器很少,那么您就患上了类泛滥。” (http://www.steveworkman.com/html5-2/standards/2009/classitis-the-new-css-disease/)
现在,鉴于 Chris 和 Harry Roberts 明显不是新手,我的问题是:最近发生了什么变化,突然让你们给出与传统 CSS 智慧相悖的建议,不要在您的标记中到处添加类,而是使用后代选择器?
Dave,
要更好地理解为什么会有向元素添加类(但不是提倡类泛滥)的转变,我建议您阅读 SMACSS.com。Jonathan Snook 对 CSS 的可扩展、模块化架构提供了可靠的解释。
在小型宣传册风格的网站上,这种方法似乎有点矫枉过正——可能确实如此。但是,当尝试与大型网站上的大型团队合作时,继承和级联实际上可能会阻碍您维护 CSS 的能力,而不希望大开杀戒。
就像所有事情一样,适度和计划是关键。SMACSS 概念并非关于类泛滥——它更倾向于一种均衡的方法。
根据我对 OOCSS 的了解,使用大量类似乎是最佳方法;因为——如果我记得 ShopTalk 的话——Facebook 通过这种方法设法将他们的 CSS 文件大小减少了 50%。
正如我刚刚在 CSS Wizardry 的帖子中添加的那样,我认为他帖子中的这段评论总结了这种思维过程
“…问问自己‘我选择这个是因为它是在 .header 内部的 ul,还是因为它是我网站的主导航?’”
这是一个很好的心态!
很棒的文章,Chris!
@Fulidbyte——确实,平衡可能是关键,但我对您描述的第二种情况中“语义”代码方面感到好奇。在 HTML 中,语义似乎仅存在于您用来描述内容的 HTML 标签中。但我认为这并不总是与 CSS 语义直接相关。CSS 语义应该使您的样式易于应用和更新(如果需要)。(.redThing 可能需要在一个月后变成蓝色)
如果有的话,似乎拥有更多类实际上有可能使 HTML 从开发人员的角度来看更加语义化,*只要 CSS 类在设计时考虑了可扩展性*。
有时探索这些问题也是很有趣的 :d
我不一定同意它可以简化为
可能有些情况下,设计师只希望它应用于评论中的 button 类列表项。也许非列表按钮和非评论列表按钮的样式不同。我将忽略类名的模棱两可的“button”。
让我们一步一步来。
首先,在大约 99% 具有文章和评论字段的网站上(并且每个页面只有一个,因为 #comments 是一个 ID),如果它曾经在 article 类中,它可能总是存在于 article 类中。我们可以去掉初始类。
假设设计师确实知道 html 如何工作,li 总是位于 ul 内部。需要直接后代的极端情况非常少(阅读:没有,除非您的 html 非常奇怪),因此我们可以省略它。这样我们就得到了这个
根据“button”的名称,我认为可以安全地假设它总是可点击的,因此可能总是 <a> 标签。我们可以忽略它。同样,让我们忽略直接后代,因为整个选择器已经非常具体了,除非我们的 HTML 极其混乱,否则我们可能不需要它。这样我们就得到了这个
我觉得这仍然足够具体,可以涵盖所有相同的用途,而不会变得混乱或意外地遗漏任何内容。当然,所有这些都可以通过为这个用例创建一个新类来避免(事实上,这正是我会做的),但我认为这是在保持原意不变的情况下,最简洁的方法。
非常有道理。对于那些说按钮特定于评论的人,你当然可以这样写
然后将这两个类应用到评论按钮上。这样按钮类始终保持干净,只需要进行少量修改。
为什么要费心使用
li
祖先选择器?我无法想象在什么情况下,你会想要如此具体地深入到
#comments
中的li
内的.button
,但又不想同时命中碰巧不在li
内的.button
。同样,就像你已经提到的,如果我们要处理非常格式错误的HTML,当然要尽可能具体,但在那种情况下,为什么不解决问题的根源呢?
我认为你的代码示例写错了
#comments li button {
你现在正在选择页面上的一个按钮元素。
我认为你的意思是
#comments li .button{
我知道人们说花哨和复杂的CSS选择器在技术上比更简洁的选择器“更慢”……但我认为对于大多数较小的“夫妻店”网站来说,速度差异几乎没有区别……
我个人喜欢尽可能保持我的HTML简洁,因为我相信内容的可移植性……这意味着我认为内容应该能够从一个网站提取到另一个网站……你在标记中使用的自定义类越多,这就会变得越麻烦……
此外,有时我们可能无法访问原始HTML,因此这些高级选择器可以派上用场……
我认为这些高级选择器可以使用……除非你正在构建一个拥有大量月浏览量的网站……并且速度是你最关心的问题……
同意
听起来更像是你在这里不是在讨论对错,而是在讨论懒惰与最佳实践。“实践最佳实践”从长远来看总是会让你更强大。
就像一个在油漆工作中偷工减料的油漆工。他可能在几份工作中都能侥幸逃脱,但总会有一个客户让你返工3次,直到你把它做好。
虽然我同意这篇文章中的示例将特异性带得太远了,但我不会完全反对包含父选择器。
CSS 本质上是混乱的(与 C#、HTML、PHP 等其他语言相比),我发现拥有整块的样式
当你处理一个巨大的 CSS 文件时,完全难以阅读(尝试做 SharePoint 样式……)
我发现,当我工作时,因为我不介意长水平线,我会将每个样式放在一行上,并使用它的父级作为快速找到我需要的内容的指南
我不确定会慢多少,但总有一些最小化程序,即使如此,几毫秒也值得可读和可维护的代码。
但是的,我认为每当出现“>”选择器时,你可能都需要重新考虑 CSS 的结构。只是不要太快地评判非常具体的选择器,因为它们在很多方面都有用。
我理解你的感受,SharePoint 的样式很难设置,尤其是因为在旧版本中,它不费心声明文档类型!
通常我会最终使用大量的 !important(至少在 SharePoint 中是这样):)
另外:即使它很疯狂,自从我在上一篇文章中看到“疯狂小镇”的评论以来,我一直都在脑海中循环播放那首迪斯科歌曲“Funky Town”
“你不会带我去疯狂小镇,你不会带我去……”
非常感谢!;)
哈哈,解释得很好。我喜欢疯狂小镇和快乐小镇!
我实际上发现,当存在稍微更大的父选择器时,扫描 CSS 会更加干净。它让你更了解自己的位置,而不是仅仅使用单个类来指向 HTML 中的某个位置。
想想看,你是希望你的 HTML 充斥着类,而你的 CSS 充斥着单个类选择器,从而使你的 CSS 更难扫描?还是希望你的父元素带有类,这些类指向其内部不会发生太大变化的常规元素,从而使你的 CSS 能够更轻松地扫描,同时又不让你的 HTML 充斥着类?
如果标题中出现额外的 UL 元素,则必须更改 CSS 的说法听起来很荒谬,因为如果有人真的这样做,无论如何都必须更改 CSS。
我更喜欢保持 CSS 可扫描,并且 HTML 不受类杂乱的影响,而不是仅仅为 CSS 中的每个元素都分配一个单独的类。
这就是有意义的类名发挥作用的地方,对吧?
我希望当我第一次学习父选择器时,能有人这样向我解释,感谢你又一篇很棒的文章。
哦,Chris,我不知道你如何拥有如此强大的自制力。只有你能写一篇博客文章来推广 OOCSS,却一次也没有提到“OOCSS”。 :)
你只是有一种很棒的方式,将自己定位为网页设计行业的非官方外交官。
但事实是:我们用什么流行语来描述我们所做的事情并不重要。重要的是解决方案。这就是为什么解决问题将永远是一件事,而流行语只是过眼云烟。
你知道,我使用 Sass……我嵌套代码,这样我就可以移动网站元素而不用担心特异性。我的输出代码产生了一些非常长的选择器。
大家对这篇文章以及使用 Sass 或 LESS 等预处理器有什么看法?
@David,恕我直言,SASS 在解决这个问题方面做得很好。我们的团队使用 SASS 并将所有内容范围限定得相当紧密,因为 SASS 在处理嵌套元素方面非常出色,这些元素恰当地反映了相关的 DOM。
我们的 SASS 最终可能会输出类似本文中原始示例的选择器,但也有一些例外
• 不在类中使用 #comments ID(我们尝试使用 ID 来限定页面覆盖并最大限度地减少其在子元素上的使用,因为它们会覆盖级联)
• 除非绝对必要,否则不使用 > 选择器。它非常有用,但传达了一个非常具体的意图。如果你开始毫无必要地使用它,那么其他开发人员/设计师就无法相信它是有原因存在的。
对于小型网站来说,仅仅定义一个 .button 的通用类就可以了,但任何规模较大的复杂网站很快就会变成一片相互依赖/复杂的类名海洋(“我不能为这个使用 .button,因为它是在全局定义的,我猜我应该称之为…… .cute_button”)和意外的继承(“糟糕,`.article a` 使我的锚点变为红色,并且当我在 `.article` 中放置一个带有 `button` 类的锚点时,它会覆盖蓝色的 `.button` 定义”。)
当然,也可以完全避免使用 id 和标签选择器,而是堆积类,但这更多的是哲学上的差异,而不是其他什么,这条评论已经太长了,希望它已经回答了你的问题。
太长不看:SASS 很棒
我当时也在想同样的事情。我使用 SASS 来很好地“分组”我的元素。例如,我可以编写这段非常简单的代码(假设页面上只有一种列表样式)
这显然会导致
但是,在这种情况下,嵌套已经太多了。UL LI 不是必需的,可以简化为 LI(就像 A.BUTTON 可以简化为 .BUTTON 一样)。当然,我可以以不同的方式编写我的 SASS,但同样,我喜欢这样对我的项目进行分组,有时会将元素嵌套起来,因为它们只出现在该部分。
类似地,当
h1
足够时,使用#header h1
。在 SASS 中,它只是很好地直观地显示了该项目在 DOM 中出现的位置,而在 CSS 中,它添加了一个不必要的父元素。显然这是一个非常简单的例子,但它显示了结构良好的 SASS 代码并不总是会产生经过优化的快乐小镇 CSS。
SASS 和 LESS 很好。但是,如果你在使用时不够谨慎,嵌套可能会让你陷入困境。仍然明智地进行模块化思考,这意味着要考虑 DOM 的未来更改可能对 SASS 或 LESS 代码的编写方式产生的影响。
将样式专门绑定到特定的 DOM 结构并不能提供大规模可能需要的灵活性。Chris 的示例非常具体,它很可能是有人进入了一个已经“具体”的代码库,努力使特定元素上的样式生效的结果。我以前也遇到过这种情况。
学习将样式分解成模块化、不太具体的片段的目的是允许设计元素随着网站的增长而扩展。
当以模块化方式使用 SASS 或 LESS 时,如果出于某种原因需要嵌套,请尽可能保持嵌套深度浅。例如“.comments { .button { } }” 比 “.comments { ul.comment-list { li { a.button { } } } }” 更可取。
我最近一直在尝试一种有趣的方法,用像“.button”这样通用的类来温和地指定元素。
这种水平选择器规范同时解决了非常通用的选择器问题、规则需要越来越深的冲突解决问题以及如何阐明差异的问题。此外,如果使用得当,它还可以让你在 CSS 中直接为用户需要快速理解的视觉语言建立一个自文档化的样式指南。为什么那个按钮是绿色的?因为它是一个提交按钮,就是这样。那个黑色按钮呢?哦,当然,它是取消按钮。
此外,如果需要,你可以在视觉语言中统一样式。
具体来说,也许你需要支付表单非常、非常清晰。
现在,我们深入到网站结构中并处理了特殊性,并且我们的代码没有互相干扰。
此外,我注意到,一个往往导致我们开始与自己的 CSS 作斗争的问题是,我们一开始使用非常通用的选择器名称,然后一直这样做,直到最终陷入一种类似于“电子世界争霸战”的光循环状态。我认为造成这种情况的真正问题是我们一开始就过于通用。有时,我们通过使用父选择器来获得更具体的样式来解决这个问题;不幸的是,这通常会导致陷入混乱。问题在于,这是一个语言问题,而不是代码问题。我们陷入困境是因为我们开始把所有的椅子都称为红色椅子。只有红色椅子应该是红色椅子,只有提交按钮应该看起来像提交按钮。通过这种方式使用水平选择器,我们永远不会把所有椅子都称为豆袋椅。豆袋椅舒适又柔软,椅子是用来坐的。椅子之所以舒适柔软,不是因为它在我的卧室里,而是因为它是一张豆袋椅。如果我告诉所有认识的人我房间里的每一把椅子都很柔软,我很快就会陷入混乱。相反,我告诉他们所有豆袋椅都很柔软,我的朋友们永远不会被我的办公椅弄糊涂。
我认为你是对的。每当我的 CSS 出现严重问题时,都是因为我一开始过于通用,然后添加特殊性来覆盖它。我一直在想办法让我的 CSS 更井然有序和合理,这绝对是其中一部分。
这不是最佳实践,在选择器中使用标签,例如“article .button”,网站上可能有很多类型的文章,我认为最好使用特定的文章类“.article .button”。
很棒的文章,谢谢……
不错的文章。我认为分组是更好的选择。感谢这篇文章,它很有用也很有帮助。
顺便说一句,以防万一有任何疑问 ;-) 我创建了一个基准测试来证明这篇文章——它显示更简单的选择器速度提高了 40%!http://bit.ly/ObVKpv
“很有可能,选择器应该是”
确实……很有可能。只需确保你的 CSS 选择器是正确的。确保内部的所有内容都是必要的,不要仅仅因为它们“变得太长”就删除它们。
推广短选择器的这种新炒作的危险在于,人们只记得这一点,即使短选择器不一定是更好的,也可能损害未来的适应性和性能,而性能的影响却微乎其微。
至于 HTML,这些类不会损害语义,但会损害 HTML 代码的重用。在你的 HTML 中散布像“comment-button”这样的类远非明智之举,它限制了你的 HTML 代码在其他项目中的重用。
我承认,在大多数情况下,“疯狂城镇”选择器很可能可以改进。我只是说,你不应该仅仅根据这一点来判断某人的 CSS,除非你确定你理解它如何改进以及开发人员/设计师首先使用这种选择器的原因。
如果你在一个开发人员/设计师从头开始创建并完全控制的项目中看到这样的东西,当然,它肯定可以改进。但是有很多情况是你正在修改一个现有的网站,并且你没有选择丢弃遗留代码。那个“疯狂城镇”CSS 可能是由 Drupal 模块生成的“疯狂城镇”HTML 的副作用。
我不是设计师,我相信我的博客有很多“疯狂城镇”选择器。其中一些来自插件。其中一些是我自己的(可能是为了覆盖插件中的某些内容)。一方面,我不希望有人根据我博客上的 CSS 来判断我的整体技能。但另一方面,我认为“疯狂城镇”选择器应该在用来判断 CSS 代码质量的事项列表中处于较低的位置。如果你确实看到了它们,也许你应该看看是否有某种原因。
如果我必须编写疯狂的选择器来覆盖 CMS 生成的某些内容,我会这么做。我并不总是有选择更改生成原始 HTML + CSS 的代码。
再说一次,这是我作为开发人员(而不是设计师)的观点,以及我处理至少更换过一次手的项目(主要是 Drupal,最近是 WordPress)的经验。每当我看到 !important 时,我的大脑都会尖叫,因为它通常意味着我最终会编写我自己的、更具体的 !important 规则,我内心会感到一丝痛苦。
我认为 SMACSS 方法无疑是一种避免不必要的特殊性的好方法,并且具有不与特定元素绑定的额外优势。
我非常喜欢采用模块化方法,例如
只要确保你的元素上没有出现数不胜数的类(如果这样,那么你显然抽象过头了),这是一种很好且非常易于维护的 CSS 方法。
此外,我认为基本原则应该始终如下:使标记尽可能具有语义和合理性;完善它,以便你的文档和数据真正得到结构化,然后只在明确需要的地方进行样式设计,并在你进行抽象的过程中尽可能地进行抽象。
天哪,我爱前端!:-D
如果我使用 less 或 sass 并且我只是喜欢嵌套选择器怎么办?
并且它输出为以下内容
这算是一个正当理由吗?
嗨,Enrique,
总的来说,在 SASS/LESS 中反映你的 HTML 结构是一种不好的做法(尽管很诱人),因为它会创建不必要的选择器,随着项目的增长,这些选择器会变得越来越复杂。
我认为你首先需要掌握 CSS 才能有效地使用预处理器。如果你对“幕后”发生的事情没有很好的理解,那么你的 SASS/LESS 最终也会效率低下。
我不经常使用 SASS(遗憾的是),但当我使用时,我喜欢创建“占位符”类以提高可维护性,如下所示
这样,你最终会得到像这样的好代码
你的代码检查器也会喜欢它 ;-)
我会直接使用
添加“a”标签而不是一直回到顶部!不是吗?
a.button 太具体了,这里不需要元素(也不够灵活)。
.button 就足够了 ;-)
特殊性是魔鬼!
哈哈!我同意!
非常搞笑。我对特殊性感到非常困惑
我做开发已经超过 30 年了,如果说有一件事我非常重视,那就是可维护性。除非速度至关重要(例如空中交通管制系统),否则在代码有效性之后,可维护性是最重要的要求。然后是注释。效率排在非常遥远的位置。沉迷于令人惊叹的聪明才智会立即取消某人接近代码的资格 :-)
这不仅仅是善待新手的问题:复杂的嵌套和继承由于短期记忆容量有限而本质上难以阅读。理解它们需要比阅读简单语句更多的时间。结果,维护成本飙升。然后是技术和编码风格的变化。在 CSS3 中可能易于理解的东西对于习惯使用 CSS15 的人来说可能完全令人费解……(别忘了,仍然有一些系统运行着 20 世纪 70 年代编写的代码——谁知道 Web 系统是否会拥有这种持久性?)
当然,可以在虚荣网站上使用聪明的东西,但对于严肃的系统,请保持可维护性!
这就是我现在正在努力解决的问题
.menu2 > li ul:hover > li ul
和
.menu2 > li:nth-child(3):hover ~ li
呵呵..