面向对象的CSS:响亮的流行语还是合法的设计方法?

16

看起来在Web开发领域中出现了一个新的流行语:面向对象CSS。

表面上看,这似乎只是将最佳实践打包成一个 catchy 的口号。我理解并完全尊重该运动背后的意图,但它是否有更多深层含义?

是否有人有更深入的见解,将此方法与其他方法区分开来,使其更加可信,还是我应该将其视为提醒自己确保正确地继承和级联我的类?

10个回答

10
我认为这更像是对CSS中已有内容的一个引人注目的流行短语。当然,在我们开始讨论什么是面向对象,什么不是以及CSS如何面向对象之前,我们必须定义它实际上是什么 - 这是其他人之前曾经努力过并且存在激烈争论的问题。但是,如果我们假设面向对象的基本原则包括:

  • 对象
  • 实例
  • 方法
  • 消息传递
  • 继承
  • 抽象化
  • 封装
  • 多态性
  • 解耦

我们可以说,层叠样式表在某种程度上是面向对象的,因为它们允许定义类,创建实例/对象(通过将类分配给元素),类的继承(甚至支持多重继承),抽象化(例如,通过为纯元素定义样式)和多态性(通过为不同的元素定义相同的类名)。当然,由于CSS的静态特性,方法/消息传递是不可能的。

因此,总体而言,我认为以面向对象的方式开发CSS是一种有效的方法,但我不会真正称其为面向对象的CSS,因为至少对我来说,这是CSS固有的特性。这有点像说“我正在做面向对象的Java…”


我喜欢这个论点。我认为它很好地回答了问题,但同时也提出了一个新的问题:网页开发人员是否忘记了如何构建形式良好的样式表?或许可以稍后再探讨这个问题。 - Phil.Wheeler
6
这完全忽略了OOCSS的重点。CSS很难封装(看看嵌套显示类型时会发生什么),而“最佳”实践往往会阻碍DRY原则的使用(例如,不要使用表现类名称)。Nicole Sullivan的OOCSS概述了原则,使您能够以模块化、可维护的方式实际上使用CSS。 - theazureshadow
@Phil.Wheeler“回答问题得当并提出了一个新问题”不是。正是这个新问题首先引发了OOCSS术语的产生,以描述一组原则和模式,使CSS可以以干燥、一致的方式使用。如果没有意识到OOCSS术语在CSS社区中的使用方式,当它已经回答了那个“新问题”时,对第一个问题的回答就不够好了。 - Barney

5

吸引眼球的流行语和合法的设计方法。

尽管我认为其中一些想法有点幼稚,它们倾向于忘记“客户随着开发而不断更改”的网络开发范例。


1
嗯,我想我不应该那么大声地说出来 ;) - Julian Aubourg

4
我认为将其称为“面向对象的CSS”是一种热门用语,实际上会减少其有用性和更广泛的采用。当我了解它时,我认为宣称它是面向对象的实际上减缓了我对它真正含义的理解。了解编程中“面向对象”的人会持怀疑态度,因为它不是真正的面向对象,是吗?这只是尝试将一些面向对象的原则应用于CSS以提高其效率。另一方面,如果客户端开发人员不是程序员,则大多数人将无法理解此概念,因此他们将感到困惑或尴尬。所以,这是一个很棒的概念,需要重新命名。极致CSS!强力CSS!CSS重生!CSS平方!CSS Prime!类似这样的东西。

