让前端飞程序员

视觉格式化模型、定位简略相关概念的理解

2017-08-04  本文已影响0人  科研者

目录

一. 我对标签、元素、盒子的理解
   1. web相关概念的职责
   2. 在浏览器与人类交互的过程中,它们的扮演的角色
二. 视觉格式化模型的相关概念
三. display属性
四. 定位策略
   1. position属性
   2. 正常文档流
   3. 相对定位
   4. 浮动
   5. 绝对定位
   6. display、position和float的关系

内容


一. 我对标签、元素、盒子的理解

相信很多人和我之前一样,对于web的许多概念也都知道是什么意思,大家平时交流起来也没什么障碍;但是如果仔细定义、区分这些概念时,却好像又表达不出来,如:

  1. 标签和元素是同一事物吗?
  2. 如果是同一事物,哪为什么它起2个名字?这些名字的使用场景又是什么?
  3. 如果不是同一事物,那它们又分别是什么?

等等,类似这样的问题我们似乎能理解,但又表达不出来!为会会这样,其实这是因为我们没有真正地严格地理解它们,简单来说就是:我们并不理解它们!为了帮助大家理解,我就简单描述一下我对他们的理解,在这里我并不描述这些概念的定义,因为在不更加事物之前,仅描述定义是不能帮助大多数人深刻理解的;

1. web相关概念的职责如下:

  1. 元素包含标签、标签属性和标签之间的内容;标签、标签属性和标签之间的内容是用来描述元素的;
  2. CSS规则是用来描述元素的呈现效果的;
  3. 网页的显示是通过视觉格式化模型呈现的;
  4. 视觉格式化模型是根据元素和CSS规则建立的;

2. 在浏览器与人类交互的过程中,它们的扮演的角色如下:

  1. HTML标签、CSS规则、JavaScript脚本是人与浏览器沟通相互的语言,主要用于人向浏览器表达信息;
  2. 元素是浏览器能直接理解的数据模型;
  3. 视觉格式化模型是浏览器表达自己对元素的理解的规制及方式,主要用于浏览器向人表达信息;

浏览器读取人类传达给他的HTML、CSS规则、JavaScript脚本,然后通过对它的翻译、理解,建立了自己的能直接理解的数据模型——元素;浏览器为了能把自己的数据模型以人类能直接理解的方式传达给人类,它便以具视觉格式化模型把自己的数据开模呈现出来;

所以,标签是HTML语言中的事物;元素是浏览器数据模型中的事物;盒模型是浏览器对人类表达方式中的事物;

二. 视觉格式化模型的相关概念

  1. 盒子: 为了呈现文档树中的元素,浏览器会根据视觉格式化模型为每个元素生成0或多个盒子;这些盒子的布局由如下因素决定:

    1. 盒子的尺寸和类型;
    2. 定位策略(如:正常文档流、浮动或者绝对定位);
    3. 和文档树中其他元素的关系;
    4. 额外的信息(如:视口的大小、图片的原始尺寸等);
  2. 块容器盒子: 即可以产生块级上下文,又可以产生行内上下文的盒子叫做块容器盒子;

  3. 包含块: 既然元素可以有子元素和父元素,而盒子是依据元素生成的,所以盒子也可以包含其它盒子,也可以被其它盒子包含;盒子是根据包含它的盒子的边界来定位的,当一个盒子包含另一个盒子时,就称为这个盒子是另一个盒子的包含块;

    所以,包含块只是盒子在某个场景下的别名;

  4. 格式化上下文: “上下文”是环境的意思;“化”是使转化的意思;所以“格式化上下文”就是使其转化为一定格式的环境;在当前语境中,更通术地讲:“格式化上下文”是合其中的盒子具备一定格式的环境;或者可以理解为:“格式化上下文”是放置盒子的环境;所以,盒子必须放置在格式化上下文中;

    根据其中放置盒子的类型不同(或者说:使盒子转化的格式不同),格式化上下文可分为:

    1. 块级格式化上下文: 只能放置块级盒子的格式化上下文;
    2. 行级格式化上下文: 只能放置行级盒子的格工化上下文;
    3. 行内格式化上下文: 只能放置行内级盒子的格式化上下文;

    当盒子需要包含其它盒子时,便会生成自己的格式化上下文,用来包含其它盒子;每个盒子在同一时刻,只会拥有一个格式化上下文;

  5. 块级盒子: 放置在块级格式化上下文的盒子;

  6. 主块级盒子: 每个块级元素都会产生一个主要的块级盒子,它用来铃后代盒子和其它生成的内容,同时还参与任何的定位策略,这个主要的块级盒子就称为主块级盒子;有些块级元素,除了主块级盒子以外,还将产生其他的盒子,如”list-item”元素。这些额外的盒子会根据主块级盒子进行布局;

  7. 块容器盒子: 即可以生成块级格式化上下文,又可以生成行级格式化上下文的盒子叫做块容器盒子;

  8. 块盒子: 即是块容器盒子,又是块级盒子的盒子叫做块盒子;

  9. 行级盒子: 当盒子里包含的是文本时,文本会一行一行的排列,每一行文本都是被包含在行级盒子里面;所以,有多少行,就有多少个行级盒子;行级盒子存在于行级格式化上下文中;

  10. 行内级盒子: 行级盒子会生成行内级格式化上下文,用于放置行内级盒子;行内级盒子里面一般直接存放的就是文本或者其它行可用于直接展示的行内级内容;


