这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战
- 原文地址:An Interview With Elad Shechter on “The New CSS Reset”
- 原文作者:Elad Shechter
- 译文出自:掘金翻译计划
对Elad Shechter有关CSS重置的访谈
大家好!Elad和我沟通,并向我展示了他的被称为[新CSS重置]的项目。这真的很有意思,我认为不仅可以通过介绍来与你分享它,也可以问Elad一些关于它的问题,让你们读起来更感兴趣。 下面是前端样式重置的所有源码:
/*** 新的CSS重置 - 版本号 1.2.0 (最近更新于 23.7.2021) ***/
/* 除了`display`属性,删除所有浏览器的默认样式 */
*:where(:not(iframe, canvas, img, svg, video):not(svg *)) {
all: unset;
display: revert;
}
/* 首选盒模型中的值 */
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
删除列表样式 (小圆点/序号)
防止和normalize.css同时使用了这个样式
*/
ol, ul {
list-style: none;
}
/* 使图片不会超出划分的范围 */
img {
max-width: 100%;
}
/* 删除表中单元格间的间距 */
table {
border-collapse: collapse;
}
/* 在浏览器上恢复多行文本输入控件的`white-space`属性 */
textarea {
white-space: revert;
}
嘿, Elad!我想快速了解一下源码,但是首先,我很想听听这个项目开发的原因。CSS重置一直以来都很流行,因为它们能够消除不同浏览器之间因为默认样式而造成的差异,然后你可以自己重新编写样式。有一些重置样式的方式已经在广泛应用了,为什么还要开发一套新的呢?
首先,当谈论到CSS重置问题时,我们通常会想到两种方法:
- Nicolas Gallagher的CSS重置方法是最常用的. Normalize.css消除了在不同浏览器之间实现的差异。
- Eric Meyer是原生CSS重置,因为在大多数情况下,我们并不想要浏览器的基本样式, 像
font-size的值是元素<h1>到<h6>, 或<ul>和<ol>列表元素的默认样式。打个比方,因为列表元素在某方面有助于可访问性和搜索引擎优化,因此我们只是想将列表元素用于语义表达。
我很喜欢使用Normalize.css. 在任何一个项目中我认为它都是必须的,哪怕你更喜欢CSS 重置的方法。
为什么Normalize.css这么重要呢?Normalize.css涉及到了CSS 重置中没有的Shadow DOM元素。查看Normalize.css源码时,你会发现一些特殊的伪类,像::-moz-focus-inner, ::-webkit-file-upload-button等。它涵盖了这么多基础元素,因此我认为在任何一个项目中Normalize.css都是必不可少的。
我也喜欢原生CSS重置的方法.在大多数情况下,我们并不想要浏览器的默认样式,如果我们在一些特定的场景需要使用,可以按需定义。因此就让我有了将Normalize.css 和 CSS Reset组合起来的想法。 因此,首先Normalize.css加载,加载完成后会进行原生CSS重置.
那么,为什么我们需要一个新的CSS重置方法?我们拥有的CSS重置是建立在旧的CSS功能之上的。但是在最近几年,我们有了专门为重置CSS内容而构建的新功能。这让我想到,现在我们可以使用这些前沿CSS功能创建更多有效的CSS重置。
在我看来,这里最有趣的是第一个规则集。让我们从第一个CSS属性和值开始: all: unset;.这就是在这个CSS重置中做的事情吗? 具体是怎么生效的?
[all] 在CSS属性中最特殊,因为它能够让我们一次性重置CSS中存在的所有属性
这个属性可以接受几个关键字. 两个基本元素是initial 和 inherit; 两个更好用的元素是unset 和 revert. 为了理解all: unset是什么,我们需要去看CSS属性的基本行为。
在CSS中, 我们有两组属性:
- 继承属性组: 这些属性默认具有继承性,主要是字体属性。
- 非继承属性组: 这些都是默认情况下不会继承的其他属性, 例如, 盒模型属性,包括“内边距”、“边框”和“外边距”。
像字体属性, 当我们试图重置它们时,我们希望保持“继承”行为. 因此,这就是我们能够使用inherit关键字值的地方。
/* 将从父元素值获取值 */
font-size: inherit;
line-height: inherit;
color: inherit;
用于非继承属性组中的其他属性, 在大多数情况下,我们想要得到它们的初始值。值得一提的是,initial关键字对于不同的属性计算方法不同。
max-width: initial; /* = none */
width: initial; /* auto */
position: initial; /* = static */
在我们理解了基础原理以及“继承”和“初始”关键字值之后,我们要知道,如果想一起重置所有属性,不能直接使用all属性。这是因为,如果将所有属性重置成了“初始”值,即:all: initial,我们就失去了继承属性组的固有行为。假设我们用inherit值重置所有属性,所有的属性都得到一个继承 - 甚至是我们想要避免的盒模型属性。
这就是为什么我们需要unset值。unset根据属性的类型重置属性。如果我们在继承属性上使用它,它就相当于inherit;如果我们在非继承属性上使用它,它就相当于initial;
max-width: unset; /* = initial = none */
font-size: unset; /* = inherit = get parent element value */
这就把我们带回到了CSS重置的主要特性。all: unset所做的就是将所有继承属性重置为inherit,将所有非继承属性重置为initial。
这个操作就把所有浏览器自带的默认样式都移除了。为了理解CSS的这些重要的新功能,所有这些都发生在我对所有HTML元素只执行一个操作的时候。
/*
全部重置:
- 继承属性赋以继承值
- 非继承属性赋以初始值
*/
* {
all: unset;
}
接着你使用display: revert; —all: unset; 会对 display 属性造成不好的影响吗?
简明回答: 是的. ' display '属性表示我们确实想从浏览器默认样式表中得到的基本结构. 就像我们在大部分属性中所看到的那样, ' unset '值非常适合我们,我们在一个操作中重置了所有属性。
现在,为了了解唯一的revert关键字为display属性做了什么, 让我们来谈谈我们从浏览器中获得的两种样式。我们从浏览器获得的样式是由两个层构建的:
- 第1层, CSS的“初始”值: 正如我们所看到的,第一层是CSS中所有属性的“初始”值,包括一些属性的“继承”行为。
- 第2层, 浏览器默认样式表: 这些是浏览器为特定的HTML元素定义的样式。
大部分情况下, 当我们想要重新设置的时候, 我们想移除第2层的基本样式. 当我们用 all: unset重置时, 我们就删除了浏览器默认的所有样式.
但是display属性是例外的. 正如我们所看到的, 每个CSS属性只有一个初始值. 这就意味着如果我们把display属性重置为了它的初始值, 像<div>元素或者其他 HTML 元素, 它总是会返回内连值
继续这个逻辑, 我们为<div>元素赋予了从浏览器中得到的,默认的display: block声明。 但是我们之所以能得到这个属性和属性值是因为第2层,即浏览器默认样式,它定义了它们. 标题元素的“字体大小”更大就是建立在了相同的理念上, <h1> 到 <h6>, 而不是其他的HTML元素。
div {
display: unset; /* = inline */
}
span {
display: unset; /* = inline */
}
table {
display: unset; /* = inline */
}
/* 或者任何其他HTML元素将获得内联值 */
当然,这是不希望出现的结果。display是唯一一个我们想从浏览器中获得的属性. 因此,我们使用关键字revert从浏览器默认样式中恢复默认的display值。
revert值是唯一的. 首先, 它检查了它所在的特定HTML元素的浏览器默认样式中的特定属性中,是否含有默认样式, 如果有,就使用它。如果没有,revert的工作方式类似于unset值,这意味着如果该属性是默认继承的属性, 就使用inherit值;如果不是revert,就使用initial 值。
然后,这两个规则在一个规则集中,其中有一个选择器,您可以选择几乎所有内容。就像是通过通用标记选择器选择页面上的所有内容 (*), 但是当移除了一些内容. 可以这样吗?为什么要针对这些特定的内容?
当我开始思考新的CSS重置方法,我不认为我需要额外的东西. 我的想象中要简单得多。
但当我开始设计时, 我用新的CSS重置替换了旧的CSS重置 (没有任何例外), 我看到一些东西破坏了我用来测试的旧项目。
被破坏的主要原因是通过“宽度”和“高度”属性获取大小的元素— 像<iframe>, <canvas>, <img>, <svg>, and <video>元素. 不幸的是, 当我重置一切时,这些元素的宽度和高度由auto值定义了,它的优先级更高,并删除了元素的“宽度”和“高度”属性的影响。
这可能会有问题,因为在通过HTML宽度和高度属性添加维度的情况下,我们希望精确来自HTML元素的大小. 我们更想从HTML而不是CSS获取它,因为如果它来自CSS,在加载页面时可能会出问题。
我发现移除所有这些特定元素的重置效果的唯一方法是将它们放在:not() 选择器下. 在这种情况下,我新的CSS重置是有害的,而且没有帮助,因此,我删除了这些特定元素的效果。
在重置中保持最小的特异性似乎很重要,所以你不会发现自己在与重置本身做斗争. 这就是:where()背后的思想吗?
是的,:where()的想法就是消除特异性. 我们不需要在我们的 CSS 中描述更重要的特殊性,只是为了覆盖 CSS 重置就可以了。
通常而言,我认为我们很快就会看到更多类似:where() 包装内容来消除特异性的情况,而不仅仅是用多个选择器来替换它。
第二个例子, :not(svg *)是使用单独的:not()完成,因为它是针对不同的问题。涉及到SVG的内部元素可能会破坏可视图像,这是没有任何合理原因中断浏览器的情况之一。
我说,让图像就是图像吧。
大部分内容重置之后,就可以对一些固定部分做一些小的改动了。 例如,浏览器对“box-sizing”的初始值没有差异,但你还是要更改它. 我自己也很喜欢这样做,但我很好奇什么应该重置,什么不应该重置。
一般来说,当涉及到CSS重置时,我认为这是一个主观问题。例如, Eric Meyer的CSS重置选择删除特定事物的样式和像display这样的属性,正如你所看到的那样,是不间断的,我完全同意这样做。
关于box-sizing,是的,这是个主观想法. 我做了15年的 Web 开发。 在那段时间里,我看到许多web开发人员都在努力理解过去我所习惯的box-sizing的默认行为。许多年前,当人们讨论将它添加到CSS重置中时,web开发人员(其中许多人已经在这个行业工作了很长时间)害怕这种改变,因为一般来说,人们害怕改变。
但现在, 我几乎没有看到任何项目不把所有元素重置为box-sizing: border-box。浏览器引擎无法修复默认的box-sizing: content-box的尴尬行为,因为如果这样做,它们将中断对旧网站的支持。但是对于更新的项目,包括这一部分是必须的,因此我们要自己解决它。
再说一次,这完全是主观臆断。
另外两个规则集,删除列表样式和折叠边界,也在Eric Meyer的重置中,所以它们已经存在很长时间了! 从列表样式开始,我可以看到想要清除这些,因为列表通常用于不需要标记的事情,如导航。 但现在感觉有点争议, 就像列表中的 list-style: none; [消除语义],在iOS上也是如此. 有什么问题吗?
简明回答: 不。我认为不用担心。原因如下。
如果我们选择重置了list-style, 这意味着我们不能使用列表元素进行导航。 这也意味着我们不会得到任何其他浏览器的语义。
现在,如果我需要在大多数浏览器获得这些语义和没有浏览器获得这些语义之间做出选择, 我选择前者,因为从中获益的浏览器要多于损失的浏览器。
你能想象自己随着时间的推移而增加吗? 比如,如果你发现自己在项目中反复做同样的事情。 对我来说,设置图像的max-width就是这种感觉。 再次强调,这不是浏览器不同意的事情,而是几乎每个项目都需要做的事情。
当然。如果这次重置缺少了一些我没有考虑到的东西,我将添加它并发布一个新的版本. 但它需要像max-width一样,即我们不希望图像溢出其容器。
你看过这些新东西吗[级联层]? 任何关于如何影响CSS重置的想法?
直到你问我,我才想起来。 级联层模块是一个令人兴奋的功能。它仍然没有任何支持,但大多数浏览器引擎已经把这个特性放在了默认样式下,这意味着我们很有可能在一年后看到这个特性在所有的主流浏览器中得到支持。
给那些还没听说过层叠图层的人, 这个想法是,“@layer”可以覆盖样式而不创建更强的专一性,因为在它之后加载的每一层都会自动比之前的层更强。
当这个特性到来时,我们将首先加载重置层。 例如: 首先, Normalize.css, 然后是 the-new-css-reset, 然后是 项目中的@layer样式。
@layer normalize; /* 创建名为normalize的第一层 */
@layer the-new-css-reset; /* 创建名为“the-new-css-reset”的第二层 */
@layer project-styles; /* 创建名为“project-styles”的第三层 */
这将确保底层加载完成后样式能够覆盖顶层。 这也意味着不再需要像我那样使用':where() '删除特异性。
@layer 是CSS最令人兴奋的未来特性之一,感谢[Miriam Suzanne],她一如既往地做着出色的工作。