Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

浅析 Bootstrap 的 CSS 类名设计 #45

Open
cssmagic opened this Issue Apr 6, 2014 · 26 comments

Comments

Projects
None yet
9 participants
Owner

cssmagic commented Apr 6, 2014

浅析 Bootstrap 的 CSS 类名设计

最近在重新设计一个 UI 框架,因此也在考察同类项目的特征和要素。在读到《Bootstrap 编码规范》时,顺着链接发现了其作者 @mdo 的一篇文章,其中讲到 CSS 类名的设计思路。


[译] 使用前缀来限定 CSS 类的作用范围

When building a CSS design system like Bootstrap, it's important to keep things simple, durable, and flexible. This is no easy task, especially on larger teams and projects where the number of components can become quite high. To help improve this situation in a CSS design system, you might consider using prefixed classes instead of chained classes.

在构建类似 Bootstrap 这样的 CSS 系统时,保持系统的简单性、稳定性、灵活性是相当重要的。这并非易事,尤其对于大型团队和项目来说,组件的数量可能会变得相当庞大。为了改善这种状况,你不妨考虑用前缀式类名取代链式类名。

Taking the chained classes approach, your CSS selectors might look something like this for a given set of components:

在使用 链式类名 方案时,你可能会把一系列特定组件的 CSS 选择符写成这样:

.success { ... }
.btn.success { .. }
.alert.success { ... }

We have here a global base class, .success, that might house all the commonalities between successful buttons and alerts. Then, at the individual component level, we add on or override as necessary. However, this wide open class and chained approach exposes developers to a number of questions and potential paint points:

我们在这里设置了一个全局基础类 .success,它可能涵盖了成功按钮和成功提示框之间的所有共性。然后,在单个组件层面,我们又需要对它进行扩充或覆盖。但是,这种完全开放式的类名和链式风格令开发者面临一些困扰和潜在痛点:

  • What's that base class stand for
  • What elements will be affected at the root level
  • How many elements have .success chained onto them
  • Can it be extended further to more components
  • What if one instance of .success uses green text on a white background while another uses white text on a green background
  • 这个基础类到底代表什么
  • 哪些元素会在根层级受到影响(译注:啥意思?)
  • 哪些元素可以把 .success 类链到自己身上
  • 它是否可以被进一步扩展到更多的组件上
  • 假如一个 .success 的实例要用白底绿字,而另一个要用绿底白字,怎么办?

And those questions barely scratch the surface. This solution isn't necessarily bad, but when scale, brevity, and flexibility are your top requirements, it might not be the best idea. A better solution might be using prefixed classes.

而且这些问题还只是冰山一角。这种方案未必很差,但如果可扩展性、简单性和灵活性是你的最高需求,这可能就不是最好的办法。此时,前缀式类名方案可能更加适合你。

Prefixed classes guide developers towards a simpler and more maintainable direction for building an extensive CSS design system. Here's what we have if we take away the generic base class and scope things per component with prefixes:

前缀式类名 将开发者引入一种更简单、更易维护的方向,从而构建一个可扩展的 CSS 系统。当我们抛弃常规的基础类的方式,并将每个组件的样式用前缀限制起来时,我们的代码会变成这样:

.btn-success { ... }
.alert-success { ... }

This way, the base class is at the component level and not the entire system level. In other words, our base classes have become .btn and .alert, not .success. There's no bleeding of styles or behavior from one component to another here because we treat components in a "successful state" as an idea across the design system. That is to say, we have a shared idea of what "success" looks for buttons and alerts, but the execution is scoped entirely to each independent component. No questions of where common styles are used and no concern of unintended effects, making each component more durable and flexible.

这样一来,基础类被设定在组件级别,而不是整个系统级别。换句话说,我们的基础类变成了 .btn.alert,而不是 .success。所有组件之间都不会出现样式和行为上的相互干扰,因为我们把组件具备“成功状态”视为贯穿整个系统的一种概念。这就是说,每个组件在“成功”状态下的样式,只有在 概念 层面才是相通的;而对于如何 实现 这个样式,是被约束在每个独立的组件内部的。不用操心通用的样式还会在哪里使用,也不用顾虑不可意料的副作用,这种方式使得每个组件更加稳定和灵活。

While a very tactical and detail-oriented practice, building components that inherently isolate themselves for improved modularity and customization in a system like Bootstrap makes for better code and a more enjoyable project down the line.