以下内容参考了《CSS中的视觉格式化模型》,并对其进行了修正

三. display属性

display属性的值决定元素产生盒子的种类,具体如下:

  1. block:应用该属性值的元素将会产生一个块盒子;

  2. inline-block:应用该属性值的元素将产生一个行级块容器。inline-block的内部被格式化成一个块盒子,元素本身被格式化成一个原子行级盒子;

  3. inline 应用该属性值的元素将会产生一到多个行盒子;

  4. list-item 应用该属性值的元素(比如html中的li)将会产生一个主块级盒子和一个标签盒子;

  5. none 应用该属性值的元素将不会出现在格式化结构(formatting structure)中,也就是说,元素不产生任何盒子,对布局没有任何影响。元素的后代元素也不产生盒子,元素和元素的内容被从格式化结构中完全删除。通过设置后代元素的"display"属性值也不能改变。

    请注意,"display"为"none"时不产生任何不可见的盒子,实际上,根本不产生任何盒子。如果想产生既不可见又影响格式化结构的盒子,请参考visibility属性。

  6. table,inline-table,table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, and table-caption
    应用以上属性值的元素将表现得像一个表格元素。

注意,尽管"display"属性的初始值为"inline",但是浏览器的默认样式表可能覆盖这个值。

四. 定位策略

盒子的定位方式决定于定位策略;共有3种定位策略,如下:

  1. 正常文档流:盒子根据它所在的格式化上下文逐个排列;
  2. 浮动:在浮动模型中,一个盒子先根据正常文档流定位,然后被从文档流中拿出来尽可能的放到左/右边。上下文中的其他内容将流动到浮动元素的某一边;
  3. 绝对定位:在绝对定位模型中,盒子被从正常文档流中完全移除(被移除的盒子对它原来的兄弟盒子将不再产生任何影响) 并且根据它的包含块进行定位。

如果一个元素是浮动的、绝对定位的或者是根元素,那么就称这个元素脱离了文档流。如果一个元素没有脱离文档流,那么就称这个元素在文档流内。一个脱离文档流的元素A,它的文档流包括元素A本身以及所有A的在文档流内的后代元素。

1. position属性

position属性的取值范围是:static | relative | absolute | fixed | inherit, 初始值为static。每个取值的含义如下:

static: 应用该属性值的盒子就是正常的盒子,根据正常的文档流来进行定位。top、right、bottom和left属性不生效。

relative: 应用该属性值的盒子,其位置将根据盒子在正常文档流中初始的位置以及一个偏移量来计算。即盒子的最终位置将相对于原来的位置发生一定的偏移。当盒子B采用相对定位后,盒子B后面的其他盒子的定位将不受影响,就好像盒子B没有采用相对定位一样。

absolute: 应用该属性值的盒子,其位置由top、right、bottom和left属性来决定,这些属性将根据盒子的包含块来确定偏移量。采用绝对定位的盒子完全脱离正常文档流,也就是说,绝对定位的盒子对其他盒子将不再产生任何影响。采用绝对定位的盒子的外边距(margin)不与其他盒子的外边距重叠。

fixed: 应用该属性值的盒子,其位置将根据绝对定位来计算,另外,盒子还将相对于一定的参照物固定不动。例如在视觉媒体中,采用fixed定位的盒子将相对于视口固定不动。

如果一个元素的position属性值不为static,那么就称这个元素被定位了。被定位的元素将产生被定位的盒子,然后根据top、right、bottom、left这四个属性进行放置;

浏览器可能默认根元素的定位为static定位。

2. 正常文档流

在正常文档流中的盒子都属于一个格式化上下文。这个格式化上下文既可以是块级的,也可以是行级的,但不能两者都是。块级盒子在块格式化上下文中,行级盒子在行格式化上下文中。

2.1 块格式化上下文中盒子的定位

浮动的元素、采用绝对定位的元素、不是块盒子的块容器(比如inline-block,table-cell和table-caption)以及设置了overflow且值不为visible(设置了visible的viewport除外)的块盒子将会为他们的内容建立新的块格式化上下文。

