web前端入门到实战:CSS的逻辑属性与盒子模型

首先开篇之前先提个问题:

为什么Flex boxGrid box的是以startend为排列规则,而不是常规的toprightbottomleft

先不要急着往下翻,大家先思考一下。

这个问题的答案,鱼头会在文章中给出,欢迎大家带着这个问题往下翻阅,如果已经知道答案,也可以看看跟大家所知道的答案是否一致。

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中关于逻辑属性和值的特性。

对于前端来说,我们一直习惯于使用toprightbottomleft来定义我们的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;的时候,不同的书写规则,展示效果是不一样的。

在最开始的时候,HTMLCSS只服务于英语国家,但是随着互联网的发展,逐渐各个不同书写规则的国家也开始流行了起来。

我们原来的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轴方向的属性都改为了blockX轴方向的属性都改为了inline

对于不同语系的国家,书写顺序会可能有很大的差异,意思就是blockinline的方向不同。例如:

  • 在英语国家 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为标准的盒子模型。盒子的widthheight只包括盒子本身的widthheight属性。

计算法则:

width = width

height = height

border-box

border-box为盒子模型可选的属性之一。盒子的widthheight包括contentpaddingborder。这也是当文档处于 Quirks模式 时Internet Explorer使用的盒模型。

计算法则:

width = width + border + padding

height = height + border + padding

padding-box

padding-box为非标准属性,曾经在Firefox中实现过,但是在Firefox 50中被删除。padding-boxwidthheight 属性包括内容和内边距,但是不包括边框和外边距。

图示:

这里吐槽一下,不知道为何没有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)

以上代码为例,divtable 都是包含块。divtable 的包含块,同时 table 又是 td 的包含块,不是绝对的。

盒子的生成

盒子的生成是 CSS视觉格式化模型 的一部分,用于从文档元素生成盒子。盒子的类型取决于CSS display 属性。

  • 块级元素

    • 当元素的displayblocklist-itemtable 时,它就是块级元素。
  • 块级盒子

    • 块级盒子用于描述它与父、兄弟元素之间的关系。
    • 每个块级盒子都会参与块格式化上下文(block formatting context)的创建。
    • 每个块级元素都会至少生成一个块级盒子,即主块级盒子(principal block-level box)
    • 主块级盒子包含由后代元素生成的盒子以及内容,同时它也会参与定位方案。
    • 一个同时是块容器盒子的块级盒子称为块盒子(block box)
  • 匿名盒子

    • 某些情况下需要进行视觉格式化时,需要添加一些增补性的盒子,这些盒子不能被CSS 选择器选中,也就是所有可继承的 CSS 属性值都为 inherit ,而所有不可继承的 CSS 属性值都为 initial。因此称为匿名盒子(anonymous boxes)
  • 行内元素

    • 当元素的displayinlineinline-blockinline-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,并且positionstaticrelative时,该盒子为浮动定位。

    • float: left:盒子会定位到当前行盒子的开始位置(左侧)。
    • float: right:盒子会定位到当前行盒子的尾部位置(右侧)。
  • 绝对定位:如果元素的positionabsolutefixed,该元素为绝对定位。

    • 在绝对定位中,盒子会完全从当前流中移除,并且不会再与其有任何联系。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,904评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,581评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,527评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,463评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,546评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,572评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,582评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,330评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,776评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,087评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,257评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,923评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,571评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,192评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,436评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,145评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容