原文链接:

https://elad.medium.com/normalize-css-or-css-reset-9d75175c5d1e

本文已同步归纳在 Github

更新


[2021-2-22]

  • Initial release

[2021-2-26]

Added

  • 完成剩余章节的翻译

概述


通常情况下,我们希望某个 HTML 元素在不同浏览器上具有相同的展示效果。但是遗憾的是,每个浏览器处理 HTML 展示的方式都不同。

那么到底是使用 Normalize CSS 还是 CSS Reset 来消除不同浏览器的样式差异,目前还是存在争议的。

1.png

在深入讲解我推荐的使用方式之前,我首先要向大家解释一下几个你们可能不太熟悉的术语。

CSS 的 User-Agent 样式

在渲染 HTML 页面的时候,浏览器会在应用你自己编写的样式之前,首先应用其自身的基础样式表。举个例子,从 <h1><h6> 的 HTML 标签在所有的浏览器里面的展示效果都和其它普通文本不同:一般情况下,诸如 <h1> 这类标签的文字会大一些、字体会粗一些(font-weight: bold),并且会有向上 & 向下两个方向的外边距。

2.png

虽然所有浏览器都应用了它们自己的默认样式表,但是每个浏览器的默认样式表彼此之前也存在差异,所以会产生一些问题,这也就是本文所探讨的。

有两种方式可以解决不同浏览器的样式不一致的问题:Normalize CSSCSS Reset。你可以把 Normalize CSS 想象为一个温和的小绵羊;把 CSS Reset 想象为一个粗鲁的大怪兽。下面,让我来举例讲解。

Normalize CSS

Normalize.css 是一个小型的 CSS 文件,使得 HTML 元素的默认样式提供了跨浏览器的一致性。

这就意味着如果我们在 W3C 上查阅浏览器所应用的样式的规范的时候,不同浏览器的规范是不一样的,而 normalize.css 会修复不同浏览器产生的样式差异。

但是对于 IE 和 EDGE 这样的浏览器,normalize.css 并不能按照规范来抹平差异,因此 normalize.css 会把 IE 和 EDGE 中特定的样式应用到其它浏览器中。

举个实际的例子:对于类似 <article> / <aside> / <nav> / <section> 标签内部的 <h1> 标签,Chrome、Safari 和 Firefox 渲染得到的最终 font-size 会小于单独的 <h1> 标签,并且 margin 大小也有所不同。<article> / <aside> / <nav> / <section> 标签内部的 <h1> 标签在 Chrome、Safari、Firefox 的默认样式表(User-Agent-Stylesheet)里的样式如下:

1
2
3
4
5
:-webkit-any(article,aside,nav,section) h1 {
font-size: 1.5em;
margin-block-start: 0.83em;
margin-block-end: 0.83em;
}

而 IE 和 EDGE 则很少出现上述这种情况,所以理论上我们可以把同样的样式直接复用到 IE 和 EDGE 浏览器上,但是由于 IE/EDGE 并没有 “any” 选择器,所以直接复用是不可取的。因此,Normalize CSS 索性直接把 IE/EDGE 中的 <h1> 样式作为基准样式。

示例代码如下:

1
2
3
4
/*
Chrome、Firefox 和 Safari 浏览器中的 `<article>` / `<aside>` / `<nav>` / `<section>` 标签内部的 `<h1>` 标签的正确的文字大小和外边距
*/
h1 { font-size: 2em; margin: 0.67em 0; }

Normalize.cssNicolas Gallagher 在 Github 上开源的一款项目:

https://github.com/necolas/normalize.css/blob/master/normalize.css

Reset CSS

使用 Reset CSS 就意味着我们不再需要浏览器的默认样式。“CSS Reset” 会把浏览器的 user-agent 样式全部重置掉,这样我们在写项目的时候就可以按需定义 CSS 样式。

上个章节的示例中使用 Reset CSS 也是可以正常工作的,对于 <h1><h6> 这些标签的默认样式:更多情况下我们并不想要浏览器提供的默认的 font-sizemargin

CSS Reset 分很多种,如下是从 Eric Meyer 编写的 CSS Reset 样式文件中摘取的一小部分:

1
2
3
4
5
6
7
8
html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed,  figure, figcaption, footer, header, hgroup,  menu, nav, output, ruby, section, summary, time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}

解释一下上面的代码:我们给所有 HTML 元素定义了无内边距、无外边距、无边框、相同的字体大小以及相同的对齐方式。

上面的代码虽然已经重置了 <h1><h6> 以及 <ul><li> 等标签的样式,但事实上看起来很臃肿,原因如下:

  • 充斥了大量的选择器
  • 大量无意义的样式覆盖
  • 很难调试

3.png

如何同时使用 Normalize CSS & CSS Reset


我的建议是使用 Normalize CSS,但是你可以在其中掺杂一些 CSS Reset

在我自己的项目里面,我深切地体会到了 Normalize CSS 和 CSS Reset 带来的好处:一方面是 Normalize CSS;而另一方面是 CSS Reset 可以避免冗长的 CSS 选择器链条。

编写你自己的 CSS Reset

在我这 13 年的工作生涯里,对于一些频繁的需要重置样式的 HTML 标签,比如:链接的颜色、按钮的默认样式和列表的默认样式等等,我颇有见解。

除了使用 normalize.css 之外,我还编写了自己的样式覆盖文件——reset.local.css。与传统的 CSS Reset 不同的是:我在其中只重置了一小部分 HTML 标签的样式,而不是全部的。

下面的例子教你怎么自定义 CSS Reset

我的 CSS Reset——reset.local.css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/****** Elad Shechter's RESET *******/
/*** box sizing border-box for all elements ***/
*,
*::before,
*::after{box-sizing:border-box;}
a{text-decoration:none; color:inherit; cursor:pointer;}
button{background-color:transparent; color:inherit; border-width:0; padding:0; cursor:pointer;}
figure{margin:0;}
input::-moz-focus-inner {border:0; padding:0; margin:0;}
ul, ol, dd{margin:0; padding:0; list-style:none;}
h1, h2, h3, h4, h5, h6{margin:0; font-size:inherit; font-weight:inherit;}
p{margin:0;}
cite {font-style:normal;}
fieldset{border-width:0; padding:0; margin:0;}

上面的样式看起来更加具有可读性。

基本布局

在我的项目中除了使用 normalize.csslocal.reset.css 之外,还有其它的基本布局文件。这个文件和 normalize CSSCSS reset没啥关系,是网站排版的基础样式,包含:directionfont-familyfont-sizeline-height、文字颜色等属性。

typography.css

1
2
3
4
5
6
7
8
9
10
html{
font-size: 1px;/*for using REM units*/
}
body{
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',sans-serif;
font-size: 16rem;
font-weight: 400;
line-height: 1.3;
color: #222;
}

结合使用

得益于 SASS 预处理器的强大功能,我创建了一个 _reset.scss 文件,包括三个部分:

_resets.scss 文件如下:

1
2
3
@import "resets/normalize.scss";
@import "resets/reset.local.scss";
@import "resets/typography.scss";

总结


本文主要向大家介绍了 Normalizing & Resetting 样式,同时这也是我的 CSS 系列文章的第一篇,接下来的几周,我将陆续撰写其它的相关文章。

如果你对这个专题感兴趣的话,欢迎订阅我的 twittermedium

我的 CSS 架构系列文章