首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >CSS 不变性

CSS 不变性

作者头像
疯狂的技术宅
发布2019-03-27 12:24:21
5360
发布2019-03-27 12:24:21
举报
文章被收录于专栏:京程一灯京程一灯

每当我给客户和研讨班学生提出下面这个建议时,他们都会非常震惊:

我推荐使用 !important

大多数情况下,大家的第一反应是厌恶—— !important通常是坏消息——不过,“大多数情况”并不等于“所有情况”……

和其他很多事情一样,总会有某些例外情况,在这种情况下遵守规定并不是什么好事,恰恰相反,我们需要破坏规定。

举个例子,英国的限速是 70 英里每小时(很不幸,我们还在使用“英里”)。你的车速不能超过 70,那是不合法的,就这么简单。

但是……如果你的朋友正在后座上飙血,你必须在他失血过多之前到达医院,那就别犹豫了,有多快开多快!

在 90% 的情况下,规则都是好的,我们最好遵守。但是一定有某些场合不属于这 90%。

开发者也不例外。我们必须明白,程序中的各种规则总会有不适用的场景。

随着年龄(或者说时间)的增长,我们会拥有更多知识。我经常告诫出血者不要使用 !important,但是当初学者们成长起来之后,他们就会意识到这个世界并非非黑即白,这时我们就可以更进一步介绍如何用好这个特性。

不过别着急,在我们介绍例外情况之前,先来研究一下规则本身。

永远不要冲动地使用 !important

随便使用 !important是一种极具危险性并且极其愚蠢的行为。使用 !important来摆脱现有 CSS 毫无疑问是很不明智的。这样做的后果就是越来越多的 !important

不要下意识地使用 !important,不要用 !important去解决冲突,不要冲动地使用 !important

解决冲突

如果你确实遇到了冲突,比如某些已经存在的样式覆盖了新样式,那有很多更加安全的解决方法。

如果需要提高某个 class 的优先级,可以把它和它自己串联起来(比如 .btn.btn{})。如果需要提高某个 ID 的优先级,可以用属性选择器重写(比如 [id="header"]{})。更多内容可以阅读文章解决冲突的技巧。

大多数情况下,你都不需要使用 !important

那什么情况下我们可以用它?

!important实现不变性

我真的非常喜欢不变性。一个东西在创建之后就再也不会发生改变,听起来超棒!如果我们知道某个东西永远保持不变,那写起代码来不就轻松多了吗?我真的超级喜欢不变性!

不过在 CSS 中想实现不变性难度很大,因为 CSS 是基于继承设计的,其中大量应用到可变性。不过有一种特殊的类型能充分利用不变性,并且不会带来任何问题:工具类(utility class)。

工具类是一些非常简单的类,用于解决非常具体、非常明确的问题。比如:

.u-text-center { text-align: center; }

.u-float-left { float: left; }

.u-text-large { font-size: 48px; }

它们都以 u-开头,告诉开发者它们是做什么用的,并且它们只包含一条样式。

上面这段代码中,所有的声明都不包含 !important,但是它们真的真的应该这样做。原因如下:

在 HTML 中使用 u-text-center这样的类时,我们做了一个非常确定、清晰的决定,那就是我们想让一段文字居中显示。毫无疑问是这样的。然而, .u-text-center{}选择器的优先级相对比较低,因此其他选择器可能会在无意中覆盖它。看看下面的例子:

.sub-content h2 {
  ...
  text-align: left;
}

.u-text-center {
  text-align: center;
}
<div class="sub-content">
  <h2 class="u-text-center">...&lt;/h2&gt;
&lt;/div&gt;

不幸的是, .sub-content h2{}的优先级比 .u-text-center{}高,所以 h2最后还是左对齐,虽然我们设置了 text-align:center;。这里就有问题了, u-text-center无法让某些内容居中。

简而言之,这就是为什么我们应该在工具样式中使用 !important。我们希望工具样式是不变的;无论在什么情况下,当我们使用 u-text-center的时候,一定是想要让文字居中。

给工具类加上 !important,让它们不可变。

当然了,在一个完美世界中(无论是什么世界),我们可以杜绝 .sub-content h2{}这样的选择器出现在 CSS 中,但是我们无法避免:

  • 其他人编写这样的 CSS 选择器;
  • 项目中之前已经有这样的选择器。

具备适应性和防御性的系统的设计目标并不是完美世界,而是现实世界。在现实世界中,人们就是会写出各种各样的 CSS。使用 !important实现不变性会避免其他人带来的各种冲突。

关于工具类

我觉得最好再简单介绍一下各种常见的工具类。

如果你使用的不是Tachyons/Basscss/Atomic CSS这样的函数式 CSS(这些完全是另一个话题),那你一定不想在 HTML 中看到大量工具类。

不过,如果我们使用了更加模块化和组件化的 CSS 组织方法(我们确实可能这样做),那大多数类都会是这样的:

.c-carousel {}

.o-media__body {}

.c-nav-primary {}

.c-btn--large {}

它们会有一个作用域(也就是BEM中的一个块),并且被封装起来。这样做的好处是在 HTML 中可以清楚地看出类之间的关系(在函数式 CSS 中这很难——或者说不可能——办到),如下所示:

<blockquote class="o-media  c-testimonial">
  <img class="o-media__img c-testimonial__photo" ... />
  <p class="o-media__body c-testimonial__text">...&lt;/p&gt;
&lt;/blockquote&gt;

这里我们可以轻松看出两种完全不同的样式。

但!是!假设我们想让某一个 testimonial 有更大的 margin-bottom,该怎么做?显然并不是所有的 testimonial 都需要它,只有页面中某个特定位置的 testimonial 需要。这种需求需要用一种特殊的实现方式。

这里我们用工具类实现:

<blockquote class="o-media
                   c-testimonial
                   u-margin-bottom-large">

我们之所以使用工具类,是因为额外的 margin-bottom其实和 testimonial 没什么关系;它只和上下文相关,并且只需要用那么几次,所以我们不需要把它写到 testimonial 的 CSS 中。

恰恰相反,如果我们有一种字体更大的 testimonial,那网站上的其他 testimonial 也可能会用到它,那就不能写成工具类了。这并不是一个临时应急用的类,而是属于 testimonial 本身,所以需要把它封装到 BEM 中:

<blockquote class="o-media
                   c-testimonial  c-testimonial--large">

总结一下:

如果这个样式会长期存在,那就正式把它加到 CSS 中。如果只是临时使用或者只是一个特例,那就是用工具类。

工具类可能是我“最不喜欢”的一种类,因为它们和行内样式(inline style)其实差不太多。谨慎使用工具类,只用它实现临时改动或者某些极其特殊的改动。


往期精选文章

使用虚拟dom和JavaScript构建完全响应式的UI框架

扩展 Vue 组件

使用Three.js制作酷炫无比的无穷隧道特效

一个治愈JavaScript疲劳的学习计划

全栈工程师技能大全

WEB前端性能优化常见方法

一小时内搭建一个全栈Web应用框架

干货:CSS 专业技巧

四步实现React页面过渡动画效果

让你分分钟理解 JavaScript 闭包



小手一抖,资料全有。长按二维码关注京程一灯,阅读更多技术文章和业界动态。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2017-11-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 京程一灯 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 永远不要冲动地使用 !important
    • 解决冲突
    • 用 !important实现不变性
    • 关于工具类
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档