normalize、reset与base

写在前面

一个故事:

你知道normalize吗?与reset的区别是什么?

面试官问,我编(当时确实不知道,但两个单词的字面意思其实很明确了)

一.reset

reset:重置,清零

最粗暴的方式:

* {padding:0; margin:0;}

把所有标签全都扒光。bodyh1-h6divarticle等一大推本来各不相同的标签,现在长的一模一样了,仅剩名字作为最后的尊严

当然,也有温和一点的(更长的):

body, dl, dd, h1, h2, h3, h4, h5, h6, p, form{margin:0;}
ol,ul{margin:0; padding:0;}

温和reset的原则是:只去掉需要去掉的。比如div本来就啥也没穿,还被扒了一遍,这不人道

含reset的样式结构可能是这样:

reset.css   // 去掉所有默认样式
common.css  // 项目维护的公共样式
page.css    // 业务需要的样式(无法复用)

按顺序引入,用下面的覆盖掉上面的。所以一个样式属性可能经过层层重写后才以最终的模样展现给用户,存在冗余reset的问题:如果某块样式注定是需要支持订制的,那就一定会被后来的css覆盖,没必要先用reset扒光吧?

二.normalize

normalize:归一化,使正常化、标准化

Normalize.css makes browsers render all elements more consistently and in line with modern standards. It precisely targets only the styles that need normalizing.

normalize做了几件事情:

  • 保留浏览器默认样式中有用的部分

  • 同时保证跨浏览器一致性(修复各浏览器中存在的不合W3C规范的问题)

  • 在合适的地方设置默认值

normalize是补丁性质的,不像reset是破坏性的,例如normalize.css源码

/**
 * Add the correct display in IE 9-.
 * 1. Add the correct display in IE.
 */

figcaption,
figure,
main { /* 1 */
  display: block;
}

/**
 * 1. Add the correct box sizing in Firefox.
 * 2. Show the overflow in Edge and IE.
 */

hr {
  box-sizing: content-box; /* 1 */
  height: 0; /* 1 */
  overflow: visible; /* 2 */
}

此处通过前端方案修复了浏览器存在的样式问题,同时考虑低版本浏览器兼容,这里倾向于“标准化”。此外,也有“正常化”的一面:

/**
 * 1. Change the default font family in all browsers (opinionated).
 * 2. Correct the line height in all browsers.
 * 3. Prevent adjustments of font size after orientation changes in IE and iOS.
 */

html {
  font-family: sans-serif; /* 1 */
  line-height: 1.15; /* 2 */
  -ms-text-size-adjust: 100%; /* 3 */
  -webkit-text-size-adjust: 100%; /* 3 */
}

前辈已经解读过源码了,请查看关于CSS Reset 那些事(二)之 Normalize.css 源码解读

三.normalize与reset的区别

一个段子:

CSS Reset 是革命党,CSS Reset 里最激进那一派提倡不管你小子有用没用,通通给我脱了那身衣服,凭什么你 body 出生就穿一圈 margin,凭什么你姓 h 的比别人吃得胖,凭什么你 ul 戴一胳膊珠子。于是 *{margin:0;} 等等运动,把人家全拍扁了。看似是众生平等了,实则是浪费了资源又占不到便宜,有求于人家的时候还得贱贱地给加回去,实在需要人家的默认样式了怎么办?人家锅都扔炉子里烧了,自己看着办吧。

Normalize.css 是改良派。他们提倡,各个元素都有其存在的道理,简单粗暴地一视同仁是不好的。body 那一圈确实挤压了页面的生存空间,那就改掉。士农工商,谁有谁的作用,给他们制定个规范,确保他们在任何浏览器里都干好自己的活儿。

引自知乎会撸代码的段子手的回答

reset的特点

目标:强制所有浏览器表现一致

去掉大多数来自浏览器的默认样式,保证common, page等样式下层是整齐划一的初始表现

所以一般意义的reset是破坏性的,统统扒光

主要存在2个问题:

  • 冗余reset,影响性能

    无论是写错的reset(本不需要),还是在上层一定会被覆盖的reset(没必要),都增大了样式文件,影响了渲染性能

    容易杀错,也容易放过。精确的高性能reset?很难实现,甚至不存在(除FF, Chrome, Safari外,还有一大堆xx浏览器,谁知道它默认样式是啥呀)

  • 分组缺少语义,难以维护

    reset中对标签的分类不考虑语义,只关注默认表现

    引发的后果就是调试工具查看某元素,关注某个属性,一层层追下去,最后看到一长串不相关的标签被绑在一起,应用了一两条规则

