大家好!Elad联系我,向我展示了他的新CSS重置项目,名为the-new-css-reset。它非常有趣!我认为与大家分享它的一个好方法不仅是指出它,而且还要问Elad一些关于它的问题,供大家阅读。
以下是重置的完整代码
/*** The new CSS Reset - version 1.2.0 (last updated 23.7.2021) ***/
/* Remove all the styles of the "User-Agent-Stylesheet", except for the 'display' property */
*:where(:not(iframe, canvas, img, svg, video):not(svg *)) {
all: unset;
display: revert;
}
/* Preferred box-sizing value */
*,
*::before,
*::after {
box-sizing: border-box;
}
/*
Remove list styles (bullets/numbers)
in case you use it with normalize.css
*/
ol, ul {
list-style: none;
}
/* For images to not be able to exceed their container */
img {
max-width: 100%;
}
/* Removes spacing between cells in tables */
table {
border-collapse: collapse;
}
/* Revert the 'white-space' property for textarea elements on Safari */
textarea {
white-space: revert;
}
Elad,我想很快了解一下代码部分,但首先,我想了解一下这个项目的“为什么”。CSS重置长期以来一直很流行,因为它们消除了不同浏览器默认样式之间存在的差异,然后你从那里构建你的样式。已经有一些广泛使用的重置了——为什么还要一个新的呢?
首先,当谈到“CSS重置”时,我们有两种方法
- Nicolas Gallagher的Normalize.css是一种温和的方法。Normalize.css修复了不同浏览器实现之间的差异。
- Eric Meyer的CSS Reset是一种强硬的方法,它认为在大多数情况下,我们不需要来自浏览器的基本样式,例如我们从像
<h1>
到<h6>
这样的元素获得的font-size
值,或者<ul>
和<ol>
列表元素的默认样式。例如,我们仅出于语义含义使用列表,因为它还有助于提高可访问性和SEO。
我非常喜欢Normalize.css。我认为它在任何项目中都是必不可少的,即使你更喜欢CSS Reset的想法。
为什么Normalize.css如此重要?Normalize.css会触及CSS Reset不会触及的Shadow DOM元素。当查看Normalize.css时,你会发现一些特殊的伪类,例如::-moz-focus-inner
、::-webkit-file-upload-button
等等。它涵盖了很多方面,这就是我相信Normalize.css在任何项目中都是必不可少的的原因。
我也喜欢强硬的CSS Reset。我认为在大多数情况下,我们不需要浏览器的基本样式,如果我们在特定位置需要它,我们会根据我们的需要定义它。这让我想到我同时使用Normalize.css和CSS Reset。因此,Normalize.css首先加载,然后是强硬的CSS Reset。
那么,为什么我们需要一个新的CSS重置呢?我们现有的CSS重置是基于旧的CSS功能构建的。但在过去的几年里,我们获得了专门用于重置CSS中内容的新功能,这让我开始思考,现在我们可以使用这些新的尖端CSS功能创建更有效的CSS重置。
all: unset;
。这是在这个CSS重置中承担重任的部分,对吧?它是如何工作的?
在我看来,这里最关键的部分是第一个规则集。让我们从第一个CSS属性和值开始:all
是最特殊的CSS属性,因为它允许我们一次性重置CSS中存在的所有属性。
该属性接受几个关键字。两个基本关键字是initial
和inherit
;还有两个更智能的关键字,分别是unset
和revert
。要了解all: unset
的作用,我们需要了解CSS属性的基本行为。
在CSS中,我们有两组属性
- **继承属性组:**这些属性默认具有继承性——主要是排版属性。
- **非继承属性组:**所有其他默认不继承的属性,例如包括
padding
、border
和margin
的盒子模型属性。
与排版属性一样,当我们尝试重置它们时,我们希望保持inherit
行为。因此,我们可以使用inherit
关键字值。
/* Will get values from the parent element value */
font-size: inherit;
line-height: inherit;
color: inherit;
对于非继承属性组中的其他属性,在大多数情况下,我们希望获得它们的初始值。值得一提的是,initial
关键字对不同属性的计算方式不同。
max-width: initial; /* = none */
width: initial; /* auto */
position: initial; /* = static */
在我们理解了基本知识以及inherit
和initial
关键字值之后,我们理解如果我们想一起重置所有属性,我们不能直接将它们与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元素执行一个操作时。
/*
Reset all:
- Inherited properties to inherit value
- Non-inherited properties to initial value
*/
* {
all: unset;
}
display: revert;
——all: unset;
是否对display
属性进行了不希望的操作?
然后你接着使用简短回答:是的。display
属性表示我们确实希望从用户代理样式表中获取的基本结构。正如我们在大多数属性中看到的那样,unset
值对我们来说做得很好,并且我们在一项操作中重置了所有属性。
现在,要了解revert
关键字值对display
属性的独特作用,让我们谈谈我们从浏览器获得的两种类型的样式。我们从浏览器获得的样式由两层构建
- **第1层,CSS
initial
值:**正如我们已经看到的,第一层是CSS中所有属性的initial
值,包括某些属性上的inherit
行为。 - **第2层,用户代理样式表:**这些是浏览器为特定HTML元素定义的样式。
在大多数情况下,当我们想要重置某些内容时,我们想要删除第2层的样式。当我们使用all: unset
重置时,我们删除了用户代理样式表的所有样式。
但是display
属性是特殊的。正如我们已经看到的,CSS中的每个属性只有一个初始值。这意味着如果我们将display
属性重置为其初始值,例如在<div>
元素或任何其他HTML元素上,它始终返回inline
值。
继续这种逻辑,我们将<div>
元素连接到默认的display: block
声明,这是我们从浏览器获得的。但是我们只有因为第2层,用户代理样式表,定义了它们,才获得这种行为。它基于与标题元素上的font-size
更大(从<h1>到<h6>)相同的理念,而不是任何其他HTML元素。
div {
display: unset; /* = inline */
}
span {
display: unset; /* = inline */
}
table {
display: unset; /* = inline */
}
/* or any other HTML element will get inline value */
当然,这是不希望的行为。display
属性是我们希望从浏览器获取的唯一例外。因此,我使用唯一的关键字值revert
来从用户代理样式表中恢复默认的display
值。
revert
值是唯一的。首先,它检查用户代理样式表中是否存在特定HTML元素上特定属性的默认样式,如果找到,则使用它。如果找不到,revert
的工作方式类似于unset
值,这意味着如果该属性默认是继承属性,则使用inherit
值;如果不是,则使用initial
值。