3
我一直在同时使用OOCSS和B.E.M.命名约定,永远不会回头。那些声称这只是“流行词”或者“CSS已经能做到这个”的人,不理解用这两种方法编写CSS的潜力。
让我们来看看最简单的对象——一个带有链接的列表。它有许多不同的呈现方式:
1. 菜单 2. 工具栏 3. 选项卡 4. 面板(Bootstrap)
在OOCSS中,我们找到每个对象的共同属性并创建一个基础对象。我通常称之为“nav”。
/*  Nav
    =================================================*/

    /*  B
        ---------------------------------------------*/

        .nav
        {
            margin-left:            0;

            padding-left:           0;

            list-style:             none;
        }

    /*  E
        ---------------------------------------------*/

        .nav__item
        {
            float:                  left;
        }

        .nav__link
        {
            display:                block;

            color:                  inherit;

            text-decoration:        none;
        }

    /*  M
        ---------------------------------------------*/

        .nav--right
        {
            float:                  right;
        }

        .nav--stack .nav__item
        {
            float:                  none;
        }

您会注意到以下几点:
  1. Nav是应用于块元素的基本对象

  2. 子元素以nav_为前缀

  3. 修饰符以nav--为前缀

  4. 修饰符是更改行为的选项。例如,--right使导航向右浮动。

一旦我编写了我的基本对象,我会创建皮肤来改变对象的外观。这将把它变成工具栏、选项卡等。微软在手机上有Pivot选项卡。现在创建一个更容易的皮肤。
/*  Nav
    =================================================*/

    /*  E
        ---------------------------------------------*/

        .pivot .nav__item
        {
            margin-left:            24px;

            color:                  #aaa;

            font-size:          36px;
        }

        .pivot .nav__item--active, .pivot .nav__item:hover
        {
            color:                  #000;
        }

要使用此对象和样式,您需要编写:
<ul class="pivot nav">

   <li class="nav__item">

        <a class="nav__link"> Item 1 </a>

    </li>

   <li class="nav__item">

        <a class="nav__link"> Item 2 </a>

    </li>

</ul>

由于其位置独立性,您也可以将其编写为:
<nav class="pivot nav">

   <div class="nav__item">

        <a class="nav__link"> Item 1 </a>

    </li>

   <div class="nav__item">

        <a class="nav__link"> Item 2 </a>

    </div>

</nav>

最终,您正在将容器与皮肤分离。我建议从Nicole Sullivan的Media Object开始更小地开始。查看Twiter Bootstrap和Inuit.css以获取更多灵感。


