如何做好CSS架构--理论篇

397 阅读15分钟

背景

之前有幸见识到一个项目css一塌糊涂,各种样式覆盖,全局样式五六个文件,important满天飞,搞得很是头大。

CSS中可能存在的问题

  1. 冗余:小明想实现一个水平垂直居中,但是不想找现在有没有共享的样式,反正不麻烦,自己写一个好了
  2. 命名不规范:没有命名规范,个人风格差异大
  3. 缺少注释:懂的都懂
  4. 重复的覆盖:一个样式,全局有,局部有,还可能用了无数的 important(别问我如何知道的)

CSS设计模式

一、OOCSS

OOCSS(Object Oriented CSS)并不是一种特定的命名规范,而是一种CSS编写的思想和原则。它的目标是通过应用面向对象编程(OOP)中的设计原则,使CSS代码更加易于管理和维护。

1、优点

  1. 高度重用:OOCSS追求组件的复用,尽量不使用继承选择符,而是通过创建可重用的对象来减少代码的冗余。这种方式使得CSS代码更加简洁,易于维护,并且文件加载速度会更快。
  2. 易于维护:OOCSS通过清晰的类结构来组织代码,使得开发者能够更容易地定位问题并进行修改。同时,由于代码的重用性,修改一处即可全局生效,降低了维护难度。
  3. 可扩展性强:OOCSS的核心思想之一是结构和皮肤分离,这意味着新的视觉样式可以轻松地应用到现有的结构上。此外,新模块可以通过组合现有模块轻松创建,未来需求变化也能轻松应对。

2、核心思想

  1. 结构和皮肤分离:在OOCSS中,结构和皮肤被明确地区分开来。结构指的是HTML元素的布局和定位等属性(如height、width、position、margin、overflow等),而皮肤则指的是元素的视觉样式(如background、border、color等)。通过将结构和皮肤分离,可以使得视觉样式作为单独的“主题”来应用,而不必覆盖结构属性。
  2. 容器与内容分离:OOCSS强调不要在CSS中模仿HTML的结构。换句话说,不要在样式表中引用标签或ID。相反,应该尝试创建和应用描述相关标签使用的类。通过这种方式,可以减少对HTML结构的依赖,增加CSS class的重用性。

3、应用

在实际项目中应用OOCSS时,需要注意以下几点:

  1. 避免过度嵌套:过多的嵌套会增加代码的复杂性并降低可读性。因此,在编写OOCSS代码时,应尽量保持嵌套的简洁性。
  2. 命名规范:为了提高代码的可读性和可维护性,应遵循一定的命名规范。例如,可以使用有意义的类名来描述元素的功能或状态。
  3. 利用预处理器:使用CSS预处理器(如Sass、Less等)可以更方便地编写和维护OOCSS代码。预处理器提供了变量、函数、混合(mixin)等高级功能,可以帮助开发者更高效地编写可重用的CSS代码。

4、示例

假设有两个大小、外边距相同的div,但它们的背景色和字体大小不同。我们可以使用OOCSS的方法来编写CSS代码。

  1. 结构与皮肤分离

    在OOCSS中,我们首先将结构和皮肤属性分开。结构属性包括位置、尺寸等,而皮肤属性包括字体、颜色等。

            .box {  
                width: 30%;  
                margin-left: 35%;  
                height: 300px;  
                margin-top: 50px;  
                text-align: center;  
                line-height: 300px;  
                color: white;  
            }  
    
            /* 皮肤样式 */  
            .skin-purple {  
                background-color: #8A2BE2;  
                font-size: 22px;  
            }  
    
            .skin-blue {  
                background-color: blue;  
                font-size: 23px;  
            }
    

    在HTML中,我们可以这样应用这些样式:

            <div class="box skin-purple">Box 1</div>  
            <div class="box skin-blue">Box 2</div>
    

    通过这种方式,我们可以轻松地改变div的皮肤样式,而不需要修改其结构样式。

  2. 容器与内容分离

    OOCSS还强调容器与内容的分离。这意味着子元素即使离开了容器也应该能正确显示。在上述示例中,.box是容器,而内容(文本)是放置在容器中的。由于我们使用了结构与皮肤分离的方法,所以内容(文本)的样式(如字体大小和颜色)是通过皮肤样式(.skin-purple.skin-blue)来定义的,而不是直接定义在容器样式(.box)中。因此,即使我们将内容移动到其他容器中,也只需要确保新的容器具有相同的结构样式(.box),并为其应用相应的皮肤样式即可。

二、BEM

BEM(Block Element Modifier)通过特定的命名规范和组织结构来提高CSS代码的可读性、可重用性、可维护性和可扩展性。

