- 做者:陈大鱼头
- github: KRISACHAN
在上一篇【Hello CSS】
的第一章CSS的语法与工做流中介绍了CSS
的语法规则以及基本的渲染流程。本篇则会分享CSS
的逻辑属性以及盒子模型。javascript
首先开篇以前先提个问题:css
为何Flex box
跟Grid box
的是以start
、end
为排列规则,而不是常规的top
、right
、bottom
跟left
?html
先不要急着往下翻,你们先思考一下。前端
这个问题的答案,鱼头会在文章中给出,欢迎你们带着这个问题往下翻阅,若是已经知道答案,也能够看看跟你们所知道的答案是否一致。java
2017年5月18日,W3C的 CSS工做组(CSS Working Group) 发布了 CSS逻辑属性和值(CSS Logical Properties and Values Level 1) 的首份工做草案(First Public Working Draft)。不一样的书写模式(writing mode)中,能够抽取出共性的抽象概念(如开始位置,或行),这些逻辑抽象概念须要在不一样书写模式下映射到左或右、上或下等物理的概念上。一些CSS布局可能依赖这些共性的逻辑概念。该 CSS 模块给出了用于经过逻辑方式(而不是基于物理坐标、书写方向和维映射等)控制布局的逻辑属性和取值(logical properties and values)。这个模块来源于CSS21中关于逻辑属性和值的特性。
上面复制粘贴了W3C 中国里的内容。git
对于前端来讲,咱们一直习惯于使用top
、 right
、 bottom
、 left
来定义咱们的HTML
元素,这跟咱们物理上的概念是一致的。可是对于CSS
这个本来是为了服务于图文展现才诞生的语言来讲,实际上是不匹配的,为何这么说?github
writing-mode:定义了文本水平或垂直排布以及在块级元素中文本的行进方向。
writing-mode
一共有如下5个改变HTML
文本书写规则的值(还有几个是用在SVG
上的,本文不予讨论):算法
writing-mode: horizontal-tb
定义了内容从左到右水平流动,从上到下垂直流动。下一条水平线位于上一条线下方。segmentfault
writing-mode: vertical-rl
定义了内容从上到下垂直流动,从右到左水平流动。下一条垂直线位于上一行的左侧。浏览器
writing-mode: vertical-lr
定义了内容从上到下垂直流动,从左到右水平流动。下一条垂直线位于上一行的右侧。
writing-mode: sideways-rl
定义了内容从上到下垂直流动,全部字形,甚至是垂直脚本中的字形,都设置在右侧。
writing-mode: sideways-lr
内容从上到下垂直流动,全部字形,甚至是垂直脚本中的字形,都设置在左侧。
上述效果请看DEMO
源码以下:
.wm-htb { writing-mode: horizontal-tb; } .wm-vrl { writing-mode: vertical-rl; } .wm-vlr { writing-mode: vertical-lr; } .wm-srl { writing-mode: sideways-rl; } .wm-slr { writing-mode: sideways-lr; } .text-content { width: 200px; padding: 20px; border: 1px solid; display: inline-block; vertical-align: top; padding-right: 100px; } <div class="text-content wm-htb">writing-mode: horizontal-tb;</div> <div class="text-content wm-vrl">writing-mode: vertical-rl;</div> <div class="text-content wm-vlr">writing-mode: vertical-lr;</div> <div class="text-content wm-srl">writing-mode: sideways-rl;</div> <div class="text-content wm-slr">writing-mode: sideways-lr;</div>
图示以下:
从上图能够发现,当咱们设置了padding-right: 100px;
的时候,不一样的书写规则,展现效果是不同的。
在最开始的时候,HTML
与CSS
只服务于英语国家,可是随着互联网的发展,逐渐各个不一样书写规则的国家也开始流行了起来。
咱们原来的CSS
逻辑属性是按照物理逻辑,从上(top)、右(right)、下(bottom)、左(left)划分的。
那么按着这个规则去修改文本属性时,就会出现上述这种不符合语法规则的状态。
大概也是基于这个缘由,因此W3C发布了新的逻辑属性与值。
CSS新旧逻辑属性是彻底不一样的两种模型。
咱们首先来看看新旧有的逻辑属性的对比图示(图片来自medium):
左旧右新
经过上图能够得知新旧逻辑属性对应关系以下:
旧的逻辑属性 | 新的逻辑属性 |
---|---|
margin-top | margin-block-start |
margin-right | margin-inline-end |
margin-bottom | margin-block-end |
margin-left | margin-inline-start |
border-top | border-block-start |
border-right | border-inline-end |
border-bottom | border-block-end |
border-left | border-inline-start |
padding-top | padding-block-start |
padding-right | padding-inline-end |
padding-bottom | padding-block-end |
padding-left | padding-inline-start |
width | inline-size |
height | block-size |
由上表能够得知,把Y轴方向的属性都改成了block,X轴方向的属性都改成了inline。
对于不一样语系的国家,书写顺序会可能有很大的差别,意思就是block
跟inline
的方向不一样。例如:
padding-inline-start
= padding-left
padding-inline-start
= padding-right
padding-inline-start
= padding-top
这就意味着旧的逻辑属性,在某些国家里会变得不合常理。
CSS
的定位属性变化以下:
旧的逻辑属性 | 新的逻辑属性 |
---|---|
top | inset-block-start |
bottom | inset-block-end |
left | inset-inline-start |
right | inset-inline-end |
例子以下:
/* 旧的逻辑属性 */ .popup{ position:fixed; top:0; bottom:0; left:0; right:0; } /* 新的逻辑属性 */ .popup{ position:fixed; inset-block-start:0; /*top - in English*/ inset-block-end:0; /*bottom - in English*/ inset-inline-start:0; /*left - in English*/ inset-inline-end:0; /*right - in English*/ } /* 新的逻辑属性支持简写 */ .popup{ position:fixed; inset:0 0 0 0; /*top, right, bottom, left - in English*/ }
图示:(图片来自medium):
浮动float
的属性也改了。
旧的逻辑属性 | 新的逻辑属性 |
---|---|
float: left | float: inline-start |
float: right | float: inline-end |
文本text-align
的属性也改了。
旧的逻辑属性 | 新的逻辑属性 |
---|---|
text-align: left | text-align: start |
text-align: right | text-align: end |
除了writing-mode
,还有一个排版属性就是direction
,跟writing-mode
相似,不同的是writing-mode
是控住网页布局方向的,而direction
是控制文本对齐方向的。属性以下:
默认值,让文本和其余元素从左到右显示。
让文本和其余元素从右到左显示。
吐槽一下,看到这里的切图仔们,抓紧 跑路 重构吧,等哪天此属性正式被启用,就真的GG了。不过我想应该会立个属性来选择性开启物理属性仍是逻辑属性,否则这对前端来讲将会是一场灾难!
当浏览器对一个render tree进行渲染时,浏览器的渲染引擎就会根据基础盒模型(CSS basic box model),将全部元素划分为一个个矩形的盒子,这些盒子的外观,属性由CSS
来决定。
咱们在浏览器控制台输入以下代码就能够看到页面的每个元素都是由一个矩形来包裹的,这些就是盒子
$$('*').forEach(e => { e.style.border = '1px solid'; })
图示以下:
每一个盒子都由四个部分组成:
盒子(box) 的内容,显示标签内一切的文本,图案或者别的内容。
盒子(box) 内的填充物,样式为透明,主要负责扩展盒子内区域大小。
盒子(box) 外部的区域,样式为透明,负责隔离相邻的元素。
盒子(box) 的边界,负责隔离外边距以及内边距。
盒子模型一共有三个值:
content-box
为标准的盒子模型。盒子的width
跟height
只包括盒子自己的width
与height
属性。
计算法则:
width = width
height = height
border-box
为盒子模型可选的属性之一。盒子的width
跟height
包括content
、padding
跟border
。这也是当文档处于 Quirks模式 时Internet Explorer使用的盒模型。
计算法则:
width = width + border + padding
height = height + border + padding
padding-box
为非标准属性,曾经在Firefox中实现过,可是在Firefox 50中被删除。padding-box
的width
和height
属性包括内容和内边距,可是不包括边框和外边距。
图示:
这里吐槽一下,不知道为什么没有margin-box,虽然并无太大意义,当真实现了效果估计也很诡异,可是做为一个强迫症患者晚期,少了一个属性总感受好不舒服。
CSS
的 视觉格式化模型(visual formatting model) 是根据 基础盒模型(CSS basic box model) 将 文档(doucment) 中的元素转换一个个盒子的实际算法。官方说法就是:它规定了用户端在媒介中如何处理文档树( document tree )。
每一个盒子的布局由如下因素决定:
视觉格式化模型(visual formatting model) 的计算,都取决于一个矩形的边界,这个矩形,被称做是 包含块( containing block ) 。 通常来讲,(元素)生成的框会扮演它子孙元素包含块的角色;咱们称之为:一个(元素的)框为它的子孙节点建造了包含块。包含块是一个相对的概念。
例子以下:
<div> <table> <tr> <td>hi</td> </tr> </table> </div>
以上代码为例,div
和 table
都是包含块。div
是 table
的包含块,同时 table
又是 td
的包含块,不是绝对的。
图示:(图片来自w3help):
盒子的生成是
CSS视觉格式化模型 的一部分,用于从文档元素生成盒子。盒子的类型取决于
CSS display
属性。
块级元素
display
为 block
、list-item
或 table
时,它就是块级元素。块级盒子
匿名盒子
CSS 选择器
选中,也就是全部可继承的 CSS 属性值都为 inherit
,而全部不可继承的 CSS 属性值都为 initial
。所以称为匿名盒子(anonymous boxes)。行内元素
display
为 inline
、inline-block
或 inline-table
时,它就是行内级元素。行内盒子
行内格式化上下文(inline formatting context)
的建立。匿名行内盒子
initial
。行盒子
run-in 盒子(在CSS 2.1的标准中移除了)
display: run-in
来设置,它既能够是块盒子,又能够是行内盒子,这取决于它后面的盒子的类型。一旦造成了盒子,CSS引擎就须要定位它们来完成布局。
定位所使用的规则以下:
普通流
浮动:当一个盒子的float
不为none
,而且position
为static
或relative
时,该盒子为浮动定位。
float: left
:盒子会定位到当前行盒子的开始位置(左侧)。float: right
:盒子会定位到当前行盒子的尾部位置(右侧)。绝对定位:若是元素的position
为 absolute
或 fixed
,该元素为绝对定位。
视觉格式化模型(Visual formatting model)
本篇文章主要介绍了CSS
的新旧逻辑属性的状态以及盒子模型的具体状况。文章内还有部份内容没有进行太多的介绍,例如块格式化上下文(block formatting context) 跟 行内格式化上下文(inline formatting context)以及其余一些具体的名称,这些后续的文章都将会进行介绍,到时候将会进行具体的讲解,但愿你们能够多多关注鱼头个人【Hello CSS】系列。
开头时,鱼头我有问到你们一个问题,就是:
为何Flex box
跟Grid box
的是以start
、end
为排列规则,而不是常规的top
、right
、bottom
跟left
?
这个问题,经过本篇文章的分享,你们有答案了吗?
鱼头我将会在下一篇开头时分享答案,但愿你们多多留意本系列文章。
【Hello CSS】
是以CSS
基础概念为主题的系列文章,旨在帮助你们更深入地了解而且提升CSS
在各位开发者心目中的地位。因为鱼头我水平有限,文笔有限,若是各位在文章中发现有任何不合理,不正确的地方,还烦不吝指出,我会很是感谢的;若是经过文章有任何想法或疑问,也但愿各位能积极留言,咱们互相探讨;若是经过本系列文章有所收获,这就让鱼头我喜不自胜了!
若是你也喜欢CSS
,喜欢探讨技术,或者对本文,本系列有任何的意见或建议,鱼头很是但愿你能加入一个有趣的微信群 — “进击的CSS”。你能够扫描下方二维码,添加鱼头微信,添加时注明 “加群”,若是你以为个人文章有趣,欢迎关注微信公众号“鱼头的Web海洋”。衷心但愿能够碰见你。