嘿,伙计们!向我展示了他的新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重置是硬性的方法,他说在大多数情况下,我们不需要浏览器的基本样式,比如我们从
<h1>到<h6>等元素得到的font-size值,或者<ul>和<ol>列表元素的默认样式。例如,我们使用列表只是为了语义,还因为它在其他方面对可访问性和SEO有帮助。
我喜欢Normalize.css。我认为它是任何项目中的必备品,即使你更喜欢CSS重置的想法。
为什么Normalize.css如此重要?Normalize.css触及到了DOM元素的阴影,而CSS Reset却没有。在查看Normalize.css时,你会发现一些特殊的伪类,如::-moz-focus-inner 、::-webkit-file-upload-button ,以及更多。它涵盖了许多基础,这就是为什么我相信Normalize.css是任何项目中的一个必备工具。
我也喜欢硬性的CSS重置。我认为在大多数情况下,我们不需要浏览器的基本样式,如果我们在特定的地方需要它,我们会根据我们的需要来定义它。这让我想到,我把Normalize.css和CSS Reset结合使用。所以,Normalize.css是首先加载的,其次是硬性的CSS Reset。
那么,为什么我们需要一个新的CSS重置?我们现有的CSS重置是建立在旧的CSS功能之上的。但在过去几年中,我们得到了专门为在CSS中重置东西而构建的新功能,这让我想到,现在我们可以使用这些新的前沿CSS功能来创建一个更有效的CSS重置。
在我看来,这里最重要的一点是第一个规则集。让我们从第一个CSS属性和值开始:all: unset; 。这就是在这个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 属性的作用,让我们谈谈我们从浏览器中得到的两种类型的样式。我们从浏览器得到的样式是由两层组成的:
- 第一层,CSS
initial值:正如我们已经看到的,第一层是我们在CSS中所有属性的initial值,包括一些属性上的inherit行为。 - 第二层,用户代理样式表:这些是浏览器为特定的HTML元素定义的样式。
在大多数情况下,当我们想重置东西时,我们要删除第2层的基本样式。而当我们用all: unset 进行重置时,我们会删除用户代理样式表的所有样式。
但是,display 这个属性是例外的。正如我们已经看到的,CSS中的每个属性都只有一个初始值。这意味着,如果我们将display 属性重置为初始值,比如在<div> 元素或其他HTML元素上,它总是返回inline 值。
继续这个逻辑,我们将<div> 元素连接到默认的display: block 声明,我们从浏览器中得到了这个声明。但我们之所以得到这种行为,只是因为第2层,即用户代理样式表,它定义了它们。它建立在同样的想法上,即font-size 在标题元素,
到
上比其他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重置关键字的图示
然后,这两条规则是在一个带有选择器的规则集中,你几乎选择了所有的东西。看起来你是通过通用标签选择器(* )选择了页面上的所有东西,但又删除了一小部分东西。是这样吗?为什么要针对那些特定的东西?
但是,当我开始创造经验时,我用我的新CSS重置(没有所有的例外)来替换我的旧CSS重置,我看到了一些破坏我的旧项目的东西,我对此进行了测试。
破坏的主要是那些可以通过width 和height 属性获得大小的元素--像<iframe>,<canvas>,<img>,<svg>, 和<video> 。不幸的是,当我重置一切时,这些元素的宽度和高度是由auto 的值定义的,这更强大,并消除了元素的width 和height 属性的影响。
这可能是个问题,因为在我们通过HTML宽度和高度属性添加尺寸的情况下,我们希望准确的尺寸来自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 ,是的,这是有意见的。我做了15年的网络开发者。在这段时间里,我看到许多网络开发者在努力理解box-sizing 的默认行为,而我在过去已经习惯了这种行为。许多年前,当人们在讨论将其加入到CSS重置中时,网络开发者,其中许多人已经在这个行业工作了很长时间,都害怕这种变化,因为,一般来说,人们都害怕变化。
但这些天,我几乎没有看到任何项目不是将所有元素重置为box-sizing: border-box 。浏览器的引擎不能修复默认的尴尬行为box-sizing: content-box ,因为如果他们这样做,就会破坏对旧网站的支持。但是对于较新的项目,包括这一块是必须的,因为我们只能靠自己来解决。
再说一遍,这完全是意见的问题。
另外两个规则集,即删除列表样式和折叠边框,也在Eric Meyer的重置中,所以它们已经存在了很长时间了从列表样式开始,我可以看到想要消除这些,因为列表经常被用于不需要标记的东西,比如导航。但现在感觉有点争议了,因为list-style: none; 抹去了列表的语义,在iOS上也是如此。有什么担忧吗?
简短的回答:没有。我不担心。这就是原因。
如果我们选择不重置list-style ,这意味着我们不能使用列表元素进行导航。这也意味着我们不会为任何其他浏览器获得任何语义。
而现在,如果我需要在大多数浏览器获得这些语义和没有浏览器获得这些语义之间做出选择,我会选择前者,因为更多的浏览器从中获益,而不是它们的损失。
你能看到自己随着时间的推移而增加这些内容吗?比如你发现自己在项目中反复做同样的事情?在图片上设置max-width ,对我来说就是这样。同样,这不是浏览器现在不同意的事情,但也是几乎每个项目都会做的事情。
当然了。如果这个重置缺少一些我没有考虑到的东西,我会添加它并发布一个新的版本。但它需要像你的例子max-width ,在那里没有好的情况下,我们希望一个图像溢出它的容器。
你看到这个新的级联层的东西了吗?有没有想过这可能会影响到以后的CSS重置?
在你问我之前,我并没有想过这个问题。Cascade Layers模块是一个令人兴奋的功能。它仍然没有任何支持,但大多数浏览器引擎已经把这个功能放在一个标志下,这意味着我们很有可能在一年后看到这个功能被所有常青浏览器所支持。
对于那些还没有听说过级联层的人来说,其想法是:@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,她一如既往地做着出色的工作。