1、基本概念

  • Block(块)

    • 定义为页面中的独立实体,具有独立的意义。每个页面都可以看作是由多个Block组成的。
    • 示例:一个导航栏、一个按钮组件、一个轮播图等都可以被视为一个Block。
    • 命名规则:没有特定的前缀,多个单词使用连字符(-)连接。
  • Element(元素)

    • 是Block的一部分,没有独立的意义,是组件下的一个元素。多个Element形成一个完整的Block。
    • 示例:在导航栏Block中,每个导航项都可以被视为一个Element。
    • 命名规则:在Block的类名后,使用双下划线(__)连接Element的名称。
  • Modifier(修饰符)

    • 是Block或Element上的标记,用于描述其属性或状态。同一Block或Element可以有多个Modifier。
    • 示例:一个按钮Block可以有“成功”、“失败”等不同的Modifier来表示不同的状态。
    • 命名规则:在Block或Element的类名后,使用双连字符(--)连接Modifier的名称。

2、特点

  1. 清晰的结构:可以清晰地反映HTML文档的结构,使得开发者能够快速地定位和理解样式。

  2. 易于维护:BEM规范使得CSS代码具有高度的可维护性。由于类名具有明确的含义和层级关系,开发者可以轻松地找到和修改相应的样式。

  3. 高可重用性:通过BEM的Block和Element定义,组件和元素可以被多次使用,提高了样式的重用性。

  4. 可扩展性:由于BEM的Modifier定义,组件和元素可以轻松地扩展出不同的状态或版本,满足不同的需求。

3、示例

以ElementUI的按钮组件为例:

  • Block(块).el-button 表示一个按钮组件。
  • Element(元素).el-button__icon 表示按钮中的图标元素。
  • Modifier(修饰符).el-button--primary 表示主要按钮样式;.el-button--round 表示圆形按钮样式。

三、SMACSS

SMACSS(Scalable and Modular Architecture for CSS)是一种面向模块化的CSS架构方法,旨在提高CSS代码的可读性、可维护性和可扩展性。

1、核心概念

  1. 模块化:SMACSS鼓励将整个页面结构划分为小型、独立的模块,并为每个模块创建独立的CSS文件。这样可以使样式更容易管理,并且减少了CSS文件的大小。
  2. 工具类(Mixins) :Mixins是可以被复用的CSS规则,用于为模块添加主题、样式或功能。它们可以组合在一起,并在不同的模块中重用。
  3. 深度优先:SMACSS鼓励开发者使用深度优先规则,即在同一深度级别内,越具体的类名越前面展示。这有助于避免冲突,并提高CSS的可读性。
  4. 目的className:SMACSS推荐为每个类名提供一个明确的描述,即目的className,这样有助于理解该类名的用途。
  5. Innateario:这是一个帮助开发者获取元素前缀(如:before、after或::before、::after)的工具类。

2、项目引入SMACSS的步骤

  1. 对整个页面进行模块化。
  2. 开始使用工具类(Mixins)来添加主题、样式或功能。
  3. 使用深度优先规则来避免样式冲突。
  4. 为每个类名提供一个明确的描述。
  5. 使用Innateario来获取元素前缀。

3、SMACSS的分类

SMACSS的核心是分类,具体将项目的样式分为五类:

  1. Base(基础) :定义了元素全局的默认样式。
  2. Layout(布局) :处理页面结构和布局。
  3. Module(模块) :包含页面中可复用的组件或元素。
  4. State(状态) :定义元素在不同状态下的样式(如:hover、active等)。
  5. Theme(主题) :允许开发者为项目定义多个主题。

4、SMACSS的优势

  1. 可读性和可维护性:由于SMACSS鼓励使用深度优先规则和目的className,样式文件变得更加可读和可维护。
  2. 可扩展性:由于SMACSS的模块化和工具类,样式文件可以轻松地增加或修改模块,这使得项目可以在未来扩展得更加容易。
  3. 性能:由于SMACSS的模块化和深度优先规则,样式文件的大小变得更加小巧,这可以提高页面加载速度。

5、示例

以下是一个使用SMACSS的例子,来展示其如何组织和管理CSS代码。

1. Base(基础)

Base规则里一般放置默认样式。这些默认样式基本上都是元素选择器,也可以包含属性选择器、伪类选择器、孩子选择器和兄弟选择器。

示例

	/* 重置浏览器默认样式 */  
	body, h1, h2, h3, p, ul, ol, li {  
	  margin: 0;  
	  padding: 0;  
	}  

	/* 设置基础字体样式 */  
	body {  
	  font-family: Arial, sans-serif;  
	  color: #333;  
	}

2. Layout(布局)

Layout规则定义了页面的整体布局结构。