在块格式化上下文中,各个盒子从他们的包含块的顶部开始,竖直的顺次放置。相邻的两个盒子的竖直距离有margin属性决定。在同一个格式化上下文中的两个相邻的块级盒子的竖直外边距将会合并。

在块格式化上下文中,每个盒子的左外边界与盒子的包含块的左边界相接(对于从右到左的情况,右外边界与右边界相接)。 即使当有浮动元素存在是也依然使用,除非这个盒子产生了新的块格式化上下文(这样的话,由于浮动,盒子的宽度将变小)。

2.2 行内格式化上下文中盒子的定位

在行内格式化上下文中,每个盒子从他们的包含块的顶部开始,依据每个盒子的水平margin,border和padding,水平的依次放置。这些盒子在竖直方向上,可能依据顶部或者底部对齐,也可能依据盒子内部文本的基准线对齐。包含这些盒子的来形成行的这个长方形区域就叫行盒子。

2.3 行级格式化上下文中盒子的定位

行盒子必须要有足够的高度来包含它的所有后代盒子。因此,它可能比它包含的最高的盒子还要高(比如,行盒子内部的盒子都依据文本基准线对其)。当盒子B的高度比行盒子低的时候,盒子B在行盒子里的对其方式就由vertical-align属性决定。如果多个行内级盒子无法在单一的行盒子中水平放置,那么这些行内级盒子将会被分放到多个行盒子中。因此,一个段落就是多个行盒子的竖直堆叠。堆叠的行盒子之间没有分隔(除非指定),并且从不重叠。

通常,行盒子的左边界与包含块的左边界相接,右边界与包含块的右边界相接。但是,如果有浮动元素存在的话,那浮动元素将会介乎两者之间。因此,尽管在同一个行级格式化上下文中的行盒子通常都与包含块同宽,但是他们的宽度也会因为受到浮动元素的影响而有所差异。在同一个行级格式化上下文中的行盒子高度可以不同(比如一个行盒子包含一个较高的图片,而另一个仅仅包含文本。)

当行内级盒子的宽度小于包含他们的行盒子时,他们水平方向的对其方式将由text-align属性决定。如果text-align属性取值为justify,那么浏览器可能拉伸盒子中的文字和间距,但是inline-table和inline-block盒子除外。

如果一个行内级盒子的宽度超出了行盒子的宽度,那它将被拆断为多个行内盒子,然后放到多个行盒子中。如果行内盒子不能被拆断(比如:行内盒子仅包含单个字符,或者规定语言单词的截断规则不允许截断,或者使用了white-space,且取值为nowrap或pre),那这个行内级盒子将会溢出行盒子。当行内级盒子被拆断时,margin、border和padding对拆断处没有任何视觉上的影响。

当在行级格式化上下文中需要包含行内级内容时就会创建行盒子。不包含任何文本、任何保留的空白字符、任何拥有非零margin、padding和border的行内元素以及任何其他在流中的内容(例如图片、行内块或行内表格)并且不以保留的换行符结束的行盒子,它将被视作没有高度的行盒子,以此来保证盒子里的任何元素的的位置计算。

3. 相对定位

盒子一但被定位或者被浮动,它可以相对于这个位置进行一定的偏移。这就叫做相对定位。偏移的盒子(B1)对紧跟着它的盒子(B2)没有任何影响(B2的位置就像B1没有发生偏移一样)。因此,相对定位可能导致盒子重叠。但是,如果相对定位导致了设置有"overflow:auto"或者"overflow:scroll"的盒子溢出了,那么浏览器必须允许用户(通过滚动条等)能够访问到盒子的内容。

相对定位的盒子会保持原来的正常大小,包括换行和一开始就保有的空间。

对于相对定位的元素:

在水平方向上:
left和right将盒子不改变大小的水平移动。left将盒子右移,right将盒子左移。因为left或right的结果都不会导致盒子被分隔或拉伸,所以实际上最终使用的值总是: left=-right;具体规则如下:

在垂直方向上:
top和bottom属性将盒子不改变大小的上下移动。top将盒子下移,bottom将盒子上移。因为盒子不会被分隔或者拉伸,所有最终使用的值总是:top=-bottom。

4. 浮动

浮动的盒子会被移动到当前行的左边或者右边。浮动最有趣的特点就是其他内容会在浮动的元素的旁边依次放置(或者通过设置clear属性禁止),或者说其他盒子会流动到浮动盒子的旁边。也就是说,其他盒子将沿着向左浮动的盒子的右边、向右浮动的盒子的左边依次放置。

