Skip to content

Instantly share code, notes, and snippets.

@spemoon
Last active January 2, 2016 07:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spemoon/8269324 to your computer and use it in GitHub Desktop.
Save spemoon/8269324 to your computer and use it in GitHub Desktop.

原文在这

这篇文章写得相当好,这里做下总结:

##良好的CSS架构目标(The Goals of Good CSS Architecture)

####可预测(PREDICTABLE) 当你添加或者修改某个规则时,它并不会影响到没有指定的部分。 ####可重用(REUSABLE) CSS规则应具备抽象和解耦性,可以在现有的基础上快速构建新的组件。 ####可维护(MAINTAINABLE) ####可扩展(SCALABLE)

##常见的错误实践(Common Bad Practices) ####基于父组件来修改组件(MODIFYING COMPONENTS BASED ON WHO THEIR PARENTS ARE)

.widget {  
  background: yellow;  
  border: 1px solid black;  
  color: black;  
  width: 50%;  
}  
 
#sidebar .widget {  
  width: 200px;  
}  
 
body.homepage .widget {  
  background: white;  
}

首先,例子中的widget是不可预见的。当这些小部件出现在页面两侧或者主页面时,开发人员期望它们以某种特定的方式显示出来,且又不失特色。另外,它也是不可重用或不可扩展的。

另外,它也比较难维护。一旦这个widget需要重新设计,那么你不得不修改其他几个CSS样式。想象一下,如果这段代码是使用其他语言编写的,它基本就是一个类定义,然后在代码的另一部分使用该类定义并做出扩展。这直接违反了软件开发的开放/闭合(open/close)原则。

####过于复杂的选择器(OVERLY COMPLICATED SELECTORS)

#main-nav ul li ul li div { }
#content article h1:first-child { }
#sidebar > div > h3 + p { }

如果这个HTML是永远不变的,那就无可说之处,但这根本毫不现实。过于复杂的选择器会让人印象深刻,它可以让HTML摆脱掉表面上的复杂,但对于实现良好的CSS架构目标却毫无用处。

上面提到的例子都是不具备可预测性、可重用、可扩展和可维护这四大特性的。

####过于通用的类名(OVERLY GENERIC CLASS NAMES)

<div class="widget">  
  <h3 class="title">...</h3>  
  <div class="contents">  
    Lorem ipsum dolor sit amet, consectetur adipiscing elit.  
    In condimentum justo et est dapibus sit amet euismod ligula ornare.  
    Vivamus elementum accumsan dignissim.  
    <button class="action">Click Me!</button>  
  </div>  
</div>
.widget {}  
.widget .title {}  
.widget .contents {}  
.widget .action {}

像.title、.contents、.action这些子元素类选择器可以被安全地进行样式命名,但它并没有阻止相同样式类名称会蔓延到这个组件上。在一些大型项目上,像.title这样的名称很有可能会被用在另外一个页面或者本身。如果这样的情况发生,那么整个标题部分明显会和预期的不一样。

####一个规则做太多事(MAKING A RULE DO TOO MUCH)

.widget {  
  position: absolute;  
  top: 20px;  
  left: 20px;  
  background-color: red;  
  font-size: 1.5em;  
  text-transform: uppercase;  
}

问题的关键是你让.widget这个选择器做的事情太多,不仅对该组件的位置进行了规定,还对它的外观和感觉方面进行了样式。外观和感觉可以通用,而位置是不可以的。有时候,把它们整合起来使用反而会大打折扣。

##原因(The Cause)

内容与表现(presentation)相分离是件好事,但CSS从HTML中独立出来并不意味着内容也需要从表现中分离。换句话说,如果CSS请求深入分析HTML架构,那么从HTML中分拆所有的显示代码并不一定会实现所有的目标。

此外,HTML很少会只包含内容,也表示整体框架。通常,架构是会包含container元素,允许CSS隔离一些固定元素。即使没有表象类(presentational classes),也能混合HTML清晰地把内容展示出来。

鉴于当前的HTML和CSS状态,把HTML和CSS明智地结合起来,当做表现层是非常需要的。而通过模板和局部模板(partials)也可以把内容层进行分离。

##解决方案(The Solution)

最好的方法是CSS中尽可能少的包含HTML架构。CSS则是应该定义元素的视觉效果,无论该视觉元素在哪里。如果有一些特定的组件需要在不同的场合显示不同的效果,那么应该赋予不同的名称。例如,CSS通过.button类选择器定义了一个按钮组件。如果HTML想要一个特定的元素看起来像按钮,那么就可以使用.button。如果这里有特殊要求,这里的按钮与其他的有所不同(有可能更大和宽些),那么CSS需要定义一个新的类,HTML可以使用新的类来赋予该元素新的视觉效果。

##最佳实践(Best Practices)

####专注(BE INTENTIONAL) 确保选择器对一些元素不进行无关样式的最好方法是不给它们机会。例如像#main-nav ul li ul li div这样的选择器可能很容易地应用于不想要的元素上。另一方面,像.subnav这样的选择器就不会给它们任何机会。把类选择器直接应用于你想要的元素上是最好的方式,并且可以保持元素的可预测性。

/* Grenade */
#main-nav ul li ul { }  
 