示例

	/* 定义页眉样式 */  
	.header {  
	  background-color: #f8f9fa;  
	  padding: 20px;  
	}  

	/* 定义页脚样式 */  
	.footer {  
	  background-color: #343a40;  
	  color: #fff;  
	  padding: 20px;  
	  text-align: center;  
	}

3. Module(模块)

Module规则定义了可复用的组件样式。

示例

	/* 定义一个卡片模块 */  
	.card {  
	  border: 1px solid #ccc;  
	  border-radius: 5px;  
	  padding: 15px;  
	  margin-bottom: 10px;  
	}  

	/* 卡片模块中的标题 */  
	.card__title {  
	  font-size: 18px;  
	  margin-bottom: 10px;  
	}  

	/* 卡片模块中的描述 */  
	.card__description {  
	  font-size: 14px;  
	  color: #6c757d;  
	}

4. State(状态)

State规则定义了组件在不同状态下的样式。

示例

	/* 定义一个激活状态的按钮 */  
	.btn--active {  
	  background-color: #007bff;  
	  color: #fff;  
	}  

	/* 定义一个禁用状态的按钮 */  
	.btn--disabled {  
	  background-color: #6c757d;  
	  color: #fff;  
	  cursor: not-allowed;  
	}

5. Theme(主题)

Theme规则定义了整个应用或页面的主题样式。

示例

	/* 定义一个暗色主题 */  
	.theme--dark {  
	  background-color: #343a40;  
	  color: #fff;  
	}  

	/* 在暗色主题下,修改卡片模块的样式 */  
	.theme--dark .card {  
	  border-color: #6c757d;  
	  background-color: #495057;  
	}

总结

通过使用SMACSS,我们可以将CSS代码分解成多个可复用的模块,并按照Base、Layout、Module、State和Theme这五个部分进行组织。这样的架构方法使得CSS代码更加模块化、结构化和可维护,同时也提高了代码的可扩展性和复用性。

6、注意事项

虽然SMACSS带来了许多优势,但也可能存在学习曲线较陡、增加代码复杂性(特别是在项目较小或简单的情况下)以及可能导致过度设计的问题。因此,在使用SMACSS时,需要根据项目的具体需求和团队的实际情况进行权衡和选择。

四、ITCSS

1、核心概念

ITCSS (Inverted Triangle CSS Architecture) 是一种 CSS 架构或方法论,旨在帮助开发者更有效地组织和管理他们的 CSS 代码。这个架构强调代码的可维护性、可扩展性和可重用性。

ITCSS 的基本思想是:将 CSS 规则按照特定的优先级和重要性进行分层,确保每个层级的规则都能在其预期的范围内应用,而不会对其他层级的规则造成干扰。

2、层级结构

以下是 ITCSS 的基本层级结构(从高到低优先级):

  1. Settings(设置) :全局变量、配置开关等。
  2. Tools(工具) :CSS 函数、mixin、helpers 等。
  3. Generic(通用) :重置和盒模型等全局默认样式。
  4. Base(基础) :HTML 元素的默认样式,如 <body><p><a> 等。
  5. Objects(对象) :无类名的、可重用的设计模式,如布局、网格等。
  6. Components(组件) :具体的界面元素,如按钮、表单、卡片等。
  7. Trumps(盖帽) :覆盖其他所有层级的规则,如 .is-hidden.u-text-center 等。

这个结构的好处是:

  • 清晰的组织:每个层级的规则都有明确的作用域和优先级,使得代码更加清晰易懂。
  • 可维护性:由于每个层级的规则都是独立的,因此可以很容易地对它们进行修改、添加或删除。
  • 可扩展性:新的规则可以很容易地添加到适当的层级中,而不会影响其他层级的规则。
  • 可重用性:对象和组件可以在整个项目中重复使用,减少了代码的冗余。

3、示例

在项目中使用ITCSS架构时,可以遵循其分层结构来组织和管理CSS代码。以下是一个示例,展示了如何在项目中应用ITCSS的层级结构:

1. Settings(设置)

  • 作用:定义全局变量、配置开关等。

  • 示例

    	/* settings.css */  
    	:root {  
    	  --main-color: #333;  
    	  --secondary-color: #fff;  
    	  --font-stack: Helvetica, sans-serif;  
    	}
    

2. Tools(工具)

  • 作用:包含CSS函数、mixin、helpers等。

  • 示例

    	/* tools.css */  
    	@mixin clearfix {  
    	  &::after {  
    	    content: "";  
    	    display: table;  
    	    clear: both;  
    	  }  
    	}
    

3. Generic(通用)

  • 作用:全局默认样式,如CSS重置。

  • 示例

    	/* generic.css */  
    	*,  
    	*::before,  
    	*::after {  
    	  box-sizing: border-box;  
    	  margin: 0;  
    	  padding: 0;  
    	}
    

4. Base(基础)

  • 作用:HTML元素的默认样式。

  • 示例

    	/* base.css */  
    	body {  
    	  font-family: var(--font-stack);  
    	  color: var(--main-color);  
    	  background-color: var(--secondary-color);  
    	}  
    
    	h1, h2, h3 {  
    	  /* ... */  
    	}  
    
    	p {  
    	  /* ... */  
    	}
    

5. Objects(对象)

  • 作用:无类名的、可重用的设计模式。

  • 示例

    	/* objects.css */  
    	.grid {  
    	  display: flex;  
    	  flex-wrap: wrap;  
    	}  
    
    	.grid__item {  
    	  flex: 1 0 200px;  
    	}
    

6. Components(组件)

  • 作用:具体的界面元素。

  • 示例

    	/* components/button.css */  
    	.button {  
    	  display: inline-block;  
    	  padding: 10px 20px;  
    	  background-color: var(--main-color);  
    	  color: var(--secondary-color);  
    	  border: none;  
    	  border-radius: 4px;  
    	  @include clearfix; /* 使用之前定义的mixin */  
    	}  
    
    	.button--primary {  
    	  background-color: var(--some-other-color);  
    	}
    

7. Trumps(盖帽)

  • 作用:覆盖其他所有层级的规则。

  • 示例

    	/* trumps.css */  
    	.hide {  
    	  display: none !important;  
    	}  
    
    	.text-center {  
    	  text-align: center !important;  
    	}
    

总结

  • 在项目中,确保按照ITCSS的层级结构来组织CSS文件。
  • 每个层级的CSS文件都应只包含该层级特定的规则。
  • 通过使用预处理器(如Sass)的@import功能,可以按照正确的顺序导入这些文件。
  • 这种结构有助于保持代码的清晰、可维护和可扩展。

请注意,这个示例仅用于说明目的,并且可能需要根据具体项目的需求进行调整。

五、ACSS

ACSS (Atomic CSS) 是一种 CSS 架构或方法论,它强调将 CSS 规则分解为尽可能小的、可重用的、独立的单元(通常被称为“原子”),然后通过类名组合这些单元来构建复杂的界面样式。ACSS 的主要目标是减少 CSS 的复杂性和冗余,提高样式的可重用性和可维护性。

1、ACSS 的特点

  1. 原子化:CSS 规则被分解为最小的、可重用的单元。
  2. 组合性:通过组合多个原子类来构建复杂的样式。
  3. 可重用性:原子类可以在整个项目中重复使用,减少了样式的冗余。
  4. 可维护性:由于每个原子类都是独立的,因此可以更容易地修改、添加或删除它们。

2、ACSS 的使用示例

假设你有一个 ACSS 系统,其中包含以下原子类:

	/* Atomic CSS classes */  
	.padding-xs { padding: 4px; }  
	.padding-sm { padding: 8px; }  
	.padding-md { padding: 16px; }  
	.bg-red { background-color: red; }  
	.text-center { text-align: center; }  
	.font-bold { font-weight: bold; }

然后,你可以通过组合这些原子类来创建一个按钮的样式:

	<button class="padding-md bg-red text-center font-bold">Click Me!</button>

在这个例子中,按钮有中等内边距(padding-md)、红色背景(bg-red)、文本居中对齐(text-center)和粗体文本(font-bold)。这些样式都是通过组合原子类来实现的,而不是在一个单独的、复杂的 CSS 规则中定义的。

3、ACSS 的优缺点

优点

  • 易于维护:由于每个样式都是独立的,因此可以更容易地修改和扩展它们。
  • 可重用性高:原子类可以在整个项目中重复使用,减少了代码的冗余。
  • 灵活性:通过组合不同的原子类,可以轻松地创建复杂的样式。

缺点

  • HTML 标记变得冗长:由于需要添加多个类名来实现一个复杂的样式,HTML 标记可能会变得冗长和难以阅读。
  • 可能增加选择器的复杂性:如果过度使用 ACSS,可能会导致选择器的复杂性增加,从而影响性能。
  • 需要谨慎设计原子类:需要仔细设计原子类,以确保它们足够通用且可重用,同时避免创建太多冗余的类。

4、总结

ACSS 是一种将 CSS 规则分解为最小、可重用单元的 CSS 架构。它强调通过组合原子类来构建复杂的样式,从而提高样式的可重用性和可维护性。然而,使用 ACSS 时需要谨慎设计原子类,并注意 HTML 标记的冗长性和选择器的复杂性。

总结

个人简单总结:

  1. BEM更加侧重于通过规则的命名约定去编写样式。
  2. OOCSS更侧重于分离的概念:结构和皮肤分离,容器和内容分离
  3. SMACSS和ITCSS更注重从文件的角度去进行分离css
  4. ACSS则是最小原子的概念去组合css