CSS Architecture

CSS Architecture

要求

  1. 在编辑一个类的CSS时不会影响其他类的CSS
  2. 这个类的CSS是名称显而易见的
  3. 不能使HTML变得臃肿
  4. 必须立即知道这个组件是否在使用JavaScript

最佳方案,使用BEM和其中命名空间的优化版

Block

一个Block是代表一个组件

.form来代表form元素因为class具有无限的重用性 button是一个很好的例子,如果你用button属性设置它的背景颜色,所有的button都会应用这个样式
你不得不一个个是覆盖其他你想要定义的颜色 如果你使用class的button,你可以自己决定在任何一个button使用这个class。或者你想用其他的颜色你可以使用.button--secondary

.button {
  background-color: red;
}

.button--secondary {
  background-color: blue; 
}

Modifiers

Modifier使用来代表一个组件的不同状态。例如.button--secondary

经过修改过的modifier,使用Mixin来实现DRY的特性

@mixin button {
  padding: 0.5em 0.75em;
}

.button {
  @include button; 
  background-color: red;
}

.button--secondary {
  @include button; 
  background-color: green;
}

或者使用原生的属性选择器实现

[class*='button']:not([class*='button__']) {
  padding: 0.5em 0.75em;
}

Elements

elements是Block的子元素。例如form__row说明row元素是form元素的子元素

不能连接elemnets,例如.form__row__input

Container

<section> <div class="prefix-wrap"> <div class="block"> <!-- ... --> </div> </div> </section>

##Namespace

  1. .l-: layouts
  2. .o-: objects
  3. .c-: components
  4. .js: JavaScript hooks
  5. .is-|.has-: state classes
  6. .t1|.s1: typography sizes
  7. .u-: utility classes

Layouts with .l-

OOCSS的基本概念为把CSS的呈现部分和结构部分相分离,把影响布局的部分分离出来进行维护,使用l打头的前缀

Global layouts

global layout表示那个大型的grid和container,在所有页面都应用的布局,把它区分在_layout.scss

.l-wrap {
  padding-left: 1em;
  padding-right: 1em;

  @media (min-width: 1000px) {
    max-width: 800px;
    margin-left: auto;
    margin-right: auto;
  }
}
<div class="site-header">  
  <div class="l-wrap">
    <!-- stuff -->
  </div>
</div>

<div class="site-footer">  
  <div class="l-wrap">
    <!-- stuff -->
  </div>
</div>  

Block-level layouts

每一个模块都有自己的布局

<form class="form l-form" action="#">  
  <div class="form__row">
    <div class="form__item l-form__item"></div>
    <div class="form__item l-form__item"></div>
  </div>
  <div class="form__row">
    <div class="form__item l-form__item--large"></div>
    <div class="form__item l-form__item--small"></div>
  </div>
  <!-- ... -->
</form>  
.l-form {/* container styles */}
.l-form__item {/* half-width styles */}
.l-form__item--large {/* larger-width styles */}
.l-form__item--small {/* smaller-width styles */}

Objects with .o-

object是最小的的模块,类型与Atomic Design中的元素分子

Object有一下要求

  1. 有o前缀
  2. 不能再包含其他的objects和组件
  3. 它们在内容上是独立的
  4. 去掉o前缀也有意义
<a href="#" class="o-button">A button</a>  

A timer

<div class="o-countdown jsCountdown">  
  <div class="o-countdown__inner">
    <span data-token="days">1</span>
    <span>day</span>
  </div>
  <div class="o-countdown__inner">
    <span data-token="hours">21</span>
    <span>hours</span>
  </div>
  <div class="o-countdown__inner">
    <span data-token="minutes">41</span>
    <span>minutes</span>
  </div>
  <div class="o-countdown__inner">
    <span data-token="seconds">50</span>
    <span>seconds</span>
  </div>
</div>  
Objects are context independent

意味着从原来的结构里拿出来,再放进其他的结构里并不会破坏其他的结构的结构

所有object不能有

  1. 绝对或者fixed定位
  2. 外边距
  3. 内边距(除非你有background-color属性)
  4. float
[class*='o-button']:not([class*='o-button__']) {
  display: inline-block;
  padding: 0.75em 1.25em;
  border-radius: 4px;
  background-color: green;
  color: white;
  font-size: inherit;
  line-height: inherit;
  transition: all 0.15s ease-in-out;
}
Certain objects can ignore the .o- prefix when it makes sense.
<input type="text">

@mixin input {
  padding: 0.5em 0.75em;
  font-size: inherit;
  line-height: inherit;
  font-family: inherit;
}


input[type="text"],  
input[type="email"],  
input[type="textarea"] {  
  @include input;
}

Component

Components相当于Atomic Design中的有机体

必须要有 1. .c-前缀
2. 组件可以包含object和其他的组件
3. 是 Context aware的

<form class="c-form l-form" action="#">  
  <div class="c-form__row">
    <div class="c-form__item l-form__item">
      <label for="fname">
        <span>First Name</span>
        <input type="text" id="fname" name="fname">
      </label>
    </div>
    <!-- ... the email input item -->
  </div>
  <!-- ... other form_rows -->
  <div class="c-form__row">
    <button class="o-button c-form__button">Buy Mastering Responsive Typography!</button>
  </div>
</form>  

BEM mix

.c-form__button

用组件的类来给object上样式而不影响原来的button

.is or .has 的状态类

// Sass
.object {
  &.is-animating { /* styles */}
}
.object.is-animating { /* styles */ }

.t 或 .s的字体类

在简单的项目中使用

h1 { /* styles */ }  
h2 { /* styles */ }  
h3 { /* styles */ }  
h4 { /* styles */ }  
h5 { /* styles */ }  
h6 { /* styles */ }  

是极好的

在复杂的情况中应该给h标签加一个带前缀的类

  • .t1:最大的font-size
  • .t2:第二大的font-size
  • .s1:在font-size基础上的第一小
  • .s2:在font-size基础上的第二小

使用Sass

@mixin s1 {
  font-size: 14px;
  line-height: 1.25
}

h1,  
nav a {  
  @include s1;
}

字体是object的一部分,不能加margin或者padding

.u-前缀的功能性class

功能性class经常覆盖其他的属性,所有有时要加!important

.u-text-left { text-align: left !important; }
.u-text-center { text-align: center !important; }
.u-text-right { text-align: right !important; }

.u-hide-st-med {
  @media (man-width: 599px) {
    display: none !important;
  }
}

.u-hide-bp-med {
  @media (min-width: 600px) {
    display: none !important;
  }
}