好的,所以我希望为所有位于应用程序中出现在各种地方的某种部分内的导航元素添加修饰符。由于某种原因,我发现采用inline-block比浮动方案更有优势。为什么我要寻找每个具有这些部分之一的模板并在HTML中添加nav--<modifier>,而不是为选择器#annoying_section_2chng .nav > <some element>编写属性定义呢? - Erik Reppen
'OOCSS','SMACSS'和'原子设计'实际上只是指称相同的设计模式的不同流行语。然而,这是一种非常有用的设计模式,我基于它开发了自己的CSS框架(http://www.cascade-framework.com/)。但我不喜欢BEM语法。对我来说,BEM太啰嗦、太受限制,而且太难看了。事实上,我甚至可以说,BEM消除了使用OOCSS、SMACSS或者你想怎么称呼它们所获得的许多优势。 - John Slegers

3
我希望您能为后人编写此答案。上面的所有答案显然都没有听说过面向对象的CSS这个严肃的话题。当提问者询问它是否是一个时髦词汇时,这应该表明该表达式指的是值得讨论的主题(比“我们通过面向对象意味着什么”更值得讨论)。
我相信“面向对象的CSS”是由Yahoo前端技术传教士Nicole Sullivan创造的一个术语,她在咨询Facebook将演示性前端代码重构为更轻巧、更易于管理、可以随着时间的推移轻松扩展和修改的东西之后。术语“面向对象”并不是指CSS本身的特性(就这样),而是一种编写CSS和受影响标记的方法,有助于简洁和可扩展性。
OO CSS的一些示例原则包括:
  • 避免使用ID作为选择器:一个对象是唯一的并不意味着它的关键属性应该被定义在这样一种方式下,即它们覆盖所有其他属性。
  • 避免基于嵌套标记的长选择器:根据文档结构中的偶然位置来定义元素的外观通常是一种逻辑谬误,将其移动到新位置将强制您重新编写选择器。与上述情况类似,这种不良实践还导致条件性覆盖或扩展需要在其选择器中具有额外的强度和特异性,这很少有帮助。
  • 使用非语义化标记创建具有不同表示目的的元素,而不是尝试将单个元素的所有细节重载到一个规则中。这会导致CSS更简洁。

OOCSS的最终目标是DRY。当您实际上正在创建类似事物的变体时,不应编写成千上万行的CSS。

Nicole在这个主题上做了一些好的演讲 - 她还写了一些文章,扩展了一些有用的技术并避免了一些不良实践

'OOCSS'也是她编写的框架的名称,该框架提供了可扩展CSS布局的样板代码。为什么这个框架如此出色(网格模块几乎在我使用的所有地方都被使用)并不完全自证不疑,阅读她关于背后思想的博客文章肯定有助于更好地使用它和CSS。


IDs在使用得当时可以减少冗余。具体性是一种工具,而不是敌人。删除特定性的整个层次将最终导致选择器数量的冗余,这在我看来是真正的敌人,而不是IDs。当重复使用的元素需要在新上下文中进行变化时,IDs是完美的选择。在我看来,它更接近于分类法而不是OOP。即使在CSS中,DRY也是一个很好的气味测试,但最终我们谈论的是布局和设计。两个设计元素很容易具有几乎相同的属性集,同时对值得分离的设计的不同方面做出贡献。 - Erik Reppen

3

我已经说了这个观点多年了。

CSS选择器基于实例ID和类。它甚至支持多重继承。这还能更明显吗?

将CSS视为对象的美妙之处在于,开始“转换”您的标记元素变得非常简单。需要让那个div突然变成INotRenderedAnymore吗?只需让JS扩展其类属性以匹配.removed,不要玩弄样式属性。

显然,这是一个相当平凡的例子,但好处应该是清楚的 - 特别是在JS操作的情况下。您可以将JS与其必须修改的实际样式分离开来,这既是维护和抽象的优势,而且还有像不直接设置非常高特异性样式(CSS无法覆盖)等附加好处。


所以这又回到了“渐进增强”的理念。为了实现关注点分离(内容、表现、行为),你需要确保你的 [css] 类按照最佳实践进行结构化设计。 - Phil.Wheeler
是的,完全正确 - 如果你把CSS看作是面向对象的术语,这是一个简单的方法。 - annakata
在我看来,ID更适合被视为多态性。当某些常规内容在不同的上下文中被重复使用时(任何在ID范畴下的元素),可能会有变化。在CSS中最接近“实例”的是HTML + CSS的最终呈现。 - Erik Reppen

2
术语“面向对象的CSS”是一个误称。
“面向对象的CSS”实际上只是一种设计模式,用于如何充分利用您的CSS,并基本上是Jonathan Snooks所称的SMACSS相同的方法。
无论您将其称为OOCSS还是SMACSS,该方法的关键在于创建通用的UI元素,例如导航抽象。然后,可以通过向元素和/或容器元素添加额外的类别来增强这些UI元素的更具体功能。或者,作为替代方案,您可以使用元素的ID或语义类别添加自定义CSS规则。 Cascade Framework是一种全新的基于此方法的CSS框架。它只有微小的占用空间,但提供了最佳性能、最大的灵活性和最佳的模块化。

1

CSS在许多方面类似于面向对象编程语言:编写

p { color: red }
p span { color: blue }

而你基本上就有了继承。以下是更复杂的例子,将看门狗(terrier)继承自狗(dog),再由狗继承自动物类:

.animal { font-weight:bold; color: blue; } 
.dog:before, .terrier:before { content: "GRRR"; }
.animal, .dog, .terrier { color: brown } 

现在你可以以面向对象的方式使用动物、狗和梗类。

需要记住的是,CSS非常擅长解决它所设计用来解决的问题:以透明的方式指定元素的样式。如果加入更多面向对象的概念会更好吗?我不确定。假设有人说:如果CSS文件看起来像这样,那么它会更简单:

@class dog @derives_from animal /* the syntax i just invented */
@class terrier @derives_from dog

.animal { font-weight:bold; color: blue; } 
.dog:before { content: "GRRR"; }
.terrier { color: brown } 

这看起来更简单,但更简单的解决方案是在服务器端删除@class thing,同时将“dog”添加到任何“terrier”和“animal”添加到任何“dog”(使用简单的替换语句)或使用JavaScript。

CSS最好的一点是它很简单,并且很容易回退,这意味着浏览器不需要解释他们不理解的CSS,事情可以相对顺利地进行。由于您必须打破与主要新CSS结构的向后兼容性,我认为这使面向对象的CSS更像是一个流行词汇。


0

我认为这不是什么难事。

OOCSS 面向对象的层叠样式表

它减少了重复编写的代码量,你可以设置foocontainer的全局CSS,然后在任何地方重复使用并为headerbodyfooter设置自定义样式。

<div class="foocontainer header"> Your header </div> <!-- two classes -->
<div class="foocontainer body"> Your body </div>  <!-- two classes -->
<div class="foocontainer footer> Some footer </div> <!-- two classes -->

BEM 块--元素__修饰符

这使得代码易于阅读但难以书写,您可以轻松地识别它们的子元素和父元素。

<div class="foocontainer--header"> Your header </div> <!-- one class -->
<div class="foocontainer--body"> Your body </div> <!-- one class -->
<div class="foocontainer--footer> Some footer </div> <!-- one class -->

0

这确实是像表格 VS div等等那些争议性的事情之一。

在我看来,有很多开发者太过于沉迷于面向对象编程(OO)以至于他们试图将其用于任何东西,首先是JavaScript,现在是CSS。别误会,JavaScript也有OO的元素,但我们不谈论这个。

由于CSS本身已经是一个热门词汇(所有雇主都想要Web 2.0的CSS方法),所以许多新开发人员正在发现它。这不是件坏事,但是作为开发者,他们会尽力改进CSS。在开发者的想法中(我是一名开发者),按照面向对象的原则组织CSS非常合理 - 因此出现了新的热门词汇。

最终我想说的是,面向对象的CSS只是某些人采取的一种方法,因为它似乎更合乎逻辑。如果您编写的CSS将由开发人员维护,那么这种方法很适合。它真的取决于你如何编写CSS和你自己的个人风格...

就我个人而言,我不在意人们如何编写他们的CSS - 如果我需要维护它,Firebug可以轻松完成这项工作。


我确实关心如何编写自己的CSS,这样人们就不会产生错误的想法 :) - Darko
表格与DIV的选择是无法争论的,这其中有对错之分,唯一的讨论在于一些人认为“它能用,表格也行”是一种实用主义的解决方案,而另一些人则觉得这等同于放弃。GOTO语句也“能用”,但没有人使用它是有原因的。 - annakata
这就是为什么我说它是可以商榷的 - 实用主义 vs 风格,你不需要向已经信仰相同的兄弟传教。好吧,我并没有被“转化”,我从来没有真正使用表格进行布局... - Darko
虚假的经济效益与学习CSS更相似,但我已经注意到了我的反表格同事 :) - annakata
仅供记录,我喜欢面向对象编程和CSS,但我讨厌人们在CSS上使用面向对象编程。@annakata 大约10年来,由于IE无法跟上CSS2所建立的Netscape Navigator circa 2002ish上的表格显示属性,因此无法垂直居中高度未知的元素。实际上有一个高度特定的参数很长一段时间,但是,如果您不支持IE<=7,则目前没有这样的参数,尽管我仍然认为那些表格显示属性有点脆弱。 - Erik Reppen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接