构建组件是一项非常具有策略性并且注重细节的工作,在一个类似 Bootstrap 的系统中,组件需要天生具备独立性,以提高模块分离度和可定制性。我们通过这种方式来打造更好的代码和一个令人愉悦的项目。


我的体会

作者视角

我自己在 CMUI 第一版中,基本上使用的是文章开头所说的“链式类名”风格。比如说,一个大号按钮的结构可能是这样的:

<button type="button" class="cmBtn cmLarge">Large button</button>

而在 Bootstrap 中,类似的元素是这样的:

<button type="button" class="btn btn-lg">Large button</button>

最开始我并没有觉得这两者有什么不同——前一个类名用于挂载框架预定义的按钮样式,后一个类名用于指定按钮的尺寸。把 Bootstrap 源码中所有的 .btn-lg 替换成 .cmBtn.cmLarge,不就跟我的 CMUI 一样了嘛?我甚至觉得 Bootstrap 的类命名有点啰嗦,.btn.btn-lg 中的 btn- 不是重复了吗?还是 CMUI 干净利落啊!

然而,看完这篇文章,我似乎体会到 Bootstrap 这种设计的好处。我的理解可能并不是原作者的出发点,但也不妨列举出来,仅供参考。

用户视角

这两种类名风格的差异并不在于源码是怎么写的,而是在于开发者(这里指使用 Bootstrap 制作网页的开发者)在看到类名时的反应。我的理解是,不同的命名风格,对开发者的暗示是不同的

开发者们并不总是会按照组件文档的示例来编写组件的结构代码。比如说,某些时候他们手边没有文档(或不想找文档),又或者他们所期望的样式在文档中并没有列出。他们可能会抱着一种试试看的心态,尝试修改或组合手头的几个类名,以期产生某种新的样式效果。

如果类名是宽泛的(比如 CMUI 中的 .cmLarge),就很容易被拿来尝试——比如开发者会给一个 ul.cmList 元素增加 .cmLarge 类并期望得到一个大号的列表,但实际上 CMUI 并没有提供这种组合!这破坏了开发者的预期,导致心理受挫,以致最终放弃这个组件库(夸张了点哈)。

但如果类名是被一个“组件级”前缀限定的(比如 Bootstrap 中的 .btn-lg),那么它被开发者拿去组合到其它组件身上的可能性就相当低。即使某个异想天开的开发者试图把 .btn-lg 改成 .dropdown-lg 并应用到一个下拉菜单上,当他失败时,他应该也已经做好心理准备了罢。

结语

这样看来,Bootstrap 的做法确有它的好处,我的 CMUI 2.0 不妨也试试看。

你如何评论这两种类名风格呢?不妨留下你的观点吧!


© Creative Commons BY-NC-ND 4.0   |   我要订阅   |   我要打赏

@cssmagic cssmagic added the CSS label Apr 6, 2014

Alvansea commented Apr 7, 2014

  1. "cmBtn cmLarge"看起来更简单,但不便于维护。举个例子,假如使用了“cmLabel cmLarge”,同时希望对label的实际显示效果做微调,或者针对某浏览器做fix,那对cmLarge的修改就可能会影响到button的显示结果,这样每次修改都要针对所有可能的element做回归测试,增加了不必要的工作量。

  2. 回答关于微博上讨论的有了btn-lg是否还需要btn的问题。btn定义了按钮的基本形态,比如圆角形状,float模式等等,在没有btn-lg的时候可以正常显示。如果需要用jQuery动态调整按钮大小,只要用$(...).addClass('btn-lg')就行了,同样removeClass('btn-lg'), toggleClass('btn-lg')也都可以正常使用。

    但是如果框架允许btn-lg在没有btn的情况下也能正常工作,前段工程师就有可能只写一个btn-lg,这个时候调用removeClass,button就丢失了所有style。所以在这种约定下,js端在removeClass以后还要不可避免的附加一个addClass('btn'),以保证button的正常显示。最终结果虽然是减少了class内的字符,却大大增加了js端的代码,得不偿失。

Owner

cssmagic commented Apr 7, 2014

@Alvansea 谢谢留言。先讨论你的第一个观点。

……那对 cmLarge 的修改就可能会影响到 button 的显示结果……

其实不会。因为样式可能是这样写的(CMUI 确实也就是这么做的):