至于性能,在成为问题之前都不是问题。据传言* {padding:0; margin:0;}对渲染对影响也只是2ms,如果真是这样,那就不用多想了,直接统统扒光最好。因为比起更复杂(更长,更人道)的reset带来的负面影响(增大了样式文件),渲染时的2ms比芝麻还要小

维护的问题,其实还是指向精确的高性能reset,如果reset恰到好处,样式问题应该与reset无关,如果调试中发现需要往下层追,就说明reset不够好

“不reset行吗?”

“当然不行呀,不reset的话,那么多浏览器,保不齐有什么奇怪的默认样式呢,前端应该有1px的执着,精确还原设计稿”

其实仔细想想,为什么我们需要reset?就因为大家都在用?

确实很多reset样式在业务中永远不会用到(老古董legendfieldset以及新的语义化标签asidesection对于纯移动页面是几乎不需要的),真正有用的常用的可能只是body {margin: 0; },其它都要么在用的时候需要全面重写,要么永远用不到

所以几年前掀起了一场no reset运动,后来迎来了normalize……但答案究竟是什么?

normalize的特点

从源码可以发现normalize就像补丁一样,让浏览器默认样式更“正常”一些:

/* 1.样式补丁,修补浏览器差异,使其表现贴近标准 */
/**
 * Prevent the duplicate application of `bolder` by the next rule in Safari 6.
 */
b,
strong {
  font-weight: inherit;
}
/**
 * Add the correct font weight in Chrome, Edge, and Safari.
 */
b,
strong {
  font-weight: bolder;
}

/* 2.微量的reset */
/**
 * Add the correct background and color in IE 9-.
 */
mark {
  background-color: #ff0;
  color: #000;
}
/**
 * Prevent `sub` and `sup` elements from affecting the line height in
 * all browsers.
 */
sub,
sup {
  font-size: 75%;
  line-height: 0;
  position: relative;
  vertical-align: baseline;
}
sub {
  bottom: -0.25em;
}
sup {
  top: -0.5em;
}

同样,通过源码也能发现它并不是reset的替代品:

  • reset像压路机,开过去之后路面非常平整

  • normalize像沥青,填补路面上的裂缝,小坑

但是,我们需要这层沥青吗?就因为Bootstrap用了我们就得用?

对于纯移动页面来说,normalize里98%的样式都用不着,很巧,有用的几行可能还是:

/**
 * Remove the margin in all browsers (opinionated).
 */

body {
  margin: 0;
}

当然,Bootstrap需要同时支持PC和移动端,适配大屏小屏,一个框架引入这些兼容代码自然没错,更健壮了

但我们的应用可能真的不需要normalize,即便需要,可能也只需要取其中真正能用到的30%,其余部分应该是根据业务特点,去掉某些丑丑的默认样式(比如table),再置入基础样式,避免在每个页面中都去设置这些东西,那么最后产生的这个css就叫——base.css

四.css三层结构

  • base: 基本样式

    站点级的,最基础,最通用的样式,不同风格不同内容的站点可以共用base样式

    base是原子的,不可再分,比如兼容性良好的flex, clearfix等等

    reset与base并列,作为基本样式组件,当然,也可以把简单的reset放在base层里

  • common: 通用样式

    模块级的,自定义的样式模块,可以供各个页面复用

    在base层基础上提供更复杂的样式模块,比如日历,popup等等

  • page: 页面样式

    页面级的,不需要复用的样式

    针对具体页面,添加特有的样式,比如具体色值,字体,hack等等

合理的分层能够有效提高样式的复用性,可以通过在高层简单地重写低层某条样式规则来改变最终样式;此外还能提高样式的可维护性,各层分工明确,新增样式对号入座,html中以class组合的方式来实现最终样式

base层和common层应该由很少的人来负责管理维护,不会经常变动,但可以扩展,开发者直接针对UI设计稿完成page层样式,实现视觉效果,编写page层样式时同样可以按照三层结构来组织,例如:

/* base */
body {
    background-color: #eee;
}
h1 {
    border-bottom: 1px solid #ccc;
}
/* common */
.panel {
    border: 1px solid #ddd;
}
.line {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
/* page */
h1 span {
    border: 1px solid red;
    border-raduis: 3px;
}
.panel .line {
    line-height: 1.5em;
}

五.总结

reset?normalize?需要吗?不需要吗?

为业务量身定制的才是最好的,精简、高效

参考资料

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*

code