*
)选择页面上的所有内容,但随后删除了少量内容。对吗?为什么针对这些特定内容?
然后这两个规则位于一个规则集中,该规则集使用一个选择器来选择几乎所有内容。看起来你似乎正在通过通用标签选择器(当我开始构思“新CSS重置”时,我没想到会需要例外。在我的想象中,它要简单得多。
🤓 我想象中2022年的#CSS重置。
— Elad Shechter (@eladsc) 2021年2月2日
你怎么看?
关于CSS重置的更多信息,你可以阅读我之前关于“CSS是如何工作的?”的文章:https://#/r3ZFz4wl6j pic.twitter.com/kce8wbqmOB
但是当我开始创建体验时,我用我的新CSS重置(没有所有例外)替换了我的旧CSS重置,并且我看到一些破坏了我测试过的旧项目的东西。
主要出现问题的是可以通过 `width` 和 `height` 属性获取尺寸的元素——例如 `<iframe>`、`<canvas>`、`<img>`、`<svg>` 和 `<video>`。不幸的是,当我重置所有内容时,这些元素的宽度和高度由 `auto` 值定义,该值优先级更高,并会消除元素 `width` 和 `height` 属性的效果。
这可能是个问题,因为当我们通过 HTML 的 `width` 和 `height` 属性添加尺寸时,我们希望精确的尺寸来自 HTML 元素。我们更倾向于从 HTML 获取尺寸,而不是从 CSS 获取,因为当尺寸来自 CSS 时,在页面加载时可能会导致故障。
我发现的唯一能够去除所有这些特定元素重置效果的方法是将它们放在 `:not()` 选择器下。在这种情况下,我的新 CSS 重置是有害的,而不是有帮助的,因此我删除了对这些特定元素的影响。
在重置中,保持最低的特殊性似乎很重要,这样你就不会发现自己在与重置本身作斗争。这是 `:where()` 背后的理念吗?
是的,`:where()` 的理念是去除特殊性。我们不需要在 CSS 中描述更高的特殊性,仅仅是为了覆盖 CSS 重置。
总的来说,我认为我们很快就会看到更多使用 `:where()` 包裹元素以去除其特殊性的案例,而不仅仅是替换多个选择器。
看起来里面有一些对 `<svg>` 子元素的额外特殊处理。这是怎么回事?
第二个案例 `:not(svg *)` 使用单独的 `:not()` 是因为它是针对不同的问题。修改 SVG 内部元素可能会破坏视觉图像,而这是浏览器没有合理理由中断的事情之一。
让图像成为图像。我说。
在大型重置部分之后,它进入了一些更主观的片段。例如,浏览器之间对 `box-sizing` 的初始值没有分歧,但无论如何你都在更改它。我个人很喜欢这个,但我很好奇关于什么内容应该包含在重置中,什么内容不应该包含的理念。
总的来说,我认为 CSS 重置是一个见仁见智的事情。例如,Eric Meyer 的 CSS 重置选择删除特定事物的样式,而其他事物,例如 `display` 属性,则保持不变,正如你已经看到的,我完全同意这一点。
关于 `box-sizing`,是的,这是主观的。我做 Web 开发已经 15 年了。在这段时间里,我看到许多 Web 开发人员难以理解 `box-sizing` 的默认行为,而我过去已经习惯了。多年前,当人们谈论将其添加到 CSS 重置时,许多在行业工作多年的 Web 开发人员都害怕这种变化,因为总的来说,人们害怕改变。
但如今,我几乎看不到任何项目没有将所有元素重置为 `box-sizing: border-box` 的。浏览器的引擎无法修复默认 `box-sizing: content-box` 的笨拙行为,因为如果它们这样做,就会破坏对旧网站的支持。但是对于新项目,必须包含这部分内容,因为我们只能自己解决这个问题。
再说一次,这完全是主观的。
也会在 iOS 上删除列表的语义。对此有什么顾虑吗?
另外两个规则集,删除列表样式和折叠边框,也包含在 Eric Meyer 的重置中,因此它们已经存在很长时间了!从列表样式开始,我可以看到希望将它们清除,因为列表通常用于不需要标记的事情,例如导航。但在今天,这感觉有点有争议,因为 `list-style: none;`简短的回答:没有。我这边没有顾虑。原因如下。
如果我们选择不重置 `list-style`,则意味着我们无法将列表元素用于导航。这也意味着我们不会在任何其他浏览器中获得任何语义。
现在,如果我需要在大多数浏览器获得这些语义和没有浏览器获得这些语义之间做出选择,我将选择前者,因为获得这些语义的浏览器比失去它的浏览器更多。
你能看到自己随着时间的推移不断添加内容吗?比如,如果你发现自己一遍又一遍地在项目中做同样的事情?为图像设置 `max-width` 感觉就像这样。再说一次,这并不是浏览器现在存在分歧的东西,但几乎每个项目都会这样做。
当然可以。如果这个重置缺少我没有考虑到的东西,我会添加它并发布新版本。但它需要像你提到的 `max-width` 的例子一样,没有很好的理由让我们希望图像溢出其容器。
层叠层 功能吗?你认为它将来会如何影响 CSS 重置?
你见过这个新的在你问我之前,我还没有想过这个问题。层叠层模块是一个令人兴奋的功能。它还没有任何支持,但大多数浏览器引擎已经将此功能置于一个标志之下,这意味着我们很有可能在一年后看到此功能在所有常青浏览器中得到支持。
对于那些还没有听说过层叠层的人来说,其理念是 `@layer` 可以覆盖样式而无需创建更强的特殊性,因为每个加载在其之后的层都自动比之前的层更强。
当此功能到来时,我们将首先加载“重置”层。例如:首先是 Normalize.css,然后是 the-new-css-reset,然后是项目的 `@layer` 样式。
@layer normalize; /* Create 1st layer named “normalize” */
@layer the-new-css-reset; /* Create 2nd layer named “the-new-css-reset” */
@layer project-styles; /* Create 3rd layer named “project-styles” */
这应该确保底层始终胜过顶层。这也意味着像我所做的那样使用 `:where()` 去除特殊性将不再必要。
`@layer` 是即将出现在 CSS 中的最令人兴奋的未来功能之一,感谢 Miriam Suzanne,她一如既往地出色地完成了工作。
当我点击链接时我持怀疑态度,但我很高兴我这么做了。我想我会在即将到来的项目中尝试一下。
纯金。这不仅是一个很棒的重置选项,我终于理解了重置的价值。谢谢!
哇,我认为我从这篇单篇文章中学到的 CSS 知识比我过去几年学到的都多。谢谢!✌️
这太棒了!
自从 Eric Meyer 的重置样式发布以来,我一直在使用它,最近也开始使用 Andy Bell 的重置样式。
我喜欢 Elad 乐于为了其他(更好)浏览器更优雅地处理缺失的项目符号而“移除” iOS Safari 中列表语义的做法。;)
感谢您提供的这篇信息丰富的访谈。我以前总是混淆
unset
和revert
的效果。通过访谈中提供的示例,尤其是图表,现在我明白了。另外,感谢您提供的信息,
list-style: none;
会抹去列表的语义,这一点我之前不知道。所以我尝试了一种不同的隐藏列表标记的方法,使用::marker { color: transparent; }
,看起来这种方法有效。也就是说,我不确定这种方法是否也会对可访问性造成不利影响。任何建议都将不胜感激。经过更多测试,我发现还需要
font-size: 0
,否则标记仍然会占用空间。Ian,你可以看看 Andy Bell 是如何处理这个问题的。他明确地针对设置了
role="list"
属性的列表。/* 移除具有列表角色的 ul、ol 元素上的列表样式,这表示默认样式将被移除 */
ul[role='list'],
ol[role='list'] {
list-style: none;
}
参见 https://piccalil.li/blog/a-modern-css-reset/
我曾经在 Stack Overflow 上 记录了一个关于 css
all
属性的问题 - 特别是在 iOS 上以及它如何影响颜色。我目前手边没有 iOS 设备来检查这个问题,但我想知道这是否仍然是一个问题,如果是,它是否会在新的 css 重置代码中表现出来。
这太棒了。尽管会增加更多内容,但我认为需要在顶部声明中添加
outline: revert
。令人不安的 unset。
我尝试了这个重置,然后“砰”的一声,我的 input[type=”raio”] 由于以下原因消失了
是的,Jame,这是主要思想的一部分,即使对于单选按钮和复选框按钮,也要设计您自己的样式。
例如,您可以设计复选框
如果您不想对它们进行重置,则可以将 input 元素恢复,例如
我必须承认,我从未想过像使用普通的 css 属性一样使用
all
。我使用
all
的唯一情况是在过渡中(即使在那里,我也很少使用它)。这篇文章彻底改变了我对这个属性的看法。我肯定会在我的下一个项目中使用这个重置样式表以及 Heydon Pickering 的 Lobotomized Owl 选择器 :D
玩了一下,发现它会破坏标准的
<pre>
white-space
格式,需要额外的revert
。或者
(
white-space: pre
代码: https://webmasters.stackexchange.com/a/16597)友情提示,
与什么都不存在的情况并不相同。我正在制作一个字体演示,其中包含应用于文本中散布的
<span>
的功能。第一个规则弄乱了一些这些跨度的连字符和位置(请参见图像的最后一行)。第二个规则没有解决这个问题,并且我无法调试此问题,因为该问题仅出现在 Chrome 中,Chrome 不再允许显示 UA 样式。看来 Markdown 的支持并不全面 :) 这是图片链接
嗨,Adam,
请使用 CodePen 提供出现问题的具体代码。这样,就能更容易地看到问题并修改代码,以了解是否存在问题。如果存在问题,则需要找到解决方法 :-)。
这是一个
all: revert
不按预期工作的示例: https://codepen.io/hyvyys/pen/GRMbbev至少在 Chrome 中,
contenteditable
div 无法编辑。在 Firefox 中,它可以编辑,但没有光标可见。嗨,Adam,
如果您对每个 DIV 都使用 all:revert;,那么您就是在重置我的 CSS 重置样式。
如果您添加 all:revert; 而不使用我的 CSS 重置样式,则 contenteditable 将无法工作。
contenteditable 的特定修复方法是将其恢复,如 CSS 重置样式中所示
/* Chromium 浏览器中的错误恢复
– 修复内容可编辑属性,使其正常工作。 */
:where([contenteditable]){
-moz-user-modify: read-write;
-webkit-user-modify: read-write;
overflow-wrap: break-word;
-webkit-line-break: after-white-space;
}
哦,对了,它不在我复制的原始版本中(也不在本文中)。
这是我原始问题的复现:https://codepen.io/hyvyys/pen/poWMgMj。Chrome 中的连字符错误。
我想知道你是如何解决这些问题的!由于 DevTools 不会列出
all
覆盖的所有属性(并且不会在“计算”选项卡中列出所有供应商前缀属性),你是使用所有属性的索引并逐个检查它们,还是真的像天才一样? :)谢谢!
那么
margin:0
padding: 0
在这里
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
?
all:unset
已经从所有其他元素中删除了 padding 和 margin。我认为这是一种有趣的方法,但它仍然让我想知道为什么我要这样做,而不是仅仅使用 Normalize 或 Sanitize。(后者实际上将 Normalize 作为其一部分)。
我理解硬重置的目的。但我只是想知道在现代浏览器中这是否真的必要,以及为什么 Normalize 或 Sanitize 这些更具主见的方法不是更好。
我觉得这是一个值得一问的问题,但这里并没有真正问到。我确实看到了 Elad 对他如何更喜欢硬重置和柔和重置的描述。但尚不清楚,如果要使用柔和重置方法,为什么硬重置方法是真正必要的。
我认为这部分是我的自然倾向,并非总是合理,即避免对所有内容进行“全部”或“从不”样式的毯子式更改。
Elad 说:“我们现有的 CSS 重置样式是建立在旧的 CSS 功能基础上的。但在过去几年中,我们获得了专门用于重置 CSS 中事物的全新功能……”
这意味着 CSS 维护人员认为重置样式是必要的,因为我们获得了专门用于重置事物的全新功能。但为什么这么多人对是否使用重置样式存在分歧呢?
尽管如此,我同意如果目标是对所有内容进行硬重置,这绝对是最简洁的方法。
最后一点,如果我将 Normalize 或 Sanitize 与这种方法一起使用,则我不清楚为什么我要将它们放在硬重置之前。似乎硬重置随后会删除 Normalize/Sanitize 设置的任何内容,而不仅仅是与 Shadow DOM 相关的。
在文章中,Elad 陈述
“第二种情况,:not(svg *) 是单独使用 :not() 完成的,因为它是针对不同的问题。触摸 SVG 的内部元素可能会破坏视觉图像,而这是浏览器没有合理原因中断的事情之一。”
我完全不清楚这意味着什么。此外,在实际的 GitHub 文件中,后半部分写为
:not(svg *, symbol *))
并且注释中提到“symbol *”部分是为了解决“Firefox SVG 精灵错误”。但很难确定所指的错误究竟是什么。在查找相关信息时,看起来 Firefox 一直存在 SVG 精灵问题。
我觉得重置样式甚至 Normalize 类型的代码应该引用特定的错误号,或者至少提供一些参考,说明包含该代码是为了解决什么问题。我之所以这样说,是因为我觉得各种重置样式中的很多内容都是基于信任的,然后传播很长时间。
我并不是说这里也是这种情况。我只是没有办法知道。例如,我看到很多来源引用了这个重置样式,但他们似乎都不完全知道为什么其中包含了那部分代码。