.cmBtn { /* 按钮的默认样式 */ }
.cmBtn.cmLarge { /* 大按钮的特殊样式 */ }
.cmLabel { /* 标签的默认样式 */ }
.cmLabel.cmLarge { /* 大号标签的特殊样式 */ }

这并不存在组件之间的样式干扰问题。所以我在博文里也说:

把 Bootstrap 源码中所有的 .btn-lg 替换成 .cmBtn.cmLarge,不就跟我的 CMUI 一样了嘛?

Alvansea commented Apr 7, 2014

还有一点忘了说,如果用到全文替换,比如把某几个文件中所有 btn-lg 替换成 btn-sm 就很方便。但是如果用 cmLarge 就需要排除非 button 的情况,虽然可以把 'cmBtn cmLarge' 替换成 'cmBtn cmSmall',但是如果其中还有类似 'cmBtn cmRed cmLarge' 的情况呢?基本上就需要排查了。

其他类似场景,比如要为某个文件/页面中的所有 large button 增加其他 style 或者 class,用 btn-lg 也比 cmLarge 更容易定位。

Owner

cssmagic commented Apr 7, 2014

为便于记录讨论过程,我先引用一下我们的讨论所涉及的原微博:

@cssmagic: 我不喜欢 Bootstrap 的前缀式类名风格的主要原因在于,要描述一个大按钮,不仅要有 .btn-lg 类,还不能少了 .btn 这个基础类。可是 .btn-lg 这个类名看起来已经有 “btn” 字样了啊。

以及我的某个评论:

@soulteary: 私以为 Bootstrap 的这个设计偏重 css rule 的复用,而不是单纯的命名维护,.box, .box-info, .box-alert, 继承关系一目了然……

@cssmagic: Bootstrap 的前缀式类名的实践应该叫“组合”吧。因为 .btn-lg 不能独立使用,必须跟 .btn 配合使用,它并没有继承 .btn 的样式,它的作用只是覆盖 .btn 的部分样式。


@Alvansea ,我赞同你第二点的描述。多个类名(基础类 .cmBtn + 另一个维度的辅助类 .cmLarge)的组合使用确实比单个类(假设有一个叫 .cmLargeBtn 的可以单独使用的类)更加灵活。

其实我想说的不是这种类名组合的方式不好,也不是说 “Bootstrap 没有为大按钮提供一个可以独立使用的类” 不好。我的槽点在于,Bootstrap 在这里实际上是把 .btn-lg 当成 .lg(large)来用了。也就是说,如果以这种方式来使用 .btn-lg 这个类名,我觉得不直观、有歧义。

Owner

cssmagic commented Apr 7, 2014

还有一点忘了说,如果用到全文替换,比如把某几个文件中所有 btn-lg 替换成 btn-sm 就很方便。但是如果用 cmLarge 就需要排除非 button 的情况,虽然可以把 'cmBtn cmLarge' 替换成 'cmBtn cmSmall',但是如果其中还有类似 'cmBtn cmRed cmLarge' 的情况呢?基本上就需要排查了。

其他类似场景,比如要为某个文件/页面中的所有 large button 增加其他 style 或者 class,用 btn-lg 也比 cmLarge 更容易定位。

@Alvansea 谢谢补充。这个点确实很有说服力。估计这也是 Bootstrap 采用前缀式命名的出发点之一,让每个类名都有比较明确的组件归属。

hax commented Apr 10, 2014

先说我一贯的观点:所谓css框架中的class命名问题,在没有css预处理时是无解的。原因很简单,离开html只靠css来谈class本身必然无解,因为css自己没有抽象复用机制,拿class来做这个事情只是一种hack,必然不靠谱。

如果你看原本的success和btn/alert,其实它们是本质不同的。success是组件的状态(某种程度上更接近“语义”),而btn/alert是组件的。所谓组件的,其实就是样式类(即用于样式钩子的class)。注意,这里是大体而言,具体案例中边界可能是模糊的。

在没有额外信息的情况下,使用者无法清楚某个class表示组件还是组件状态。这即所谓“What's that base class stand for”问题。而btn-success/alert-success通过固化组件和状态的组合及其在命名中的位置(以组件为前缀)弥补了这额外的信息。