/* Sniper Rifle */
.subnav { }

####模块化(SEPARATE YOUR CONCERNS) 一个组织结构良好的组件层可以帮助解决HTML架构与CSS那种松散的耦合性。此外,CSS组件本身应该是模块化的。组件应该知道如何进行样式和更好地工作,但是关于布局、定位以及它们与周围元素的关系不应该做太多的假设。

布局和位置应当由一个单独的布局类或者单独的容器元素构成(请记住,有效地把内容与展示进行分离其实就是把内容与容器进行分离)。

####给类进行命名空间(NAMESPACE YOUR CLASSES)

/* High risk of style cross-contamination */
.widget { }  
.widget .title { }  
 
/* Low risk of style cross-contamination */
.widget { }  
.widget-title { }

####创建修饰符类来扩展组件(EXTEND COMPONENTS WITH MODIFIER CLASSES)

/* Bad */
.widget { }  
#sidebar .widget { }  
 
/* Good */
.widget { }  
.widget-sidebar { }

####把CSS组织成逻辑结构(ORGANIZE YOUR CSS INTO A LOGICAL STRUCTURE) CSS可以被分成四个不同的类:基础(base)、布局(layout)、模块(modules)和状态(state).

####因样式和风格使用类(USE CLASSES FOR STYLING AND STYLING ONLY)

一般来说,最佳做法是把内容与演示相分离,另外把功能分离开来也同样重要。使用样式类像JavaScript hook在某种程度上可以加深CSS与JavaScript之间的耦合,但在不打破功能性的前提下很难或者根本不可能更改外观。

####有逻辑的命名类(NAME YOUR CLASSES WITH A LOGICAL STRUCTURE)(这里应该是此文的重点了)

Nicolas Gallagher最近针对遇到的问题写了一个解决方案,并且取得了巨大的成功(略有改动),为了说明命名约定,可以考虑以下格式:

/* A component */
.button-group { }  
 
/* A component modifier (modifying .button) */
.button-primary { }  
 
/* A component sub-object (lives within .button) */
.button-icon { }  
 
/* Is this a component class or a layout class? */
.header { }

从上述类中可以发现其很难正确区分类型规则。这不但会困惑,而且连自动测试CSS和HTML也变的很难。一个结构化的命名约定应该是初看就能够知道其类名与其他类之间的关系,并且知道它出现在HTML中的位置——使命名更加简单和容易测试。

/* Templates Rules (using Sass placeholders) */
%template-name  
%template-name--modifier-name  
%template-name__sub-object  
%template-name__sub-object--modifier-name  
 
/* Component Rules */
.component-name  
.component-name--modifier-name  
.component-name__sub-object  
.component-name__sub-object--modifier-name  
 
/* Layout Rules */
.l-layout-method  
.grid  
 
/* State Rules */
.is-state-type  
 
/* Non-styled JavaScript Hooks */
.js-action-name

重做第一个例子:

/* A component */
.button-group { }  
 
/* A component modifier (modifying .button) */
.button--primary { }  
 
/* A component sub-object (lives within .button) */
.button__icon { }  
 
/* A layout class */
.l-header { }

##工具(TOOLS)

####预编译器(PREPROCESSORS)(这里是本文另一个重点)

@extend%placeholder是预处理器里面非常好的两个功能。它们可以帮你轻松管理CSS抽象并且无需添加bloat和大量的基类到CSS和HTML里,否则将会很难管理。

当你初次使用@extend时,常会与修饰符类一起使用,例如:

.button {  
  /* button styles */
}  
 
/* Bad */
.button--primary {  
  @extend .button;  
  /* modification styles */
}

这样做会让你在HTML中失去继承链。很难使用JavaScript选择所有的按钮实例。

作为一般规则,很少去扩展UI组件或者在知道类型后做些什么。这是区分模板和组件的一种方式,模板无需参与到应用程序的逻辑,并且可以使用预处理器进行安全扩展。

下面是一个引用上面的模式例子:

.modal {  
  @extend %dialog;  
  @extend %drop-shadow;  
  @extend %statically-centered;  
  /* other modal styles */
}  
 
.modal__close {  
  @extend %dialog__close;  
  /* other close button styles */
}  
 
.modal__header {  
  @extend %background-gradient;  
  /* other modal header styles */
}

####CSS Lint CSS Lint是一个用来帮你找出CSS代码中问题的工具,它可做基本的语法检查以及使用一套预设的规则来检查代码中的问题,规则是可以扩展的。

使用CSS Lint建议:

  1. 不要在选择器中出现ID。
  2. 在多部分规则中,不要使用非语义(non-semantic)类型选择器,例如DIV、SPAN等。
  3. 在一个选择器中使用的连接符(combinator)不要超过2个。
  4. 任何类名都不要以“js-”开始。
  5. 如果在非“I-”前缀规则里经常使用布局和定位应给予警告
  6. 如果一个类定义后被重新定义成子类,也应给予警告。

##总结

CSS不仅仅是视觉设计,也不要因为你编写CSS就随便抛出编程的最佳实践。像OOP、DRY、打开/闭合、与内容分离等这些规则应该应用到CSS里面。无论你如何组织代码,都要确保方法真正帮助到你,并且使你的开发更加容易和可维护的。

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