每当我开始一个新项目时,首要的任务就是处理 CSS 语言中的那些边边角角的问题。为了解决这些问题,通常会使用自定义的一组基础样式。
在过去很长一段时间,我使用的是来自 Eric Meyer 那份著名的 CSS Reset。作为一份古老且实用的 CSS 代码,在过去十多年里它从未被更新过,而这期间很多东西都已经发生了巨大的变化!
最近,我一直在使用我自己定义的 CSS 重置样式 (CSS Reset)。它包含了我总结的诸多小技巧,既可以改善用户体验又能提高 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 规范。所以,对样式一致性问题的处理已经不是那么重要了。
而且,我从不认为去掉浏览器所有的默认样式是必要的。例如,我会用 标签将字体样式设置为斜体!虽然在不同的项目中可能要遵守不同的设计规范,但我认为去除常识性的默认设置是毫无意义的。
我的这份 CSS 重置样式可能不符合 “CSS重置样式” 的经典定义,但从另外一个角度来说,这份 CSS 重置样式也拥有了更多的创造性。
在开始之前,先回答一个问题!在没有其他 CSS 样式的情况下,下面代码中的 .box
元素(粉红色边框的矩形区域)的宽度是多少?是 200px、240px、244px 还是 0px 呢?
<style>
.parent {
width: 200px;
}
.box {
width: 100%;
border: 2px solid hotpink;
padding: 20px;
}
</style>
<div class="parent">
<div class="box"></div>
</div>
在 .box
元素的样式中设置了 width: 100%
,由于它的父元素 .parent
的宽度是 200px,所以 这里的 100% 会被解析为 200px。
那么这 200px 的宽度会作用在哪里呢?默认情况下,浏览器会将这个宽度应用在内容框上 (content box)。正如我们所熟知的那样,这里所说的 “内容框” 是盒模型里的盒子实际包含的内容,它在 border 和 padding 内部:
width: 100%
将 .box
盒模型的 content 部分设置为 200px;内边距 padding 会额外增加 40px 宽度(每边各 20px);边框 border 会增加 4px(每边各 2px)。通过加法计算不难得出粉色边框矩形的宽度为 244px。因此,上面提到的问题的答案是 244px。
当我们试图将一个 244px 的盒子塞进一个 200px 宽的父容器时,它会发生溢出:
这种行为看起来很奇怪,我们可以通过以下设置来更改它:
*, *::before, *::after {
box-sizing: border-box;
}
应用此规则后,宽度的百分比将基于 border-box 进行解析。在上面的例子中,我们的粉色框是 200px,而内部的 content-box 将缩小到 156px (200px - 40px - 4px)。
在我看来,这是一条必不可少的样式的规则,因为它会使 CSS 更易于使用。我们用通配符选择器(*
)将其应用于所有元素和伪元素。与大众认知完全相左的是,这个样式设置并不会导致性能变坏,具体可参考文章* { Box-sizing: Border-box } FTW。
box-sizing 继承
我在网上看到了另外一种样式设置:
html { box-sizing: border-box; } *, *:before, *:after { box-sizing: inherit; }
如果您想在一个已存在的大型项目中迁移使用 border-box,那么这将是一个有用的策略。如果你从零开始一个全新的项目,这是没有必要的。为了简单起见,我在 CSS 重置样式中省略了它。
首先,我们可以创建一个 “legacy” 选择器,将 box-sizing 的值继续保留为
content-box
,这也是 box-sizing 属性的默认值:.legacy { box-sizing: content-box; }
然后,当应用程序中存在尚未迁移使用 border-box 时,我们就可以将该类添加到对应的位置,以保持原有样式不被影响:
<body> <header class="legacy"> <nav> <!-- Legacy stuff here --> </nav> </header> <main> <section> <!-- Modern stuff here --> </section> <aside class="legacy"> <!-- Legacy stuff here --> </aside> </main> </body>
为什么要这样做呢?现在,让我们思考一下这个代码段中的元素是如何计算的。
<header>
被赋予了legacy
,因此它使用了box-sizing: content-box
。其子元素
<nav>
的样式为box-sizing: inherit
。由于其父元>素设置为content-box
,nav
也将设置为content-box
。
<main>
标签没有legacy
,因此它从其父级<body>
继承;>而<body>
继承自<html>
;<html>
被设置为 >border-box
。从本质上讲,每个元素都可以从其父元素获得 box-sizing 属性。如果它有一个设置了
legacy
的祖先,那么它的属性值是content-box
。否则,它将最终从<html>
标签中继承,其属性值为border-box
。
* {
margin: 0;
}
浏览器会对外边距 (margin) 做出很多常识性假设。例如,h1
在默认情况下要比段落的边距更大。这些假设在那些做文字处理的文档中是合理的,但对于现代 web 应用程序来说可能并不准确。
另外,外边距会在你稍不留神的时候遭遇外边距塌陷的问题,它可真是一个令人讨厌的小机灵鬼呢。而且,我发现自己经常希望元素在默认情况下没有任何外边距。所以我决定把它全部去掉。
当我确实希望向特定的标签添加外边距时,我可以在项目中用自定义样式中来实现。通配符选择器(*
)的优先级极低,这条规则很容易被覆盖。
html, body {
height: 100%;
}
我们在 CSS 中经常会使用百分比来设置高度,很多时候却发现它似乎并没有效果。请看下面的示例:
虽然将 main
元素设置为 height: 100%
,但元素的高度根本没有变化!
这里不起作用的原因是,在 CSS 流式布局(CSS 中的主要布局模式)中,height
和 width
的工作原理完全不同。元素的宽度是基于父元素计算的,元素的高度是根据其子元素计算的。这个话题说起来比较复杂,远远超出了本文的范围,本文中不再展开讨论。
在下面的代码示例中,我们将上面的规则应用到代码中,会发现 main
元素的高度变为了 100%:
如果您使用的是像 React 这样的 JavaScript 框架,那么您可能还需要在此规则中添加第三个选择器:框架使用的根元素。
例如,在我的 Next.js 项目中,会将规则做如下更新:
html, body, #__next {
height: 100%;
}
为什么不使用 vh?
你可能会想:为什么非得使用百分比来设置高度呢?为什么不用
vh
替代呢?问题是
vh
不能在移动设备上正常工作;在移动设备上浏览器 UI 在上下滑动的时候,视口的可见部分会进行调整,这就导致100vh
在浏览器中是不固定的,可能会超过屏幕实际的使用面积。在未来,新的 CSS 单位将解决这个问题。在此之前,我继续使用基于百分比的高度。
body {
line-height: 1.5;
}
行高 line-height
控制段落中每行文本之间的垂直间距。它的默认值因浏览器而异,但通常在 1.2 左右。这个没有单位的数字是基于字体大小的比值。它的功能就像 em
一样。line-height
为 1.2 时,每行的行高将比元素的字体大 20%。
这里带来一个问题,对于那些有阅读障碍的人来说,这些句子排得太近,使阅读变得更困难。WCAG 标准规定,行高应至少为 1.5。
现在,1.5 这个数字影响标题和其他大字体元素,使它们产生了相当大的行:
您可能直观的想到,在标题上重新设置行高。我的理解是,WCAG 标准是针对 “body” 文本,而不是标题。
使用 “calc” 灵活的设置 line-heights
我一直在尝试着另一种设置行高的方法,如下所示:
* { line-height: calc(1em + 0.5rem); }
这是一个相当高级的代码片段,虽然它又超出了本文的范围,这里还是会简单做一下介绍。
这个方法并没有用字体的大小值乘以 1.5 这样的数字来计算行高,而是以字体大小作为基数,并为每行添加固定的空间。对于 body 里面的文字段落((paragraphs),每行都将解析为 24px(假设使用的是浏览器的默认字体大小)。
不过,在较大的文本上,此声明会产生更紧的行。下面的示例可以做出验证:
要注意的是,在使用这个设置时需谨慎,目前我还在试验中。
其中的一个缺点是,我们必须用
*
将其设置在所有元素上,而不是将其应用于body
。这是因为em
单位不能被子元素很好地继承;它不能使每个元素重新计>算1em
所对应的值。例如,在这个博客上,因为第三方代码假设行高是可继承的,导致我的代码被它破坏了。有关这项技术的更多信息,请查看 Kitty Giraudel 的这篇很棒的博文:使用 calc 计算最佳行高。
body {
-webkit-font-smoothing: antialiased;
}
这个 CSS 设置存在一点争议。
在 MacOS 计算机上,默认情况下浏览器会使用 “亚像素抗锯齿(subpixel antialiasing)”。这种技术可以利用每个像素内的 R/G/B 灯光使文本更易于阅读。
在过去,这个技术被认为提高了可访问性,因为它改善了文本对比度。你可能读过一篇流行的博文,停止 “修复” 字体平滑,这篇文章并不提倡切换到 “抗锯齿(antialiased)”。
问题是,这篇文章写于 2012 年,那时高 DPI “视网膜(retina)” 显示时代还未来临。今天的像素更小,肉眼根本看不见。LED 像素的物理布局也发生了变化。如果你在显微镜下观察现代显示器,你已经不会看到有序的 R/G/B 线网格了。
在 2018 年发布的 MacOS Mojave 中,苹果公司在操作系统中禁用了亚像素抗锯齿。我猜他们意识到,对现代硬件来说,这个技术的弊大于利。
令人困惑的是,像 Chrome 和 Safari 这样的 MacOS 浏览器,在默认情况下仍然使用亚像素抗锯齿。因此,我们需要将 -webkit-font-smoothing
设置为 antialiased
来显式关闭亚像素抗锯齿。
这两者的区别在于:
MacOS 是唯一使用亚像素抗锯齿的操作系统,因此这个 CSS 规则对 Windows、Linux 或移动设备没有影响。如果您使用的是 MacOS 计算机,则可以尝试运行一下下面的代码示例:
img, picture, video, canvas, svg {
display: block;
max-width: 100%;
}
在 CSS 中图像被认为是 “inline” 内联元素,也就意味着它们应该像<em>
或 ``那样在段落中间使用。这与我们经常使用图像的方式是不符的。通常,我们使用图片的方式与对待段落、标题或边栏的方式相同,这些都是布局元素。
但是,如果我们布局中试图使用内联元素,就会碰到奇奇怪怪的事情。比如内联元素的 4px 空白间距问题,这个神奇的空白与 line-height
有关系。通过在所有图像上设置 display:block
,我们避开了这一类问题。
我还设置了 max-width: 100%
,这样做是为了防止大型图像溢出,特别是它们被放在一个不够宽的容器中。
大多数块级元素将自动伸长/收缩以适应其父元素,但像 <img>
这样的媒体元素是特殊的:它们被称为替换元素,并且它们也不遵循相同的规则。
如果图像的 “自身的” 大小为 800 × 600,那么 <img>
元素的宽度也将为 800px,即使我们将其放入一个 500px 宽的父元素中。
这个规则将防止图像超出其容器,我认为这是一个比较明智的做法。
input, button, textarea, select {
font: inherit;
}
在默认情况下,按钮和输入框不会从它们的父项继承排版样式。相反,他们有自己怪异的风格。例如,<textarea>
将使用系统默认的 Monospace 字体。文本输入框将使用系统默认的 sans-serif 字体。两者都会选择 microscopically-small 字体大小(Chrome 为 13.333px)。
正如您所想象的,在移动设备上阅读 13px 的文本非常困难。当我们聚焦设置了较小字体的输入框时,浏览器会自动放大,这样文本更容易阅读。
不幸的是,这样的用户体验并不好:
如果要避免这种自动缩放行为,输入的字体大小必须至少为 1rem/16px。有一种方法可以解决这个问题:
input, button, textarea, select {
font-size: 1rem;
}
这修正了自动缩放问题,但这只是一个权宜之计。让我们从根本上来解决这个问题:表单输入不应该有自己的排版样式!
input, button, textarea, select {
font: inherit;
}
font
是一种 CSS 设置字体的简略写法,它设置了一系列与字体相关的属性,如 font-size
、font-weight
和 font-family
等。通过把它的值设置为 inherit
,可将这些元素与其周围环境中的排版一致。
只要我们没有在 body 中使用令人讨厌的较小的字体,这就一次解决了我们所有的问题。
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: aut
:自动使用连字符(在支持它们的语言中)表示硬换行。这也使得硬换行更为常见。如果你有非常窄的文本栏,可以使用一下它。在我个人的 CSS 重置样式中并wei包含它,但它值得尝试!
#root, #__next {
isolation: isolate;
}
最后一个是可选的。通常只有在使用 React 之类的 JavaScript 框架时才需要它。
正如我们在 滚蛋吧,z-index 中看到的那样,isolation
属性允许我们创建新的堆栈上下文,而无需设置 z-index
。
这是有益的,因为它允许我们保证某些高优先级元素(模态、下拉列表、工具提示)在应用程序中始终显示在其他元素之上。没有奇怪的堆叠背景错误,没有 层出不穷的 z-index。
为了匹配您使用的框架,您需要根据您的需要来调整选择器。我们希望选择在应用程序中呈现的顶级元素。例如,在 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;
}
请随意复制/粘贴到您自己的项目中!它的发布没有任何限制(不过如果你想保留这篇博文的链接,我将不胜感激!)。
我没有将这个 CSS 重置样式作为 NPM 包发布,因为我觉得你应该拥有自己的重置样式。把它带到你的项目中,随着时间的推移,当你学习新事物或发现新技巧时,可以对它进行调整。如果需要,您可以随时制作自己的 NPM 包,以便于在项目中重用。请记住:代码恒久远,一段永流传;您拥有的有这段代码,它应该与您一起成长。
感谢 Andy Bell 分享他的现代 CSS 样式重置。它激发了我的一些灵感,并启发了这篇博文!
我的 CSS 重置样式很短(只有 11 条声明!),但我还是花了整整一篇博文来谈论它们。老实说,我还有很多话要说!因为这里,我们对某些知识点只简单的提及,并未深入展开。
CSS 看似复杂,其实不然。只有你打破砂锅问到底,才能了解里面到底发生了什么,否则语言总是会感到有点不可预测和不一致。当你的心智模型不完整时,你肯定会遇到一些问题。
不过,如果你花一点时间来学习该语言的实际工作原理,一切都会变得更加直观和可预测。在那些阳光灿烂的日子里,我喜欢自由自在的写 CSS!
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/DXXWIL4m26vAf0PMcyJ4Lg
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。