--- 不懂OO的不要看这段,防止脑子浆糊 ---
如以OO为参照,btn/alert是klass(我以klass表示OO中的class,避免跟html中的class混淆),而success是这些类共同实现的interface或混入的trait。
.btn.success的方式像是klass+trait。但是因为使用者无法区分何为klass何为trait,结果看上去更像是多个trait的组合。
.btn-success的方式则像是klass+interface。从概念清晰的角度说肯定比多个trait要清晰啦。但是实现上存在不便,因为要把success共性部分复制来复制去。
需要注意的是,html并不是oo语言,你可以任意附加class,所以本质上说,所有的class都是trait。但是这里的问题是概念模型是怎样的。.btn-success所代表的klass+interface概念模型更一目了然。
--- 本段完 ---

所有他操心的其实是使用者如何能清晰快速的在html上挂样式类而不挂错。想明白这点,就会发现所谓前缀式其实并没有什么神秘的力量。假设我们为所谓chained方式引入额外的命名规约,其实也能解决问题。比如所有组件名首字母大写(就好像OO中的klass那样)。
.Btn.success
.Alert.success
看上去是不是就突然清晰了?

BTW,注意“What if one instance of .success uses green text on a white background while another uses white text on a green background”这个其实是说基于组件状态的样式共性可能不存在。这个对于我这种语义样式分离的原教旨主义者来说纯粹是废话一句,反过来恰恰说明以样式类为核心的“css框架”的方式容易把人的脑子搞成一团浆糊。

hax commented Apr 10, 2014

再说一下其他问题。

写成.Alert.success的好处其实只对于开发者或扩展者而言是如此。对于那些纯粹的使用者来说其实没啥好处,反而会造成同志们所提到的误用问题(有.large.Button但没有.large.List)还有替换问题(我是要替换.large.Button还是.Button.large?)。

所以变成alert-success避免了所有这些问题。

当然如果我们想穿一点,为啥要写"alert alert-success"?直接写单个alert-success不就完了?这对于支持class自动完成的IDE来说写UI简直就是太easy了。
不过这样会导致css里更多重复。而且alert alert-success其实是个固定展开,还是比较容易记住的,我甚至觉得早晚会有IDE的自动完成会自动扩展成这样(说不定现在就有了)。

从这样的角度看,bootstrap的选择倒也是合情合理了。

Owner

cssmagic commented Apr 11, 2014

@hax 谢谢大师兄分享。你的参与让这个话题圆满了,哈哈。

hax commented Apr 12, 2014

当然,我肯定是不喜欢这种命名法的,包括更离谱的BEM之类的。
在有CSS预处理时,我们可以有更简单的做法。比如:

enum ButtonStatus { normal, success }
trait Button(status:ButtonStatus = normal)
  &
     ...some style declarations
  &:hover
     ...some styles for hovering button
  if status == success
    &
        ...
     &:hover
        ....

nav a
  &
    use Button()
  &.success
    use Button(status=success)

以上是以我假想中的css预处理器语言写的,我们用的stylus也能做,只是语法不同。

Owner

cssmagic commented Apr 12, 2014

不过 Bootstrap 作为一个独立的 UI 项目,还是以 CSS 代码作为最终交付物的。因为并不是所有的项目都会采用 Less 或 Sass 这样的 CSS 预处理器。

而且似乎 Bootstrap 官方并没有建议用户使用(在自己的项目中重用)它内部的 mixin,这些 mixin 只被它视为自己的内部实现。也就是说,Bootstrap 源码中的 mixin 并不是公开的 API,它在样式上的公开 API 只有这些预定义的类名。

即使 Bootstrap 有机会向用户提供更酷的 CSS 抽象和重用方式,但它最终还是采用了老土的 HTML 类的方式,作为最终提供给用户的接口。它放弃了“更先进”,换取了“更流行”。作为一个项目,它成功了。

一个以 UI 层解决方案为己任的 CSS 框架,不以类名作为接口,而是以 mixin 的方式提供接口,可行吗?我不知道,也没有见过实例……

hax commented Apr 14, 2014

其实我的观点并不新鲜。

参考这2009年的文章(那时候还没有bootstrap!):
http://www.sitepoint.com/css-frameworks-semantic-class-names/
稍微晚近的(2012年):
http://ruby.bvision.com/blog/please-stop-embedding-bootstrap-classes-in-your-html

hax commented Apr 14, 2014

在第一篇文章里,可以看到css framework的鼻祖blueprint的compress.rb就是一个预处理程序,只是非常局限,从使用者的角度看还是有些问题的,不过至少绝对是可行的。
第二篇文章则示例了如何直接利用LESS的特性来使用Bootstrap的,类似的还有 http://www.hongkiat.com/blog/bootstrap-and-sass/ 中“Utilizing Sass Functions”这节。

