如何写 CSS 重置(RESET)样式?
很长一段时间,我都使用Eric Meyer著名的CSS Reset。这是CSS的一个坚实的块,但是在这一点上它有点长。它已经十多年没有更新了,从那时起发生了很多变化!
最近,我一直在使用我自己的自定义CSS重置。它包括我发现的所有小技巧,以改善用户体验和CSS创作体验。
像其他CSS重置一样,在设计/化妆品方面,它是不赞成的。您可以将此重置用于任何项目,无论您想要哪种美学。
在本教程中,我们将介绍我的自定义 CSS 重置。我们将深入研究每个规则,您将了解它的作用以及您可能想要使用它的原因!
CSS 重置
事不宜迟,这里是:
/*
1. Use a more-intuitive box-sizing model.
*/
*, *::before, *::after {
box-sizing: border-box;
}
/*
2. Remove default margin
*/
* {
margin: 0;
}
/*
3. Allow percentage-based heights in the application
*/
html, body {
height: 100%;
}
/*
Typographic tweaks!
4. Add accessible line-height
5. Improve text rendering
*/
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
/*
6. Improve media defaults
*/
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
/*
7. Remove built-in form typography styles
*/
input, button, textarea, select {
font: inherit;
}
/*
8. Avoid text overflows
*/
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
/*
9. Create a root stacking context
*/
#root, #__next {
isolation: isolate;
}
它相对较短,但是这个小样式表中包含了很多东西。让我们开始吧!
从历史上看,CSS重置的主要目标是确保浏览器之间的一致性,并撤消所有默认样式,从而创建一个空白的石板。我的CSS重置并没有真正做这些事情。
如今,浏览器在布局或间距方面没有巨大的差异。总的来说,浏览器忠实地实现了CSS规范,并且事情的行为符合您的预期。因此,它不再是必要的了。
我也不认为有必要剥离所有浏览器默认值。例如,我可能确实想要设置标签!我总是可以在各个项目风格中做出不同的设计决策,但我认为剥离常识性默认值是没有意义的。
<em>``font-style: italic
我的CSS重置可能不符合"CSS重置"的经典定义,但我正在采取这种创造性的自由。
CSS盒子模型
测验!通过可见的粉红色边框进行测量,假设未应用其他 CSS,则在以下方案中元素的宽度是多少?.box
<style>
.parent {
width: 200px;
}
.box {
width: 100%;
border: 2px solid hotpink;
padding: 20px;
}
</style>
<div>
<div></div>
</div>
我们的元素有.因为它的父级是200px宽,所以100%将解析为200px。.box``width: 100%
但是它在哪里应用200px宽度? 默认情况下,它会将该大小应用于内容框。
如果您不熟悉,"内容框"是框模型中实际保存内容的矩形,位于边框和填充内:
该声明会将 的内容框设置为 200px。填充将添加额外的40px(每侧20px)。边框添加最后一个 4px(每侧 2px)。当我们进行数学计算时,可见的粉红色矩形将是244px宽。width: 100%``.box
当我们尝试将一个 244px 的框塞入一个 200px 宽的父级中时,它会溢出:
这种行为很奇怪,对吧?幸运的是,我们可以通过设置以下规则来更改它:
*, *::before, *::after {
box-sizing: border-box;
}
应用此规则后,百分比将基于边框进行解析。在上面的示例中,我们的粉红色框将为 200px,内部内容框将缩小到 156px(200px - 40px - 4px)。
在我看来,这是一个必须的规则。 它使CSS更适合使用。
我们使用通配符选择器 () 将其应用于所有元素和伪元素。与普遍的看法相反,这对性能来说并不坏。*
我在网上看到了一些建议,可以代替这样做:
html {
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
删除默认间距
* {
margin: 0;
}
浏览器围绕保证金做出常识性的假设。例如,默认情况下,将包含比段落更多的边距。h1
这些假设在文字处理文档的上下文中是合理的,但对于现代 Web 应用程序而言,它们可能不准确。
Margin是一个棘手的魔鬼,而且我经常发现自己希望元素默认情况下没有任何元素。所以我决定全部删除它。🔥
如果/当我确实想为特定标签添加一些边距时,我可以在我的自定义项目样式中执行此操作。通配符选择器 () 具有极低的特异性,因此很容易覆盖此规则。*
基于百分比的高度
html, body {
height: 100%;
}
你有没有试过在CSS中使用基于百分比的高度,却发现它似乎没有效果?
下面是一个示例:
元素有,但元素根本不会增长!main``height: 100%
这不起作用,因为在 Flow 布局(CSS 中的主要布局模式)中,并且操作的原则根本不同。元素的宽度是根据其父级计算的,但元素的高度是根据其子元素计算的。height``width
这是一个复杂的主题,远远超出了本文的范围。我计划写一篇关于它的博客文章,但与此同时,你可以在我的CSS课程中了解它,CSS for JavaScript Developers。
作为一个快速演示,在这里我们看到,当我们应用此规则时,我们的元素可以增长:main
如果你使用的是像 React 这样的 JS 框架,你可能还希望向这个规则添加第三个选择器:框架使用的根级元素。
例如,在我的 Next.js 项目中,我按如下方式更新规则:
html, body, #__next {
height: 100%;
}
为什么不使用vh?
您可能想知道:为什么要在基于百分比的高度上大惊小怪?为什么不改用该装置呢?
vh
问题是该单元在移动设备上无法正常工作; 将占用超过100%的屏幕空间,因为移动浏览器在浏览器UI来来去去的地方做那件事。
vh``100vh
将来,新的CSS单元将解决这个问题。在此之前,我继续使用基于百分比的高度。
调整行高
body {
line-height: 1.5;
}
line-height
控制段落中每行文本之间的垂直间距。默认值因浏览器而异,但往往在 1.2 左右。
此无单位数字是基于字体大小的比率。它的功能就像设备一样。如果为 1.2,则每行将比元素的字体大小大 20%。em``line-height
问题是:对于那些有阅读障碍的人来说,这些行挤得太紧,使得阅读起来更加困难。WCAG标准规定行高应至少为1.5。
现在,这个数字确实倾向于在标题和其他具有大类型的元素上产生相当大的行:
您可能希望在标题上覆盖此值。我的理解是,WCAG标准适用于"正文"文本,而不是标题。
使用"计算"实现更智能的线高
我一直在尝试一种管理行高的替代方法。在这里:
* {
line-height: calc(1em + 0.5rem);
}这是一个非常高级的小片段,它超出了这篇博客文章的范围,但这里有一个快速的解释。
字体平滑,抗锯齿
body {
-webkit-font-smoothing: antialiased;
}
好吧,所以这个有点争议。
在 MacOS 电脑上,浏览器将默认使用"子像素抗锯齿"。这是一种旨在通过利用每个像素内的 R/G/B 灯使文本更易于阅读的技术。
过去,这被视为可访问性的胜利,因为它提高了文本对比度。您可能已经读过一篇流行的博客文章停止"修复"字体平滑,该帖子主张反对切换到"抗锯齿"。
问题是:那篇文章写于2012年,在高DPI"视网膜"显示时代之前。今天的像素要小得多,肉眼看不见。
像素 LED 的物理排列也发生了变化。如果你在显微镜下看一台现代显示器,你不会再看到R/G/B线的有序网格了。
在2018年发布的MacOS Mojave中 ,Apple在整个操作系统中禁用了子像素抗锯齿。我猜他们意识到它在现代硬件上弊大于利。
令人困惑的是,像Chrome和Safari这样的MacOS浏览器仍然默认使用子像素抗锯齿。我们需要通过设置为 来显式关闭它。-webkit-font-smoothing``antialiased
区别如下:
MacOS 是唯一使用子像素抗锯齿的操作系统,因此此规则对 Windows、Linux 或移动设备没有影响。如果您使用的是 MacOS 电脑,则可以尝试实时渲染:
合理的媒体默认值
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
所以这里有一件奇怪的事情:图像被认为是"内联"元素。这意味着它们应该在段落的中间使用,例如 或 。<em>``<strong>
这与我大多数时候使用图像的方式不符。通常,我对待图像的方式与处理段落或标题或侧边栏的方式相同;它们是布局元素。
但是,如果我们尝试在布局中使用内联元素,则会发生奇怪的事情。如果您曾经有过一个神秘的4px间隙,不是边距,填充或边框,那么它可能是浏览器添加的"内联魔术空间"。line-height
通过默认设置所有图像,我们回避了整个类别的时髦问题。display: block
我也设置了.这样做是为了防止大图像溢出,如果它们放置在不够宽而无法容纳它们的容器中。max-width: 100%
大多数块级元素会自动增大/缩小以适应其父元素,但媒体元素是特殊的:它们被称为替换元素,并且它们不遵循相同的规则。<img>
如果图像的"本机"大小为 800×600,则该元素的宽度也将为 800px,即使我们将其放入 500px 宽的父级中也是如此。<img>
此规则将防止该图像超出其容器,这对我来说更像是更明智的默认行为。
继承窗体控件的字体
input, button, textarea, select {
font: inherit;
}
如果我们想避免这种自动缩放行为,输入的字体大小需要至少为1rem / 16px。以下是解决此问题的一种方法:
CSS
input, button, textarea, select {
font-size: 1rem;
}
这解决了自动变焦问题,但它是创可贴。让我们解决根本原因:表单输入不应该有自己的印刷风格!
CSS
input, button, textarea, select {
font: inherit;
}
font
是一种很少使用的速记,它设置了一堆与字体相关的属性,如 、 和 。通过将其设置为 ,我们指示这些元素与其周围环境中的排版相匹配。font-size``font-weight``font-family``inherit
只要我们不为正文文本选择令人讨厌的小字体大小,就可以同时解决我们所有的问题。🎉
自动换行
CSS
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
在 CSS 中,如果没有足够的空间来容纳一行上的所有字符,文本将自动换行。
默认情况下,该算法将寻找"软包装"机会;这些是算法可以拆分的字符。在英语中,唯一的软包装机会是空格和连字符,但这因语言而异。
如果某行没有任何软换行机会,并且它不合适,则会导致文本溢出:
这可能会导致一些令人讨厌的布局问题。在这里,它添加了一个水平滚动条。在其他情况下,它可能会导致文本与其他元素重叠,或滑到图像/视频后面。
该属性允许我们调整换行算法,并允许它在找不到软换行机会时使用硬换行:overflow-wrap
这两种解决方案都不完美,但至少硬包装不会弄乱布局!
感谢Sophie Alpert提出类似的规则!她建议将其应用于所有元素,这可能是一个好主意,但不是我个人测试过的东西。
您也可以尝试添加属性:hyphens
p {
overflow-wrap: break-word;
hyphens: auto;
}
hyphens: auto
使用连字符(在支持连字符的语言中)来指示硬换行。这也使得硬包装更加普遍。
如果您有非常窄的文本列,这可能是值得的,但它也可能有点分散注意力。我选择不将其包含在重置中,但值得尝试!
根堆叠上下文
#root, #__next {
isolation: isolate;
}
最后一个是可选的。通常只有当你使用像 React 这样的 JS 框架时才需要它。
正如我们在"到底是什么,z-index??"中看到的那样,该属性允许我们创建新的堆叠上下文,而无需设置 .isolation``z-index
这是有益的,因为它允许我们保证某些高优先级元素(模式,下拉列表,工具提示)将始终显示在应用程序中的其他元素之上。没有奇怪的堆叠上下文错误,没有z指数军备竞赛。
您应该调整选择器以匹配您的框架。我们希望选择在其中呈现应用程序的顶级元素。例如,create-react-app 使用 一个 ,因此正确的选择器是 。<div id="root">``#root
最终成品
下面再次以精简的复制友好格式进行 CSS 重置:
/*
Josh's Custom CSS Reset
https://www.joshwcomeau.com/css/custom-css-reset/
*/
*, *::before, *::after {
box-sizing: border-box;
}
* {
margin: 0;
}
html, body {
height: 100%;
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
#root, #__next {
isolation: isolate;
}
```
```
/*
Josh's Custom CSS Reset
https://www.joshwcomeau.com/css/custom-css-reset/
*/
*, *::before, *::after {
box-sizing: border-box;
}
* {
margin: 0;
}
html, body {
height: 100%;
}
body {
line-height: 1.5;
-webkit-font-smoothing: antialiased;
}
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
input, button, textarea, select {
font: inherit;
}
p, h1, h2, h3, h4, h5, h6 {
overflow-wrap: break-word;
}
#root, #__next {
isolation: isolate;
}
```
`
作者:非优秀程序员
链接:https://juejin.cn/post/7034308682825351176