[译]css编码技巧 css coding techniques

本文根据《CSS coding techniques》所译,如果译得不好或有不对之处还请多多指点。如需转载此译文,需注明英文出处:https://hacks.mozilla.org/2016/05/css-coding-techniques/

最近,我们看到很多苦恼于CSS的人,从初学者到有经验的开发者。有些人不喜欢它工作的方式,并想知道如果用不同的语言来代替CSS是否会更好——CSS处理器从这个思维中涌现。一些期望他们将必定写更少的代码使用CSS框架(我们已经看到在先前一篇文章,为什么通常不是这样的情况)。一些人开始完全地抛弃CSS并使用JavaScript应用样式。
但你并不总是需要引入CSS处理器在你的工作流中。你不需要将一个臃肿的框架作为任何项目的默认起点。使用JavaScript去做CSS的事情意味着这只是一个可怕的想法。
在这篇文章中我们将看到写出更好的,更容易维护的CSS代码的一些提示和建议,因此你的样式表更短,有更少的规则。CSS可以感觉像是一个得心应手的工具而不是一个负担。

“最小可行选择器”

CSS是一门你指定将DOM中的元素样式化的规则的陈述性语言。在这种语言中,按照被应用的顺序一些规则优先于其他的,像内联样式重写了一些以前的规则。
例如,如果我们有这样的HTML和CSS代码:

<button class="button-warning">
.button-warning {
  background: red;
}

button, input[type=submit] {
  background: gray;
}

尽管.button-warningbutton, input[type=submit]规则之前被定义,它将覆盖后面的background属性。为什么?决定哪一个规则将覆盖另一个规则的样式的标准是什么?
特异性(优先级)
一些选择器被认为比其他的更具体:例如一个#ID选择器将覆盖.calss选择器。
如果我们使用了一个比它实际需要更具体的选择器,会发生什么?如果我们稍后要覆盖这些样式,我们需要一个更具体的选择器。如果我们稍后需要覆盖这个更具体的选择器,我们将需要…是的,它就像一个雪球越滚越大,最终将变得非常难以维护。
所以,无论什么时候你写下你的选择器,问自己:这是能够生效的最不具体的选择器?
所有的优先级规则都正式地定义在W3C的CSS选择器规范中,这是了解CSS选择器的每一个细节的方式。对于一些更容易理解,阅读这篇关于CSS的特异性(优先级)

不要在错误上扔新规则

让我们想象一下这种典型的情况:你的CSS有一个bug并且你找到有错误样式的DOM元素。你会意识到它是在某种程度上继承了一个不该有的属性。
不要只是把更多的CSS写在这。如果你这样做,你的代码库将增长的非常庞大,并且定位未来的错误将更困难。
相反,停止这么做,退后一步,并使用浏览器中的开发工具检查该元素,并查看整个级联。确定哪些规则应用了你不想要的样式。并修改现有的规则,这样就不会有意想不到的后果。
在Firefox浏览器中,你可以通过右键单击一个页面中的元素,选择检查元素来调试级联。
检查元素
看着这层层的级联。你可以看到所有的规则按照它们被应用的顺序应用到一个元素上。顶部的条目是具有更高的优先级的,可以重写先前的样式。你可以看到有一些规则的属性划掉了:这意味着一个更具体的规则覆盖了这个属性。
你不仅可以看到规则,事实上你可以切换显示它们,或随时改变他们和观察结果。它对于修复bug非常有用!
所需的修复可能是一个规则的变化,或它可能是在级联中不同点的一个规则变化。修复可能需要一个新的规则。至少你会知道这是正确的调用和你的代码库所需要的东西。
这同样是一个很好的时机去寻找重构机会。虽然CSS并不是一种编程语言,它是有源代码的,你应该给它和给你的JavaScript或Python同样的考虑:它应该是干净的,可读的和需要时可被重构的。

别!important事情

这是隐含在以前的建议中的,但因为它是关键的,我想强调一下:在你的代码中不要使用!important
!important是一个CSS中允许你打破级联的特性。CSS代表“层叠样式表”,这是一个暗示。
当你没有时间或意向修复你的级联时,!important经常被用来急于修复一个错误。当你引入有着非常具体的规则的CSS框架并且很难覆盖他们时也被大量使用。
当你添加!important到一个属性,浏览器会忽略其他更高的特异性(优先级)规则。当你!important一条规则覆盖另一条也被标记为!important的规则的时候,你就会知道你真的惹上麻烦了。

有一个合法使用!important的情况——在使用开发工具调试的时候。有时候你需要找到一个属性的某个值来修复你的bug。在开发者工具中使用!important和随时修改CSS规则会让你发现那些值,当你忽略级联的时候。
一旦你知道CSS的哪部分生效,你就可以回到你的代码中,看看从级联的角度你要包括哪些CSS。

生活不止px%

与单位px(像素)和%(百分比)一起工作是相当直观的,所以我们将集中在不为人知或不太直观的单位上。
emrem
最著名的相对单位是em,1em相当于该元素的字体大小。
让我们想象一下以下HTML:

<article>
  <h1>Title</h1>
  <p>One Ring to bring them all and in the darkness bind the.</p>
</article>

和一个样式表仅有这条规则:

article {
  font-size: 1.25em;
}

默认情况下大多数浏览器应用16像素的基础字体大小到根元素上(顺便说一下,这是由用户可重写的一个很好的辅助功能)。因此,该文章元素的段落文本可能会以20像素(16 * 1.25)的font-size呈现。
h1呢?为了更好地了解将要发生什么,让我们在样式表上添加另一条CSS规则:

h1 {
  font-size: 1.25em;
}

虽然它也是1.25em,和article一样,我们必须考虑到em单位的继承。例如,有一个h1是body的直接子元素,会有一个20像素(16×1.25)的font-size。然而,我们的h1在一个有着不同于根元素的font-size元素内(我们的article元素)。在这种情况下,1.25指的是我们级联的font-size,因此h1将呈现一个25像素(16×1.25×1.25)的font-size
通过这种方式,而不是在你的大脑中做所有的乘法链,你可以仅使用检查元素计算后标签页,显示实际的,最终的像素值:
计算属性
em单位是真的非常通用的,并且即使是动态的它很容易改变页面上所有大小(不仅是font-size,连同其他属性如line-height,或width)。
如果你喜欢em的“相对于基本尺寸”的部分,但不喜欢继承部分,你可以使用rem单位rem单位就像是忽略了继承而只采纳根元素的大小。
所以,如果我们拿之前的CSS并把h1中的em单位换成rem

article { font-size: 1.25em; }
h1 { font-size: 1.25rem; }

所有的h1元素会有一个20像素的计算后的font-size(假设16px为基础尺寸),无论他们是否在article标签内。
vmvh
vmvh是视口单位。1vw是1%视口的宽度,而1vh是 1%视窗的高度。
它们是非常有用的,如果你需要一个需要占据整个屏幕的,并不总是与实际的body尺寸相关的UI元素(就像是典型的模态框的半透明黑暗背景)。
其他单位
有一些其他的单位,可能不是一般的或通用的,但你会不可避免地遇到他们。关于他们可以在MDN学到更多。

使用flexbox

关于这个我们在以前的一篇关于CSS框架的文章中已经谈论过了,但flexbox模块简化了制作布局和/或对齐的任务。如果你对flexbox感到陌生,看看这个入门指南
是的,今天你可以用flexbox。除非由于商业原因你真的需要支持古老的浏览器。对于flexbox浏览器目前支持94%以上。所以你可以停止书写那些浮动的难以调试和维护的div
此外,留意对即将到来的网格模块,这将使布局变成轻而易举的事情。

当使用CSS处理器…

CSS编译器像Sass或Less在前端开发的世界很受欢迎。他们是强大的工具,当好好的利用可以让我们更有效地书写CSS。
不要滥用选择器嵌套
这些处理器或“编译器”中有一个共同特征是选择器嵌套。所以,例如,这个Less代码:

a {
  text-decoration: none;
  color: blue;

  &.important {
    font-weight: bold;
  }
}

会转换成如下的CSS规则:

a {
  text-decoration: none;
  color: blue;
}

a.important {
  font-weight: bold;
}

此功能允许我们写更少的代码和组织影响元素——通常在DOM树中是一起的——的规则,那些元素。这方便调试。
然而,滥用这个功能也是常见的,最终在CSS选择器中复制整个DOM。所以,如果我们有以下HTML:

<article class="post">
  <header>
    <!-- … -->
    <p>Tags: <a href="..." class="tag">irrelevant</a></p>
  </header>
  <!-- … -->
</article>

我们可以在CSS样式表中找到这个:

article.post {
  // ... other styling here
  header {
    // ...
    p {
      // ...
      a.tag {
        background: #ff0;
      }
    }
  }
}

主要的缺点是,这些CSS规则有非常具体的选择器。我们已经看到,这是我们应该避免的。我在另一篇文章中谈到过度嵌套也有其他的缺点。
总之:不要让嵌套生成你不会自己输入的CSS规则
包括与扩展
CSS处理器的另一个有用的功能是mixins(混合),这是CSS的可重复使用的块。例如,假设我们要设计按钮,其中大多数有一些基本的CSS属性。我们可以在Less中创建一个像这样的混合:

.button-base() {
  padding: 1em;
  border: 0;
}

然后创建一个这样的规则:

.button-primary {
  .button-base();
  background: blue;
}

这会产生以下的CSS:

.button-primary {
  padding: 1em;
  border: 0;
  background: blue;
}

如你所见,重构公共代码非常方便!
除了“包括”一个混合,同样可以选择“扩展”或“继承”它(工具与工具间确切的术语是不同的)。它所做的事情是合并多个相同规则的选择器。
让我们看看一个例子使用先前的.button-base混合:

.button-primary {
  &:extend(.button-base)
  background: blue;
}

.button-danger {
  &:extend(.button-base)
  background: red;
}

这将翻译为:

.button-primary, .button-danger {
  padding: 1em;
  border: 0;
}

.button-primary { background: blue; }
.button-danger { background: red; }

有些在线文章告诉我们只使用“包括”,而有些告诉我们只使用“扩展”。事实是,他们产生不同的CSS,他们本质上是没有错误的,并根据你的实际情况,使用一个或另一个会更好。
如何选择它们?“原生写法我会这样写吗?“经验法则再次适用。


我希望这能帮助你思考你的CSS代码和写出更好的规则。记得我们先前所说的:CSS代码,因此,和你的其他的代码基础值得相同级别的注意和关心。如果你给它一些爱,你会得到回报。
关于Belén Albeza
Belén作为工程师和游戏开发商在Mozilla开发者关系工作。她关心Web标准,高质量的代码,可访问性和游戏开发。
www.belenalbeza.com
@ladybenko
查看更多Belén Albeza的文章