浮动的盒子将会向左或向右移动,直到触碰到包含块的边界或者其他浮动盒子的外边界。如果是行盒子的话,那么浮动盒子的外边界的顶部将与当前行盒子的顶部对其。如果没有足够的水平空间,那么浮动的盒子将移至下一行直到有足够的空间或者行内已经没有其他浮动元素为止。

因为浮动盒子不在文档流中,所以在浮动盒子前后的未定位的块盒子将像浮动盒子不存在一样的依次竖直放置。但是,浮动盒子所在的当前行以及后面相邻的行盒子都会根据浮动盒子缩短宽度来给浮动盒子留下空间。如果有个竖直的位置满足如下四个条件:

  1. 在行盒子的顶部或者顶部之下;
  2. 在行盒子的底部或底部之上;
  3. 在浮动盒子的外边界的顶部或者顶部之下;
  4. 在浮动盒子的外边界的底部或者底部之上;
    那么行盒子将会换行。也就是说:如果浮动的盒子的外边界高度为0或者为负,那么行盒子不会缩短。

如果缩短的行盒子太短而不能包含任何内容,那么这个行盒子将会换行(并且其高度会重新计算)直到有足够的空间或者没有浮动盒子为止。当前行内的任何在浮动盒子之前的盒子都将重新流动到浮动盒子的另一边。换句话说:如果一个行内盒子放在了一个向左浮动盒子的前面,那么,向左浮动的盒子会被放在这一行的开始,与行盒子的顶部对其,之前的行内盒子将会移动到浮动盒子的右边。对于rtl和向右浮动的盒子同理。

table、块级可替换元素或者正常文档流中建立新的块格式化上下文的元素的border盒不能与任何在同一个格式化上下文中的浮动盒子的margin盒重叠。

4.1 float属性

float属性的取值范围是: left | right | none | inherit,初始值为none。该属性值决定元素向左移动还是向右移,或者根本不动。float属性可以被应用于任何元素上,除了绝对定位的元素。float属性的取值有如下含义:

如下9条规定了浮动元素的确切行为:

  1. 向左浮动的盒子的外左边界不能超过包含块的左边界。同理应用于向右浮动的盒子;
  2. 对于一个向左浮动的盒子,如果在这个盒子之前还有其他向左浮动的盒子,那么,这个盒子的左外边界不能超过其他任何向左浮动的盒子的右外边界,或者这个盒子的上边界必须比其他盒子的下边界低。同理应用于向右浮动的盒子;
  3. 任何向左浮动的盒子的右外边界不能超过任何与之相邻的向右浮动的盒子的左外边界。同理应用于向右浮动的盒子;
  4. 浮动盒子的上外边界不能比包含块的上边界高。当浮动发生在两个合并的margin中时,浮动的盒子根据一个假设的父的空匿名块盒子定位;
  5. 浮动盒子的上外边界不能比任何其他之前的块盒子或浮动盒子的上外边界高;
  6. 浮动盒子的上外边界不能比任何之前的行盒子的上边界高;
  7. 一个向左浮动的盒子,如果在他之前还有向左浮动的盒子,那么这个盒子的右外边界不能超过包含块的有边界,除非这个盒子已经尽可能的向左了。同理应用于向右浮动的盒子;
  8. 浮动元素要尽可能的往高放置;
  9. 向左浮动的盒子要尽可能向左,向右浮动的盒子要尽可能向右。但是相对于尽可能向左或向右,更高的位置有更高的优先级;

5. 绝对定位

在绝对定位模型中,盒子被从正常文档流中完全移除,并只相对于它的包含块进行偏移定位。绝对定位的盒子会为它的正常文档流后代盒子以及非fixed的绝对定位后代盒子建立一个包含块。绝对定位的盒子可能会遮盖其他元素,具体取决于堆叠层次。

固定布局:
固定布局是绝对布局的一个子类,唯一的不同在于固定布局的盒子的包含块由视口产生。

6. display、position和float的关系

这三个属性都影响盒子的产生以及定位,他们关系如下:

  1. 如果display的值为none,那么position和float不起作用。在这种情况下,元素不产生盒子;
  2. 否则,如果position的值为absolute或者fixed,那么盒子就使用绝对定位,float的最终使用的值为none,display的取值依据如下表格来定。盒子的显示位置根据top、right、bottom和left属性决定;
  3. 否则,如果float的取值不会none,那么盒子将会浮动,display的取值参照下表;
  4. 否则,如果元素是根元素,那么display的取值参照下表;
  5. 否则,display的取值就是指定的值。

display的转换表

指定的值 最终使用的值
inline-table table
inline, table-row-group, table-column, table-column-group, table-header-group, table-footer-group, table-row, table-cell, table-caption, inline-block block
其他 与指定的值相同
上一篇 下一篇

猜你喜欢

热点阅读