所以可行与否?答案是肯定的,从前Bootstrap时代到Bootstrap自己都是可行的。

那么问题是为什么它不流行?你都很少见过?说实话,我也很少见到,虽然我早就知道是可行的。

我的想法:抽象不可能是没有代价的。这也恰恰是当初CSS为啥没有抽象机制的原因,因为CSS的创造者不想承担这样的代价。

而能理解这种抽象且愿意承担其成本的人,其实很可能有足够的能力和动力和资源去从头建造自己的framework,因此也没有足够动力去普及“你应该这样那样用bootstrap,而不是那样这样……”。当然其实这样的文章老早就有,但是并不广为人知,而是淹没在大量入门级的bootstrap示例文章里了。

hax commented Apr 14, 2014

还有使用者的问题。

比如我很晚才了解bootstrap,并直到现在都没有正儿八经在项目里用过bootstrap。因为具体的样式问题在我眼里不是问题。我的意思并不是那不重要,但是我不认为那是个大问题。

但是对于大多数普通开发者来说,有个开箱即用的方案是最重要的。可定制、可维护性、代码干净、语义等问题都是其次的,甚至许多人根本不明白这些东西是什么,有什么重要的。

有些人说,这种做法那种做法都一样,没有对错之分,只有适不适合。

我讨厌这种论调,不过某种程度上他们是对的。但更合理的讲法是,并非没有对错之分,而是某些问题的对错对于许多人和许多case来说,不重要。

所以剩下的问题是,我们自己怎么选择。

看完楼上牛人的长篇回复,我想到一个问题:为什么饭店不卖菜刀?

CSS作为一种前端语言区别于其他语言的最大特点有三:
1、前端是可视的,所以视觉元素与语言之间的关系务必要简单直接,尽可能避免一切不必要的抽象、继承、计算。
例子:如果有多个元素都是9px字体,那就直接用“font-size: 9px;”,而不是抽象出一个变量,因为设计师很可能会随机修改其中某一个或者几个的值

2、前端是频繁变化的,而且频率远超其他layer,所以不同元素之间的逻辑关系不再那么有意义,而易读性与易维护性则尤为重要。
例子: 如果某按钮高亮时用不一样的color,那就指定color的绝对值,而不要用类似 @Light-blue: @nice-blue + #111; 这种方式来描述,因为设计师看不懂,无法在photoshop中调出这个色彩。

3、前端的工作需要工程师与设计师紧密地协同工作,所以语言的学习曲线务必简单快捷。太复杂的逻辑设计师没空研究,术业有专攻,就像多数web工程师也未必能分清高斯模糊和镜头虚化的差别。

回到最初的那个问题,bootstrap就是饭店,less就是菜刀,css就是烧好的菜。

icepy commented Apr 14, 2014

起名的设计,也是一门科学啊!

hax commented Apr 14, 2014

@Alvansea 你讲的是有一定道理的。CSS语言的最初设计其实就是基于此而没有加入任何抽象机制。可见此文:http://www.w3.org/People/Bos/CSS-variables

但是Web发展到今天,和当初已经有了很大不同了。前端开发越来越复杂,在实践中有CSS层面上抽象的需求。

如 1. 设计师的修改是随机的吗?如果设计师要表达一定的设计约束,怎么办?注意,Web设计师不是平面设计师,他需要也能够掌握如弹性布局、网格布局乃至响应式布局。
2. 直接RGB运算大概是不妥的,但是HSL运算或者darken/lighten呢?我认为合格的Web设计师是应该掌握的。
3. 前端需要工程师和设计师协作是没错。但是目前的情况恰恰是,工程师和设计师受限于技术而无法在自己熟悉的领域获得最大的生产力。并非设计师要研究逻辑,而是现有工具和流程不足以支持设计师来表达设计中的逻辑。

Owner

cssmagic commented May 8, 2014

转发转载记录:

  • [微博] 伯乐在线官方微博: //weibo.com/1670481425/B3k8fssdV
  • 伯乐在线: //blog.jobbole.com/67276/

就一点,组件与组件之间不能共享样式,为的是更好的解耦嘛

Owner

cssmagic commented Oct 8, 2014

就一点,组件与组件之间不能共享样式,为的是更好的解耦嘛

@zhengjunwei 话是没错。不过在现实当中还是有诸多矛盾。

