前段时间试译了Keith J.Grant的CSS好书《CSS in Depth》,其中的第二章《Working with relative units》,书中对relative units的讲解和举例能够说至关全面,看完以后发现本身并不太懂CSS相对单位,也但愿分享给你们,因此有了这个译文系列。(如有勘误或翻译建议,欢迎 Github PR ^_^
)css
《别说你懂CSS相对单位》系列译文:html
本文对应的章节目录:前端
2.2 em和remgit
2.2.2 对font-size使用remgithub
2.3 中止使用像素思惟去思考浏览器
当浏览器解析HTML文档时,建立了一个用来表明页面元素的集合,叫作DOM(文档对象模型,Document Object Model)。树状结构,每个节点表明一个元素。<html>
就是顶层节点(根节点),在下面的是它的子节点<head>
和<body>
,再往下就是它们的子节点,还有后代节点,如此类推。less
根节点是文档里全部其余元素的祖先。它有一个特别的伪类(pseudo-class)选择器(:root),在样式表里能够用这个选择器表示。使用带类名的类型选择器html,或者直接用标签选择器,效果是同样的。工具
rem是根em(root em)的缩写。rem是和根元素关联的,不依赖当前元素。无论你在文档中的什么地方使用这个单位,1.2rem的计算值是相等的,等于1.2倍的根元素的字号大小。下面的示例代码中,声明了根元素的字号大小,并在嵌套的无序列表中使用rem声明字号大小。post
[ 代码片断 2.10 使用rem声明字号大小 ]优化
:root { 1 font-size: 1em; 2 } ul { font-size: .8rem; }
在这个示例里,根字号大小是浏览器的默认大小16px(根元素的1em等于浏览器的默认字号大小)。无序列表的字号大小为0.8rem,计算结果是12.8px。由于这只跟根元素相关,尽管你在列表里嵌套了列表,嵌套子列表的字号仍然保持不变。
可用性:对font-size使用相对长度单位
一些浏览器会提供给用户2种方式定制文字的大小:缩放和设置一个默认的字号大小。经过按Ctrl+或者Ctrl-,用户能够对页面进行缩放。这在视觉上会把整个页面的文字或图片(实际上是全部元素)都放大或缩小了。在一些浏览器,这个改变只针对当前的标签页且是临时的,不会影响到新开的标签页。
设置默认字号大小,会有点不同。不只仅是设置的入口比较难找(通常在浏览器的设置页),并且这个设置是永久的,直到用户把默认值还原。值得注意的是,这个设置对使用px或其余绝对单位定义的字号大小无效。由于默认字号大小对一些用户是必要的,尤为是弱视的群体,你应该用相对单位或百分比来定义字号的大小。
rem简化了不少em带来的复杂度。事实上,rem提供了一个在px和em间的相对单位折中解决方案,并且更易于使用。那么,是否是意味着你应该在对全部元素都使用rem,去掉其余长度单位呢?固然不是。
在CSS的世界里,这个答案一般是,看状况。rem只是你的工具箱中的其中一个。掌握CSS很重要的一点,就是学会分辨在什么场景下该使用什么工具。个人选择是,对font-size
使用rem,对border使用px,对其余的度量方式如padding
、margin
、border-radius
等使用em。然而在必要时,须要声明容器的宽度的话,我更喜欢使用百分比。
这样,字号大小就变得可预测,而当其余因素影响到元素的字号大小时,你也能够借助em去缩放元素的padding和margin。在border上使用像素是很合适的,尤为当你想要一根漂亮的线的时候。以上就是我对不一样属性使用不一样单位的理想方案,不过我要再次声明,这些都是工具,在某些特定场景下,利用不一样的工具可能取到更好的效果。
提示当你不肯定的时候,对
font-size
使用rem,对border
使用px,以及对其余大多数属性使用em。
把页面的根元素字号大小定义为0.625em或者62.5%,在最近几年来,这样的用法很常见,这是一种模式,或者更贴切地说,这是一种反模式。
[ 代码片断 2.11 反模式:全局地把font-size定义为10px ]
html { font-size: .625em; }
我并不推荐这种用法。这个用法把浏览器默认的字号大小16px缩小到10px。这样作的好处是简化了计算,若是设计师告诉你字号大小应该是14px,那你能够很轻易地计算出1.4rem,毕竟咱们仍是在使用相对单位。
一开始,这看起来很方便,但事实上这样的实现方式有两个问题。第一,强制你写了不少重复的样式代码。10px对于大多数文原本说过小了,你须要在整个页面中,来来回回地覆盖它。你会发现,本身把一段段落(<p>
)的字号大小声明为1.4rem,而后又把导航(<nav>
)的连接字号大小声明为1.4rem,样式代码中还有不少这样的用法。这样引入了更高的错误风险,当你须要修改时发现代码耦合程度比较高,同时也会让样式文件变大。
第二个问题是,你这么作的时候,其实你仍是在用像素的思惟在思考。虽然在代码里写的是1.4rem
,可是在你的脑子里,其实仍是想的是14px
。在响应式网页开发中,你应该学会适应那些“模糊”的值。1.2em实际等于多少像素,并不重要,你只须要知道这是比继承的字号大一点点,那就足够了。并且,若是在屏幕上这不是你想要的效果,那就改吧。这是须要时间实验和试错的,但事实上,使用px的时候咱们也须要这样作。(在第13章,咱们会有更具体的方式来优化这个实现方式。)
当使用em时,咱们很容易陷入纠结,这个值转化成像素值会是多少呢?尤为对于字号大小。你一直在乘和除以em值,这样你很快就会疯掉了。相反,我但愿你能够接受一项挑战,尝试培养先开始使用em的习惯。若是你习惯使用像素,那转成em是须要必定时间和练习的,但相信我,这很值得。
这不是在说你不再使用像素了。若是你跟一个设计师合做,你可能须要用更精确的像素值去沟通,这没问题的。在项目的开始,你须要声明一个基础的字号大小(一般是对标题或者标注的经常使用字号)。使用绝对值去描述大小,每每会更加容易。
转换成rem会有计算环节,那就让计算器去忙吧(一般我会在Mac电脑上按cmd+空格
,在Spotlight里计算)。首先在根元素上声明根字号大小,从那开始,使用像素应该是例外的状况,而不是常态。
在这章内容里,我仍是会持续地聊起像素。这会有助于我解释相对单位的工做原理,同时也能帮助你培养计算em值的习惯。在这章以后,我基本会使用相对单位来讨论字号的大小。
先假设你想把默认字号设定为14px。把10px设定为基准值,再在页面中去覆盖它的写法,咱们不推荐这种写法,相反,你应该在根元素上直接声明一个值。
在这个代码片断里,目标字号值是继承的,浏览器的默认值16px,那么14/16 = 0.875。
把下面的代码添加到一个新的样式表的最上面,咱们会在这上面添加其余代码。这里设定根元素(<html>
)的默认字号大小。
[ 代码片断 2.12 设定正确的默认字号大小 ]
:root { 1 font-size: 0.875em; 2 }
如今,你的指望基准字号14px对整个页面的元素有效,你不须要在其余地方从新声明了。你只须要在设计不同的地方修改为新的字号,譬如标题。
咱们一块儿来建立图2.7那样的面板吧!你建立的这个面板,基于14px字号,使用相对单位。
[ 图 2.7 使用相对单位和继承字号的面板 ]
下面是模板,加到你的页面吧。
[ 代码片断 2.13 面板的模板 ]
<div class="panel"> <h2>Single-origin</h2> <div class="panel-body"> We have built partnerships with small farms around the world to hand-select beans at the peak of season. We then carefully roast in <a href="/batch-size">small batches</a> to maximize their potential. </div> </div>
下一段代码是样式的。你会在padding
和border-radius
使用em
,标题的字号使用rem
,以及border
使用px
。把下面代码添加到你的样式表吧。
[ 代码片断 2.14 使用相对单位的面板 ]
.panel { padding: 1em; 1 border-radius: 0.5em; 1 border: 1px solid #999; 2 } .panel > h2 { margin-top: 0; 3 font-size: 0.8rem; 4 font-weight: bold; 4 text-transform: uppercase; 4 }
这段代码给面板添加了一个细边框以及定义了标题的样式。我但愿标题的字号小一点,但要加粗和全是大写。(你能够根据本身的设计,把字号改大点或者使用不一样的排版方式)
第二个选择器>
是一个直接后代组合选择符(direct descendant combinator),它表明的是.panel
下的子元素h2
。更完整的选择器和组合选择符的索引能够看附录A。
在代码片断2.13中,为了更清晰看到效果,我给body
添加了一个类panel-body
,不过你会发现,在你本身的代码里是不须要的。由于这个元素从根元素上继承了字号大小,它已是你想要看到的那样。
咱们再更深刻地看看这个问题。你能够根据屏幕尺寸的变化,添加媒体查询来改变基础字号大小,这能够令面板在不一样尺寸的屏幕下,有不一样的大小变化。(见图2.8)
[ 图 2.8 在不一样屏幕大小的响应式面板:300px(左上角),800px(右上角),1440px(下面) ]
媒体查询(media query) —— 经过
@media
规则来声明样式,在不一样的屏幕尺寸或者媒体类型(如打印机或显示器)下,触发对应的样式控制。这是响应式设计的关键要素。详情看代码片断2.15的这个例子,我在第8章会更深刻的讨论媒体查询这个话题。
为了实现上面说的效果,把你的样式代码改为这样。
[ 代码片断 2.15 ]
:root { 1 font-size: 0.75em; 1 } 1 @media (min-width: 800px) { 2 :root { 2 font-size: 0.875em; 2 } 2 } 2 @media (min-width: 1200px) { 3 :root { 3 font-size: 1em; 3 } 3 }
第一套样式规则,声明了小屏幕中的默认字号大小,这是咱们想要在较小的屏幕上看到的字号大小。而后使用媒体查询,把800px和1200px分别做为两个分水岭逐级增长字号的大小,覆盖掉默认的代码。
针对页面的根元素使用这些字号大小,响应式地从新定义em和rem对应的值,从而达到响应改变整个页面的效果。尽管你没有直接对这个面板作任何的修改,它如今是响应式的。在小屏幕上,譬如一台手机,字号大小会被渲染成更小的(12px)。而后,在更大的屏幕上,宽大于800px和大于1200px的,组件的字号会分别放大到14px和16px。改变你的浏览器窗口,看看组件是怎么变化的吧。
若是你在整个页面中像这样严格使用相对单位,整个页面会随着视窗大小放大和缩小。这会是你的响应式策略里很重要的一部分。上面的2套媒体查询声明代码,能够帮助你节省在页面的其余部分使用媒体查询的额外代码。不过,若是你在元素中声明的字号大小是以像素为单位的,那就不会产生任何效果了。
相似地,若是你的老板或者客户以为如今网站的字号过小或者太大,你随时能够作到经过修改一行代码影响到全局的元素,这项改变会影响到页面上的其余元素,不费吹灰之力。
你也能够经过使用em缩放页面上的一个独立组件。有时,你可能会须要界面上的某些组件能够有个大号的版本。在咱们的面板上这么作吧,首先你须要给面板添加一个类名large
:<div class="panel large">
。
在图2.9,咱们看到了面板的普通版和大号版的比较。效果相似响应式面板,可是两种尺寸是能够同时在同一个页面中使用的。
[ 图 2.9 在一个页面上的普通尺寸面板和大号面板 ]
咱们来对面板的字号声明方式作一些小的修改。你仍是在使用相对单位,但须要调整它们的基准值。第一点,给每一个面板的父元素字号大小的定义font-size: 1rem
。这里指的是,无论在什么地方使用这个面板,每一个面板的字号大小是一个肯定值。
第二点,使用em从新声明标题的字号大小,而不使用rem,这样标题就能够和刚才声明的父元素字号1rem关联起来。下面是对应的代码,更新下你的样式表代码吧。
[ 代码片断 2.16 建立一个面板的大号版本 ]
.panel { font-size: 1rem; 1 padding: 1em; border: 1px solid #999; border-radius: 0.5em; } .panel > h2 { margin-top: 0; font-size: 0.8em; 2 font-weight: bold; text-transform: uppercase; }
这些修改看起来并无影响面板的样式,可是如今你已经准备好了,作一个大号的面板只须要修改一小行代码。你须要作的,就是把父元素字号大小改写成1rem之外的一个值。由于其余元素的计算方式都依赖父元素的字号大小,只要修改它,整个面板的相关尺寸都会发生改变。添加下一个CSS代码片断到你的样式表,定义一个大号面板吧。
[ 代码片断 2.17 利用一行代码放大整个面板 ]
.panel.large { 1 font-size: 1.2rem; }
如今,你能够给普通面板添加class="panel"
和给大号面板添加class="panel large"
。相似地,你也能够定义一个小号版本,只须要把父元素的字号设得比1rem小。若是这个面板是一个更复杂的组件,包含多种字号大小或padding,也只须要一个声明就能够重置大小,只要全部的子元素都是使用em声明的。
《别说你懂CSS相对单位》系列译文:
章节:
2.1 相对单位值的魔力
2.2 em和rem
2.2.1 对font-size使用em
2.2.2 对font-size使用rem
2.3 中止使用像素思惟去思考
2.4 视口相关单位(viewport-relative units)
2.6 自定义属性(也叫“CSS变量”)
原著版权信息:做者:Keith J.Grant
书籍:CSS in Depth
章节:Working with relative units
笔者 @Yuying Wu,前端爱好者 / 鼓励师 / 新西兰打工度假 / 铲屎官。目前就任于某大型电商的B2B前端团队。
感谢你读到这里,对上文如有任何疑问或建议,欢迎留言。
若是你和我同样喜欢前端,喜欢捣腾独立博客或者前沿技术,或者有什么职业疑问,欢迎关注我以及各类交流哈。
独立博客:wuyuying.com
知乎ID:@Yuying Wu
Github:Yuying Wu