假设您有一个模块。每个网站都有模块,对吧?
<div class="module">
</div>
完美!我们做到了!
但现在,出现了“新情况™”。此模块不会完全按原样工作。它非常接近,但在这种“新情况™”中,模块将需要一些额外的底部边距。
您如何处理这种情况?让我们探索一些方法。
主体类影响它
您网站的特定页面或区域上的所有模块是否都像这样?也许您可以在该页面(或区域)中添加一个类。
<body class="books-page">
...
<div class="module">
</div>
.module {
/* normal style */
}
body.books-page .module {
/* variation styles */
}
您实际上不需要限定 .books-page
,但我经常这样做,因为在这种情况下这没什么大不了的,并且可以提醒我正在发生的事情。
Sass 在这些情况下很有用,因为嵌套有点将房间连接在一起。
.module {
/* normal style */
aside.books & {
/* variation style */
}
}
全新的类
也许新样式足够不同,以至于您将为其命名为不同的东西。
<div class="solitary-module">
</div>
.module {
/* normal style */
}
.solitary-module {
/* alternate style */
}
如果样式非常相似,您可以
.module, .solitary-module {
/* normal style */
}
.solitary-module {
/* variation styles */
}
这正是 Sass 中 @extend 的作用
.module {
/* normal style */
}
.solitary-module {
@extend .module; /* could be a %placeholder selector */
/* variation style */
}
叠加类
也许您创建了一个额外的类,但该类并非旨在独立工作,它只是一个变体。
<div class="module module-books">
</div>
.module {
/* normal styles */
}
.module.module-books {
/* variation styles */
/* you don't HAVE to double up the classes here in the CSS, but it enforces the connection (while increasing specificity) */
}
数据属性变体
我认为这并不常见,但我有点喜欢它。
<div class="module" data-variation="books">
</div>
属性类似于类(相同的特异性),但可以具有值。
.module {
/* normal styles */
}
.module[data-variation="books"] {
/* variation styles */
}
读起来很不错。
内联样式
这种变体很少见吗?也许只需要内联样式即可。
<div class="module" style="margin-bottom: 40px;">
</div>
通常不被推荐(不可重用),但如果是一次性的事情,它可以完成工作。
Shame.css
您始终可以使用 shame.css 稍后处理它!
<div class="module chris-did-this">
</div>
/* I will totally deal with this later I promise */
.chris-did-this {
/* variation styles */
}
你是怎么做到的?
数据属性旨在承载数据,因此使用它来设置样式感觉很奇怪。
我个人更倾向于“添加额外类”(叠加)来实现不同变体。它感觉“正确”,并保持模块化方面。
我同意您的观点,数据属性旨在承载数据,但它也可以用于样式,因为我们希望减少添加到 DOM 中的类的数量,并且很多时候数据属性有助于使代码更具语义。
任何使代码更少、更简洁的方法都应优先考虑。
我个人使用“添加额外类”或“主体类影响它”的变体。它们简单易用,可以防止您弄乱样式表。但是,如果我发现自己多次执行此操作,我会返回并重新创建它以使其更灵活。
数据属性的妙处在于,您可以完全跳过添加类,而只需利用属性。
例如,这可能是一个默认模块
这可能是一个花哨的模块
CSS 非常简单
您还可以使用
[~=]
选择器创建您自己的自定义模块特定“类”看来我的一些代码块不太正确
默认模块是
花哨的模块是
嗯,我非常喜欢这个想法..
问题是,这些数据属性比类更具语义,还是更少?此外,您何时选择使用哪一个?
我个人是“全新的类”方法的粉丝,因为其逻辑类似于 OOP 原则,其中类名的格式将为
.super-class--sub-class
。这允许常规类名使用连字符,而双连字符表示超类正在被子类扩展,子类可以在其中添加规则,并且可以覆盖从超类继承的规则。
坏主意。人们会认为您正在使用 BOM,并且会混淆您没有使用它。
干杯。
我必须同意,我认为这不是一个好主意,并且并没有真正暗示 OOP 继承原则。例如,考虑一个 Java 类。已经有一段时间了,但如果我记得没错,它类似于 public Mustang extends Car{}(我已经使用 C# 多年了,但许多语言都使用类似的语法)。您暗示的几乎是相反的,并且如果没有预处理器,它将与继承完全相反,因为您需要维护两个 CSS 类,而当基类发生更改时。
也就是说,我喜欢人类可读的双类样式。在编程语言中,是的,基类最后出现,而在标记中它首先出现,但这并不是一个复杂的概念,并且更符合程序员的习惯,最终我们希望进入一个分离关注点的世界,其中处理样式的人员不需要也是编写 HTML 的人员。我们使应用样式变得越简单越好(类加类加类等于结果),而不是例如,浏览样式指南以查找带红色背景的强调按钮的特定类。
此外,您将创建许多几乎不使用的类,并为非常具体的情况增加负载,而不是促进可重用组件。
编辑(我是否错过了什么,或者我无法从平板电脑编辑我的原始帖子?)
我明白了您所做的事情实际上不会违反继承规则,尽管它确实使它们变得复杂,因为创建了多个变体,最终用户需要浏览这些变体才能获得他们需要的东西,而不是组合类。它还为少量回报创造了大量开销。我确实为错误地暗示您需要使用您的模型更改基类和子类而道歉,但仍然坚持认为,越具体的子模块,需要为每个实例添加新类而不是拥有可处理的通用类来构建模块,将需要更多的维护。请原谅我,我正在使用平板电脑,现在是凌晨 2 点。但我仍然坚持我的立场 ^_^
感谢您的反馈。建设性的批评总是好的,我确实承认此模型并不适用于所有项目,而且我多次需要改用双类模型。
@wqeqwewq 我不熟悉 BOM 这个术语,谷歌搜索也几乎没有结果。如果您指的是类似 BEM 的东西,我确实明白了您的意思,它可能会造成混淆,但这只有在与团队合作或将内容发布到公共 Web 开发社区时才是一个问题。
Eric 的观点很有道理,但是除了这两个示例的命名和格式背后的理念之外,我并没有看到任何技术上的差异:
.baseclass--modifier
和.superclass--subclass
。关于父类和子类的顺序,你是正确的。PHP、Java 和 ActionScript(以及其他一些语言)都使用Subclass extends Superclass {}
的语法结构。我对此非常清楚,并且有意地以这种方式格式化 CSS 类,因为至少对我来说,它可以更快更容易地了解类的作用,并使 CSS 文件中的内容保持井然有序。至于随着模块变得越来越复杂而产生的问题,因此需要一个全新的子类,你确实说出了一个很好的观点——收益甚微,却增加了额外负担。克服此问题的一种方法是将双类模型(作为实用程序类)与父/子类模型混合使用。
在与团队合作或向公众发布时,我当然会遵守已有的样式指南和格式模型,但在我的个人项目中,此模型对我来说效果很好。也就是说,我感谢你的评论,并且需要重新考虑这个模型是否最适合我。
抱歉,意思是 BEM,不是 BOM
http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/
大多数时候我“重复使用类”,尽管如果可以避免,我很少在我的 CSS 中采用这种级别的特异性(例外情况是类的状态,例如
is-active
)。如果我觉得新模式现在很相似,但将来有很高的风险会以戏剧性的方式分裂,我会抛开谨慎,在完全独立的模式中重复内容。但这种情况很少发生。而且我不反对偶尔采用
shame.css
技巧,尤其是在截止日期临近的时候。“真正的艺术家会交付成果”,诸如此类。伙计们,这正是我们拥有“实用程序类”的原因。
只是为了添加一个边距,是的。但是实用程序/辅助类不是为了扩展其他类。
是的,没错。我应该更具体地说明我的意思是针对这个具体的例子。
对于一些可能是一次性的微小调整,我使用实用程序类。如果我觉得我添加的太多,并且这种样式会被使用多次,则将其设为组件修饰符或新组件。
每种情况都需要不同的解决方案。了解选择哪种合适的解决方案需要经验以及维护大型项目较长一段时间。
Nicolas Gallagher 在 CSSconf AU 上发表了一个很棒的演讲,谈到了这一点以及如何谨慎对待抽象。
这正是我最初的想法。有一些实用程序类具有标准化的边距“间距”量。在 Sass/Less 中将其设为变量。如果正常的边距间距变量太大,我甚至还会使用一个半间距变量。
我很多次都使用过双类,但是如果你最终拥有超过几个变体,管理起来通常会很痛苦,尤其是在你想要编辑基础样式时。
现在我可能会将模块包装在一个 div 中并设置该 div 的样式,但我最喜欢的处理方法是:
(使用 Less)
.module-styles(){
margin: awesome;
border: snazzy;
…
}
.module-foo{
.module-styles();
margin: ballin’;
}
.module-bar{
.module-styles();
margin: stellar;
}
渲染的 CSS 具有冗余样式,但是如果你的应用程序在 2014 年对性能敏感,我不知道你在做什么。通过在“语义”类定义中覆盖样式,你无需考虑类特异性,只需考虑样式顺序,我发现这简单得多。
如果你使用 BEM 样式(我喜欢称之为 GRM——组、角色、修饰符 :))
http://codepen.io/anon/pen/dqGyr
我不久前偶然发现了这一点,这就是我的做法
这样双重声明有什么原因吗?
可能是为了旧版浏览器的回退?
(顺便从 24ways 获得的。如果有人感兴趣,请看这里:http://24ways.org/2012/a-harder-working-class/)
@Ralfff,这样做的原因是,如果在页面上加载的 CSS 中(也可能是第三方 CSS)碰巧有类似
.awesome-modules
或.user-feedback-module
的内容,那么你的样式([class*=module]
)将被应用,并且你将不得不重新定义它们。虽然如果你遵循 BEM(我再次称之为 GRM :)) 使用的命名约定(http://bem.info/method/definitions/,http://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/),其中你将 CSS 类的命名分为 3 部分:.group--role__modifier
,例如(仅凭脑海中的想法 :)):.button, .button__primary, .button__primary--alternative, .button--icon, .button--icon__arrowUp
,你不太可能遇到这种情况。我可以猜到你可能感到困惑——我极不可能遇到这种情况,如果发生了,那么我可以调整特定情况下的样式。这是真的,当你与 1-2 个前端人员一起处理项目时。就我而言,我正在处理一个大约有 30 名开发人员的项目,他们都可以为 CSS 做出贡献,因此对我们来说,制定这些约定非常重要。但是如果我离开这个项目并开始自己工作,我仍然会使用 GRM。
@所有人,抱歉造成混淆,我想使用
--
作为修饰符,__
作为元素分隔符很常见,而在我的示例中,我将它们颠倒了 :)双重声明的原因是我希望样式仅应用于与
.module
匹配的元素,其中该模块具有修饰符的元素[class*=module__]
将应用于.module__books, .module__whatever, ...
。啊,好吧,有道理。看来我需要“重写我的框架”了。
我主要从事小型到中型项目(2 名开发人员),并且熟悉 BEM 方法。我的 CSS 松散地基于此,但从未使用过
__
和--
。对我来说,单个连字符就足够了。谢谢 Sergey。
为什么不使用 ID 而不是类来设置主体样式?
ID 是邪恶的。不用多说。
ID 太过具体,难以(更难)覆盖。类可以做完全相同的事情。
我完全放弃了 CSS 中的 ID。
我仍然在 HTML 中将它们用作锚点,并在 jQuery 中使用它们。
如果我必须将它们用于样式(例如,为 WP 插件或其他人的代码设置样式),我将使用属性选择器 [id=”name”] 作为目标,因此它们的特殊性与类相同。
“不用多说”是邪恶的。
@Ralfff 使用属性选择器避免 WP 插件出现特异性噩梦的巧妙方法。感谢分享!
哈,没问题。但公平地说,我并不那么聪明,Harry Roberts 才是。
http://csswizardry.com/2014/07/hacks-for-dealing-with-specificity/
额外的类!一段时间以来我一直习惯这样做。
……哈哈,@shame.css 哈哈
我会重复使用类,在 Chris 的示例中,模块除了底部有一些额外的边距外,其他方面都是相同的。它实际上是模块对象的扩展,因此在我看来,这是正确的方法。
** … **
第三次幸运……我选择 alpha 类来防止类名与内容绑定,我们永远不知道它将来是否会被重新用于完全不同的东西。
重复使用这些类,并使用一些命名约定。去年的 Smashing Mag 关于伦敦泰晤士报网站重新设计的文章促使我详细说明我的方法和命名约定。
主要使用扩展类 BEM 样式
有时在 body 或 HTML 元素类上,例如使用 WordPress 时,会自动为特定页面插入 body 类,而当我懒得向服务器端代码添加其他参数时。
当添加到 body 或 HTML 元素时,我创建一个 mixin 以使更改更容易,并在使用时减少错误。
Mixin 会带来额外字节的代价(当然这可能并不关键)。你如何看待我的解决方案:https://css-tricks.cn/design-pattern-breaks/#comment-1584654?
这取决于模块的用途。如果模块是真正自包含的,可以在许多页面和许多上下文中使用,那么它可能根本不应该包含任何布局类型的规则。布局规则包括浮动、宽度、边距等。
我会将这些可移植模块嵌套在更通用的布局模块中,这些模块将用于模块间的定位。HTML 看起来更丑,而且可能接近 div-itis,但 CSS 非常干净且可移植。
恭喜你是第一个讲清楚的人:) 我会添加示例
目前我尝试使用双重类而不重复名称的一部分.. 类似于
因此我必须首先更具体。
它远非完美,但我喜欢可读性…
我会将类加倍,但要确保这些类是模块化的。我将使用 OOCSS 来做到这一点,添加一个 .mbm 类(margin-bottom: $medium)
我思考过很多次。现在我使用 BEM 的“方式”,使用 class=”module–solitary”,然后在 .less 文件中
Vito
最常用的是
body.contact .aside_module
。但我真的不反对使用内联样式,甚至“块”,因为通常没有足够的字节来减慢我的页面速度,而且肯定不足以证明额外的请求是合理的。我一直喜欢使我的样式表尽可能通用,因此内联样式也让我可以保持样式表的整洁。我尝试将
[data-*]
用于仅限 JavaScript 的内容。我将阅读那篇 shame.css 文章。听起来这可能是一个不错的选择。
我使用额外的类和 Sass 中的 @extend。感觉正确、简单且易于更新/删除。
我通常尝试将类加倍,除非它是一次性的,在这种情况下,我将使用快速内联样式或上面演示的稍微有点“丢人”的方法。在我的工作中,我遇到了很多需要调整边距的情况,因此我有一些通用的边距样式。我通常提供如下内容
其中 m 代表“margin”,p 代表“padding”,t 代表“top”等
.mt10 { margin-top:10px !important; } .m10 { margin:10px !important; }
!important 仅存在是因为我处理了许多其他人的代码,其中继承通常无法立即得知,因此这些快速修复类可以节省大量有关间距问题的时间。
我倾向于将类加倍
.module.module-books
。但最近我的标记开始看起来有点乱,我似乎有时需要大约 7 个类,这我并不太喜欢。但这主要是在.grid
元素上。假设模块也可以是.grid
…大多数情况下,我使用“加倍”类。如果它只需要一个常用的属性(如 margin-bottom),我通常会为它创建一个辅助类
.md
(用于 margin down)并将其添加到 html 中,如果它是实际的变体,我会选择.module-variation
。我有时使用 body 类,但主要用于 javascript..
我通常使用修饰符类。从未使用过内联样式!
这取决于,如果我只需要添加一些底部边距,我通常会有一些辅助类,例如 .margin-bottom、.margin-bottom2x、.margin-top 等。
然后我只需添加修饰符类。
添加一个额外的类!过去我可能会使用模块扩展,但最近我一直很喜欢 Inuit 风格的辅助类。因此,我并没有添加
.module-books
,而是添加了诸如.push--bottom
之类的内容(我一直在使用 Inuit 5;https://github.com/csswizardry/inuit.css/blob/master/generic/_helper.scss)这里对于这种“新情况”的关键在于,额外的底部边距可能会成为再次出现的某种设计模式。这种抽象虽然几乎过于简单,但对我来说非常有用。
我投票使用新的样式!如果使用 SASS,请导入基本样式的属性。
双类对于组织很有用,但我坚持我的第一行。
我会这样做。如果只是颜色、填充等的变化..
我尝试使用块元素修饰符方法。在这种情况下,我可能会使用基本
.module
类,然后对于额外的边距,我会使用类似.module--dbl
的内容(或类似的内容,具体取决于边距增加多少以及是否围绕所有边距还是仅在特定一侧(顶部、左侧、底部、右侧)。你总是可以语义化地命名模块
“
然后在 scss 中
.user-biography { @extend %module; padding-bottom: $bigPadding; }
嘿,Chris,很棒的文章!
我通常的做法是将类加倍,我个人称它们为“修饰符”。我认为这样可以保持良好的可维护性,并且可以很好地与 Twitter Bootstrap 配合使用。
但是我喜欢 Data 属性的变化,它们非常简洁。它非常类似于来自 GitHub 的 AMCSS 样式:http://amcss.github.io/
之前有人尝试过这种风格吗?