解耦的代价就是难免会有冗余。而程序员在面对冗余时又很难抵挡住抽象的诱惑……加上原生 CSS 的抽象机制就只有 “共用 class” 这一种方法了,于是文章开头提到的跨组件的 “状态类” 就出现了。因此,在解耦和重用之间,程序员一直在纠结地权衡。

值得庆幸的是,如今 CSS 预处理技术已经相当成熟了。因此现代 CSS 项目几乎都是基于 CSS 预处理器打造的,在代码组织上和接口输出上都变得更加灵活和自由。在接口层面解耦、在实现层面重用,可以很自然地实现。甚至,用 mixin 取代类名作为接口,就更不存在类名命名的问题了——我期待这一天的到来。

抽取跨组件的 “状态类” 的另一个目的是为了减少 CSS 代码的体积。这是另一个层面的解耦和重用的矛盾。不过好在 CSS 预处理技术又一次拯救了我们,当我们用 mixin 取代类名作为接口之后,CSS 体积问题也会被化解于无形。

hacke2 commented Feb 27, 2015

之前看过一个“CSS模块化”的概念,说的是一个元素挂在的class第一个是基类,如一些reset的操作,第二个class挂在的是组件类,比如一些组件共有的样式,第三个是个性类,就是达到设计图规定的样式,这样弄起来css的类就可以很好的复用

你好,CSS魔法大哥,请问CSS属性里面的inherit,justified这二个值怎么区别?

------------------ 原始邮件 ------------------
发件人: "CSS魔法"notifications@github.com;
发送时间: 2014年10月8日(星期三) 中午11:30
收件人: "cssmagic/blog"blog@noreply.github.com;
抄送: "郑伟"cxrhphp@qq.com;
主题: Re: [blog] 浅析 Bootstrap 的 CSS 类名设计 (#45)

就一点,组件与组件之间不能共享样式,为的是更好的解耦嘛

@zhengjunwei 话是没错。不过在现实当中还是有诸多矛盾。

解耦的代价就是难免会有冗余。而程序员在面对冗余时又很难抵挡住抽象的诱惑……加上原生 CSS 的抽象机制就只有 “共用 class” 这一种方法了,于是文章开头提到的跨组件的 “状态类” 就出现了。因此,在解耦和重用之间,程序员一直在纠结地权衡。

值得庆幸的是,如今 CSS 预处理技术已经相当成熟了。因此现代 CSS 项目几乎都是基于 CSS 预处理器打造的,在代码组织上和接口输出上都变得更加灵活和自由。在接口层面解耦、在实现层面重用,可以很自然地实现。甚至,用 mixin 取代类名作为接口,就更不存在类名命名的问题了——我期待这一天的到来。

抽取跨组件的 “状态类” 的另一个目的是为了减少 CSS 代码的体积。这是另一个层面的解耦和重用的矛盾。不过好在 CSS 预处理技术又一次拯救了我们,当我们用 mixin 取代类名作为接口之后,CSS 体积问题也会被化解于无形。


Reply to this email directly or view it on GitHub.

Owner

cssmagic commented Mar 16, 2015

@zhengjunwei 你好,与当前主题不相关的问题可以到 知乎微博 提问,谢谢 😊

dudy5 commented May 2, 2015

我觉得:如@hax老师所说,css本身并没有抽象与复用的机制。因此,如果我们去讨论真正意义上的module的抽象与复用,答案肯定是不如我们所意的。而业务模块的抽象与复用,才是我们值得去研究的东西,而命名,则应该也以面向业务模块为导向。而以面向业务模块为导向后,我们就无需纠结到底是以语义为中心还是以UI为中心去命名

但是Web发展到今天,和当初已经有了很大不同了。

@hax 发现这句话可以对上 winter 上次在知乎说的吵架金句,哈哈哈。(纯路过吐槽一下)

catouse commented Aug 11, 2016

在一些轻量系统中,个人认为前缀并不是十分重要。MZUI 中引入了丰富的通用外观选项修饰类(参见网站 “基础->外观选项”),我觉得这种思路对于移动端小型系统恰到好处。

Owner

cssmagic commented Aug 12, 2016

@catouse
粗略看了一遍 MZUI 的接口。你的选择就是文中提到的 “链式类名” 方案,它的优缺在原文和评论中已经说得比较清楚了。你能在 MZUI 中完整地实践这种方案,是相当不错的。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment