探索SMACSS:CSS的可扩展和模块化架构

本文概述

当我们在大型项目上或与开发人员团队合作时, 我们经常发现我们的代码混乱, 难以阅读且难以扩展。时间流逝后尤其如此, 我们回来再看一遍-我们必须尝试保持与编写时相同的心态。

因此, 许多人所做的就是创建CSS架构来帮助设计其代码样式, 从而使CSS更具可读性。 SMACSS(即CSS的可扩展和模块化体系结构)旨在做到这一点。这是我采纳的Jonathan Snook提供的一组特定的CSS体系结构指南。

现在, SMACSS的架构方法与Bootstrap或Foundation这样的CSS框架有些不同。相反, 它是一组规则, 更像是模板或指南。因此, 让我们深入研究一些CSS设计模式, 以了解如何使用它们来使我们的代码更好, 更简洁, 更易于阅读且更具模块化。

每个SMACSS项目结构都使用五类:

  1. 基础
  2. 布局
  3. 模块
  4. 状态
  5. 主题

基础

在SMACSS中, 基本样式定义元素在页面上任何地方的外观。它们是默认值。如果你使用的是重置样式表, 这将确保即使浏览器内部的硬编码基本CSS默认值之间存在差异, 所得到的样式在各个浏览器中也相同。

在基本样式中, 你应仅包括裸元素选择器或具有伪类的选择器, 而不包括类或ID选择器。 (你应该有充分的理由将类或ID放入其中, 也许仅当你在对第三方插件的元素进行样式设置并且需要重写该特定元素的默认样式时才可以使用。)

这是基本文件单元外观的示例:

html {
    margin: 0;
    font-family: sans-serif;
}

a {
    color: #000;
}

button {
    color: #ababab;
    border: 1px solid #f2f2f2;
}

因此, 它应包括默认大小, 边距, 颜色, 边框以及你计划在整个网站上使用的任何其他默认值。你的版式和表单元素应具有统一的样式, 该样式应出现在每个页面上, 并赋予它们外观和感觉, 使它们成为同一设计和主题的一部分。

不论是否使用SMACSS, 我都强烈建议尽可能避免使用!important, 并且不要使用深层嵌套, 但是我将在本文后面的内容中进一步讨论。另外, 如果你的做法是使用重置CSS, 则应在其中添加它。 (我更喜欢使用Sass, 因此我只将其包含在文件的顶部, 而不必将其复制或与每个页面的<head>元素分开引用。)

相关:Sass主题:SCSS教程

布局

布局样式会将页面分为几个主要部分-例如导航或手风琴之类的部分, 而不是顶级部分:

SMACSS布局样式示例:页眉,侧边栏,内容/主要和页脚

SMACSS布局样式适用于主要部分, 例如页眉, 侧边栏, 内容/主要和页脚。

这些布局将包含多个CSS模块, 例如盒子, 卡片, 无序列表, 图库等, 但是我将在下一节中详细讨论这些模块。让我们考虑一个示例网页, 以了解我们可以分为哪些布局:

可以使用SMACSS将示例网页组织为页眉,主要和页脚布局样式

在这里, 我们有页眉, 主要和页脚。这些布局具有模块, 例如顶部的页眉和徽标, 主要的框和文章以及页脚的链接和版权。我们通常为布局提供ID选择器, 因为它们不会在页面上重复, 而且是唯一的。

另外, 你还应该在布局样式的规则前加上字母l, 以将其与模块样式区分开。通常, 你会在此处设置特定于布局的内容的样式, 例如边框, 对齐方式, 边距等。页面那部分的背景也很有意义, 即使它看起来不完全是特定于布局的。

这是一个外观的示例:

#header {  
    background: #fcfcfc;
}

#header .l-right {
    float: right;
}

#header .l-align-center {
    text-align: center;
}

你还可以添加这些对齐方式的帮助器, 只需将适当的类添加到其子级或对齐其文本即可轻松地定位元素。

再举一个例子, 你可以在布局框上使用一些默认边距, 例如.l-margin的边距为20px。然后, 无论你想在哪里填充一些容器, 元素, 卡片或盒子, 都只需向其添加l-margin类。但是你想要一些可重用的东西:

.l-full-width {
    width: 100%;
}

内部没有这样的耦合:

.l-width-25 {
    width: 25px;
}

我想花一点时间谈论SMACSS中的命名约定。如果你从未听说过CSS中的命名空间的概念, 它基本上是在另一个元素的开头添加名称, 以帮助将其与其他元素区分开。但是为什么我们需要这个呢?

我不知道你是否遇到以下问题。你正在编写CSS, 并在某物上贴了标签-你可以随意放置任何样式, 然后将其称为.label。但是后来你又遇到了另一个元素, 并且你也希望它成为.label, 但是样式有所不同。因此, 两个不同的事物具有相同的名称-命名冲突。

命名空间可帮助你解决此问题。最终, 它们在一个级别上被称为同一事物, 但是它们具有不同的名称空间(不同的前缀), 因此可以表示两种不同的样式:

.box--label {
    color: blue;
}

.card--label {
    color: red;
}

模块

就像我之前提到的那样, SMACSS模块是可在页面上重用的较小代码段, 它们是单个布局的一部分。这些是CSS的一部分, 我们希望将它们存储在单独的文件夹中, 因为我们将在一个页面上包含很多此类内容。随着项目的发展, 我们可以使用文件夹结构最佳实践(即按模块/页面)进行划分:

