首先开篇之前先提个问题:
为什么 Flex box 跟 Grid box 的是以 start,end 为排列规则, 而不是常规的 top ,right ,bottom 跟 left?
先不要急着往下翻, 大家先思考一下.
这个问题的答案, 鱼头会在文章中给出, 欢迎大家带着这个问题往下翻阅, 如果已经知道答案, 也可以看看跟大家所知道的答案是否一致.
CSS 的逻辑属性
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 中关于逻辑属性和值的特性.
对于前端来说, 我们一直习惯于使用 top , right , bottom, left 来定义我们的 html 元素, 这跟我们物理上的概念是一致的. 但是对于 CSS 这个原本是为了服务于图文展示才诞生的语言来说, 其实是不匹配的, 为什么这么说?
writing-mode
writing-mode: 定义了文本水平或垂直排布以及在块级元素中文本的行进方向.
writing-mode 一共有以下 5 个改变 HTML 文本书写规则的值(还有几个是用在 SVG 上的, 本文不予讨论):
writing-mode: horizontal-tb;
writing-mode: horizontal-tb 定义了内容从左到右水平流动, 从上到下垂直流动. 下一条水平线位于上一条线下方.
writing-mode: vertical-rl;
writing-mode: vertical-rl 定义了内容从上到下垂直流动, 从右到左水平流动. 下一条垂直线位于上一行的左侧.
writing-mode: vertical-lr;
writing-mode: vertical-lr 定义了内容从上到下垂直流动, 从左到右水平流动. 下一条垂直线位于上一行的右侧.
writing-mode: sideways-rl; (仅 Firefox41 + 实现)
writing-mode: sideways-rl 定义了内容从上到下垂直流动, 所有字形, 甚至是垂直脚本中的字形, 都设置在右侧.
writing-mode: sideways-lr;(仅 Firefox41 + 实现)
writing-mode: sideways-lr 内容从上到下垂直流动, 所有字形, 甚至是垂直脚本中的字形, 都设置在左侧.
源码如下:
- .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>
web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频, PDF)
图示如下:
从上图可以发现, 当我们设置了 padding-right: 100px; 的时候, 不同的书写规则, 展示效果是不一样的.
在最开始的时候, HTML 与 CSS 只服务于英语国家, 但是随着互联网的发展, 逐渐各个不同书写规则的国家也开始流行了起来.
我们原来的 CSS 逻辑属性是按照物理逻辑, 从上 (top), 右(right), 下(bottom), 左(left) 划分的.
那么按着这个规则去修改文本属性时, 就会出现上述这种不符合语法规则的状态.
大概也是基于这个原因, 所以 W3C 发布了新的逻辑属性与值.
新旧逻辑属性对比
CSS 新旧逻辑属性是完全不同的两种模型.
我们首先来看看新旧有的逻辑属性的对比图示:
左旧右新
通过上图可以得知新旧逻辑属性对应关系如下:
旧的逻辑属性 | 新的逻辑属性 |
---|---|
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 定位
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*/
- }
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频, PDF)
CSS 浮动
浮动 float 的属性也改了.
旧的逻辑属性 | 新的逻辑属性 |
---|---|
float: left | float: inline-start |
float: right | float: inline-end |
text-align
文本 text-align 的属性也改了.
旧的逻辑属性 | 新的逻辑属性 |
---|---|
text-align: left | text-align: start |
text-align: right | text-align: end |
direction
除了 writing-mode, 还有一个排版属性就是 direction, 跟 writing-mode 类似, 不一样的是 writing-mode 是控住网页布局方向的, 而 direction 是控制文本对齐方向的. 属性如下:
direction: ltr;
默认值, 让文本和其他元素从左到右显示.
direction: rtl;
让文本和其他元素从右到左显示.
吐槽一下, 看到这里的切图仔们, 抓紧 跑路 重构吧, 等哪天此属性正式被启用, 就真的 GG 了. 不过我想应该会立个属性来选择性开启物理属性还是逻辑属性, 不然这对前端来说将会是一场灾难!
CSS 的盒子模型
基础盒模型(CSS basic box model)
当浏览器对一个 render tree 进行渲染时, 浏览器的渲染引擎就会根据基础盒模型(CSS basic box model), 将所有元素划分为一个个矩形的盒子, 这些盒子的外观, 属性由 CSS 来决定.
我们在浏览器控制台输入如下代码就可以看到页面的每一个元素都是由一个矩形来包裹的, 这些就是盒子
- $$('*').forEach(e => {
- e.style.border = '1px solid';
- })
图示如下:
每个盒子都由四个部分组成:
内容(content)
盒子(box) 的内容, 显示标签内一切的文本, 图案或者别的内容.
内边距(padding)
盒子(box) 内的填充物, 样式为透明, 主要负责扩展盒子内区域大小.
外边距(margin)
盒子(box) 外部的区域, 样式为透明, 负责隔离相邻的元素.
边框(border)
盒子(box) 的边界, 负责隔离外边距以及内边距.
盒子模型的值
盒子模型一共有三个值:
content-box
content-box 为标准的盒子模型. 盒子的 width 跟 height 只包括盒子本身的 width 与 height 属性.
计算法则:
- width = width
- height = height
- border-box
border-box 为盒子模型可选的属性之一. 盒子的 width 跟 height 包括 content,padding 跟 border. 这也是当文档处于 Quirks 模式 时 Internet Explorer 使用的盒模型.
计算法则:
- width = width + border + padding
- height = height + border + padding
- padding-box
padding-box 为非标准属性, 曾经在 Firefox 中实现过, 但是在 Firefox 50 中被删除. padding-box 的 width 和 height 属性包括内容和内边距, 但是不包括边框和外边距.
图示:
这里吐槽一下, 不知道为何没有 margin-box, 虽然并没有太大意义, 当真实现了效果估计也很诡异, 但是作为一个强迫症患者晚期, 少了一个属性总感觉好不舒服.
视觉格式化模型(visual formatting model)
CSS 的视觉格式化模型(visual formatting model) 是根据 基础盒模型(CSS basic box model) 将 文档(doucment) 中的元素转换一个个盒子的实际算法.
官方说法就是: 它规定了用户端在媒介中如何处理文档树( document tree ).
每个盒子的布局由以下因素决定:
盒子的尺寸
盒子的类型: 行内盒子 (inline), 行内级盒子 (inline-level), 原子行内级盒子 (atomic inline-level), 块盒子 (block)
定位: 普通流, 浮动, 绝对定位
文档树中当前盒子的子元素 或 兄弟元素
视口(viewport) 的尺寸 和位置
盒子内部图片的尺寸
其他某些外部因素
视觉格式化模型 (visual formatting model) 的计算, 都取决于一个矩形的边界, 这个矩形, 被称作是 包含块( containing block ) . 一般来说,(元素) 生成的框会扮演它子孙元素包含块的角色; 我们称之为: 一个 (元素的) 框为它的子孙节点建造了包含块. 包含块是一个相对的概念.
例子如下:
- <div>
- <table>
- <tr>
- <td>hi</td>
- </tr>
- </table>
- </div>
Web 前端开发学习 Q-q-u-n: 731771211, 分享学习的方法和需要注意的小细节, 不停更新最新的教程和学习方法(详细的前端项目实战教学视频, PDF)
以上代码为例, div 和 table 都是包含块. div 是 table 的包含块, 同时 table 又是 td 的包含块, 不是绝对的.
盒子的生成
盒子的生成是 CSS 视觉格式化模型 的一部分, 用于从文档元素生成盒子. 盒子的类型取决于 CSS display 属性.
块级元素
当元素的 display 为 block,list-item 或 table 时, 它就是块级元素.
块级盒子
块级盒子用于描述它与父, 兄弟元素之间的关系.
每个块级盒子都会参与块格式化上下文 (block formatting context) 的创建.
每个块级元素都会至少生成一个块级盒子, 即主块级盒子(principal block-level box)
主块级盒子包含由后代元素生成的盒子以及内容, 同时它也会参与定位方案.
一个同时是块容器盒子的块级盒子称为块盒子(block box).
匿名盒子
某些情况下需要进行视觉格式化时, 需要添加一些增补性的盒子, 这些盒子不能被 CSS 选择器选中, 也就是所有可继承的 CSS 属性值都为 inherit , 而所有不可继承的 CSS 属性值都为 initial. 因此称为匿名盒子(anonymous boxes).
行内元素
当元素的 display 为 inline,inline-block 或 inline-table 时, 它就是行内级元素.
显示时可以与其他行内级内容一起显示为多行.
行内盒子
行内级元素会生成行内级盒子, 该盒子同时会参与
行内格式化上下文(inline formatting context)
的创建.
匿名行内盒子
类似于块盒子, CSS 引擎有时候也会自动创建一些行内盒子. 这些行内盒子无法被选择符选中, 因此是匿名的, 它们从父元素那里继承那些可继承的属性, 其他属性保持默认值 initial.
行盒子
行盒子由行内格式化上下文创建, 用来显示一行文本. 在块盒子内部, 行盒子总是从块盒子的一边延伸到另一边(译注: 即占据整个块盒子的宽度). 当有浮动元素时, 行盒子会从向左浮动的元素的右边缘延伸到向右浮动的元素的左边缘.
run-in 盒子(在 CSS 2.1 的标准中移除了)
run-in 盒子可以通过 display: run-in 来设置, 它既可以是块盒子, 又可以是行内盒子, 这取决于它后面的盒子的类型.
定位规则
一旦形成了盒子, CSS 引擎就需要定位它们来完成布局.
定位所使用的规则如下:
普通流
在普通流中, 盒子会依次放置.
在块格式化上下文 (block formatting context) 中, 盒子在垂直方向依次排列.
在行内格式化上下文(inline formatting context) 中, 盒子则水平摆列.
浮动: 当一个盒子的 float 不为 none, 并且 position 为 static 或 relative 时, 该盒子为浮动定位.
float: left: 盒子会定位到当前行盒子的开始位置(左侧).
float: right: 盒子会定位到当前行盒子的尾部位置(右侧).
绝对定位: 如果元素的 position 为 absolute 或 fixed, 该元素为绝对定位.
在绝对定位中, 盒子会完全从当前流中移除, 并且不会再与其有任何联系.
来源: http://www.jianshu.com/p/3446dd9b22a6