使用SMACSS和Sass的示例文件/文件夹层次结构

因此, 在前面的示例中, 我们有一篇文章, 它本身可以是一个模块。 CSS在这里应该如何组织?我们应该有一个.article类, 它可以具有子元素标题和文本。因此, 为了能够将其保留在同一模块中, 我们需要为子元素添加前缀:

.article {
    background: #f32;
}

.article--title {
    font-size: 16px;
}

.article--text {
    font-size: 12px;
}

你可能会注意到, 我们在模块前缀之后使用了两个连字符。原因是有时模块名称有两个词或它们自己的前缀, 例如big-article。我们需要有两个连字号才能区分出子元素的哪一部分, 例如比较大文章标题与大文章标题和大文章文本。

另外, 如果特定模块占据页面的大部分, 则可以将模块嵌套在模块内:

<div class="box">
    <div class="box--label">This is box label</div>
    <ul class="box--list list">
        <li class="list--li">Box list element</li>
    </ul>
</div>

在此简单示例中, 你可以看到box是一个模块, list是其中的另一个模块。所以list–li是list模块的子元素, 而不是box的子元素。这里的关键概念之一是每个CSS规则最多使用两个选择器, 但是在大多数情况下, 只有一个带有前缀的选择器。

这样, 我们可以避免重复规则, 并且可以避免在具有相同名称的子元素上使用额外的选择器, 从而提高了速度。但这也有助于我们避免使用不必要的!important-style规则, 这是CSS项目结构不良的标志。

好(注意单个选择器):

.red--box {
    background: #fafcfe;
}

.red-box--list {
    color: #000;
}

错误(请注意选择器内的重复和重叠的引用方法):

.red .box {
    background: #fafcfe;
}

.red .box .list {
    color: #000;
}

.box ul {
    color: #fafafa;
}

状态

SMACSS中定义的状态是一种描述模块在不同动态情况下的外观的方式。因此, 这部分实际上是为了实现交互性:如果元素被认为是隐藏, 扩展或修改的, 我们希望具有不同的行为。例如, jQuery手风琴将需要帮助来定义何时可以看到元素的内容或看不到元素的内容。它有助于我们在特定时间定义元素的样式。

状态与版图应用于同一元素, 因此我们添加了一条附加规则, 它将覆盖先前的规则(如果有)。状态规则具有优先权, 因为它是规则链中的最后一个规则。

与布局样式一样, 我们倾向于在此处使用前缀。这有助于我们认识他们并给予他们优先权。在这里, 我们使用is前缀, 如在is-hidden或is-selected中。

<header id="header">
    <ul class="nav">
        <li class="nav--item is-selected">Contact</li>
        <li class="nav--item">About</li>
    </ul>
</header>
.nav--item.is-selected {
    color: #fff;
}

在这里, 可以使用!important, 因为状态经常用作JavaScript修改, 而不是在渲染时使用。例如, 你有在页面加载时隐藏的元素。在按钮上单击, 你要显示它。但是默认类是这样的:

.box .element {
    display: none;
}

因此, 如果你仅添加以下内容:

.is-shown {
    display: block;
}

即使通过JavaScript将.is-shown类添加到元素中, 它也将保持隐藏状态。这是因为第一个规则深两个级别, 并将覆盖它。

因此, 你可以这样定义状态类:

.is-shown {
    display: block !important;
}

这就是我们将状态修饰符与布局修饰符区分开的方式, 后者仅适用于页面的初始加载。现在这将起作用, 同时保持最小选择器的优点。

主题

这应该是最明显的, 因为它包含了原色, 形状, 边框, 阴影等的规则。通常, 这些是在整个网站上重复的元素。我们不想每次创建它们时都重新定义它们。相反, 我们想要定义一个唯一的类, 我们仅在以后将其添加到默认元素中。

.button-large {
    width: 60px;
    height: 60px;
}
<button class="button-large">Like</button>

不要将这些SMACSS主题规则与基本规则混淆, 因为基本规则仅以默认外观为目标, 并且它们往往类似于重置为默认浏览器设置, 而主题单元更像是一种样式类型, 它可以给出最终外观, 此特定配色方案唯一。

如果网站具有不止一种样式或在不同状态下使用的几个主题, 因此主题规则也很有用, 因此可以在页面上的某些事件期间轻松更改或交换主题, 例如与主题切换按钮。至少, 它们将所有主题样式都保留在一个位置, 因此你可以轻松更改它们并使它们井井有条。

CSS组织方法论

我已经介绍了此CSS体系结构构想的一些关键概念。如果你想了解更多有关此概念的信息, 可以访问SMACSS的官方网站并深入了解它。

是的, 你可能可以使用更高级的方法, 例如OOCSS和BEM。后者涵盖了几乎完整的前端工作流及其技术。 BEM选择器可能对某些人有用, 但有些人可能会发现它们太长, 不堪重负, 使用起来也太复杂。如果你需要更简单, 更容易拿起并融入到你的工作流程中的东西, 并且还为你和你的团队定义了基本规则, 那么SMACSS非常适合。

新团队成员不仅容易了解以前的开发人员做了什么, 而且可以立即开始工作, 而编码风格没有任何差异。 SMACSS只是CSS架构, 它可以做到如其所言, 无所不能。

微信公众号
手机浏览(小程序)
0
分享到:
没有账号? 忘记密码?