理解css2.1中的position

理解相对定位 绝对定位 固定定位

css2.1中的定位方案

在css2.1中一共有3种定位方案:

  1. normal-flow 文档流,分水平和垂直两个布局上下文
  2. float 浮动,让元素脱离normal-flow里面的IFC
  3. absolute position 绝对定位,position: abosluteposition: fixed都属于它

另外relative postion是同时可应用于normal-flowfloat的定位形式,所以没有单独作为一个分类。

position property

position这个属性,可用于设置元素的定位方式,它的定义如下:

Value: static | relative | absolute | fixed | inherit
初始值: static
可应用于: 所有元素
是否能被继承: no
Percentages: 不支持百分比

各个含义如下:

  • static 这是position的默认值,元素按默认的normal-layout进行布局。与position相关的四个偏移属性:top left right bottomposition:static时无效。
  • relative 这个可以开启相对定位。boxnormal layout中的布局出来的位置,称为normal positionrelative可以让box,相对normal position进行偏移,利用top left rigth bottom这四个偏移属性。当一个box开启relative并且进行偏移之后,对其它在normal-layout中的元素布局没有任何影响,其它元素就好像这个box没有偏移过一样;所以relative可能会导致box与其它box发生重叠。relativedisplaytable-row-group, table-header-group, table-footer-group, table-row, table-column-group, table-column, table-cell, and table-caption的元素无效。
  • absolute 这个可以开启绝对定位。它会让box脱离normal layout,注意这里它是完全脱离normal layout,不像float(不会完全脱离BFC)。然后可以使用四个偏移属性top left rigth bottombox偏移,偏移是相对于containing block进行的。absolutebox不会与任何margin发生合并。所以margin可以用在absolute的元素上实现一些特殊效果,为啥?因为margin能改变元素的位置,对元素实现拉扯定位。
  • fixed 这个也是绝对定位,是一种特殊的绝对定位,它在偏移时是相对视口viewport进行的,对网页来说,这个视口一般指的的就是网页的可视区域。fixedbox的定位位置不会受网页滚动的影响。

box offset

relative absolute fixed都可以对box进行偏移(offset),偏移用到四个css属性:top left rigth bottom。各个属性定义如下:

  • top

    Value: <length> | <percentage> | auto | inherit
    初始值: auto
    应用于: 所有元素
    是否可被继承: 不
    百分比: 支持百分比,相对于containing blockheight计算
    负值:允许

当元素是absolute | fixed定位时,这个属性定义了boxtop margin edgecontaining block上边的距离;当元素是relative时,这个属性定义了boxtop margin edge与它在normal flow中或float时的top margin edge的距离。

  • bottom

    Value: <length> | <percentage> | auto | inherit
    初始值: auto
    应用于: 所有元素
    是否可被继承: 不
    百分比: 支持百分比,相对于containing blockheight计算
    负值:允许

当元素是absolute | fixed定位时,这个属性定义了boxbottom margin edgecontaining block下边的距离;当元素是relative时,这个属性定义了boxbottom margin edge与它在normal flow中或float时的bottom margin edge的距离。

  • left

    Value: <length> | <percentage> | auto | inherit
    初始值: auto
    应用于: 所有元素
    是否可被继承: 不
    百分比: 支持百分比,相对于containing blockwidth计算
    负值:允许

当元素是absolute | fixed定位时,这个属性定义了boxleft margin edgecontaining block左边的距离;当元素是relative时,这个属性定义了boxleft margin edge与它在normal flow中或float时的left margin edge的距离。

  • right

    Value: <length> | <percentage> | auto | inherit
    初始值: auto
    应用于: 所有元素
    是否可被继承: 不
    百分比: 支持百分比,相对于containing blockwidth计算
    负值:允许

当元素是absolute | fixed定位时,这个属性定义了boxright margin edgecontaining block右边的距离;当元素是relative时,这个属性定义了boxright margin edge与它在normal flow中或float时的right margin edge的距离。

其它要点:

  1. 这四个属性都允许负值,好多网页布局都要利用它们的负值
  2. 百分比都是相对containing block的宽高计算,包括relative。不要认为relative的偏移百分比值是相对于自身计算。
  3. auto这个特殊值的逻辑,需要其它内容。

relative positioning

相对定位要点。

relative可以对normal layout中的boxfloat box生效。box可以利用四个偏移属性,对boxrelative之前的位置进行偏移,被relativebox在发生偏移后,对其它box的布局不会有任何影响,其它box就好像这个box没有移动过一样。所以relative可能会造成box的重叠。但是有一种情况,可能会因为relative影响布局:当boxrelative后可能会导致有设置overflow: scrolloverflow:autobox发生溢出,浏览器需要保证溢出后,还能与这些溢出的relative box交互,就会通过创建滚动条的方式来满足这点要求,滚动条会影响布局,因为滚动条要占据空间。

relative box偏移后,box的尺寸大小不会受影响。

leftright属性,只是将box水平移动,但是不会改变box大小。正的leftbox往右偏移,负的leftbox往左偏移;反之,正的rightbox往左偏移,负的rightbox往右偏移;由于box不会因为left right而分割或拉伸,所以它们始终要满足这个关系:left=-right

  • leftright都是auto的时候,auto是默认值,这两个属性最终被使用的值都是:0
  • 如果一个是auto,另一个不是,则另一个根据left=-right自动计算出一个值;
  • 如果两个都不是auto,则会发生冲突,其中一个会被忽略,然后用left=-right计算一个新值。谁被舍弃,取决于containing blockdirection这个属性。当direction:ltr时,表示从从到右的布局方向,right会被舍弃;当direction:rtl,时,表示从右到左的布局方向,left会被舍弃。

topbottom属性,只是将box垂直移动,但是不会改变box大小。基本跟left right大同小异,且满足:top=-bottom。有一点不同的是:

  • topbottom都不是auto的时候,始终是bottom被忽略,然后bottom = -top来得到一个新的bottom值。

absolute positioning

在绝对定位中,box是相对于它的containing block进行偏移的。它可以同时使用top right left bottom四个属性来指定偏移量,top bottomleft right之间同时设定的话,会对box进行拉伸,所以不存在类似relative那样的牵制关系。

元素绝对定位后,会完全从normal flow中脱离出来,并新建一个BFC来布局子内容。绝对定位的box会与其它box发生重叠,他们的堆叠顺序,可以通过stack level也就是z-index属性来控制。

fixed positioning

固定定位就是一种特殊的绝对定位,只不过box偏移的containing blockviewport本身。

什么是containing block

在css2.1里面,很多的box位置和大小都是根据一个矩形区域的边缘来计算的,这个矩形区域称为containing block。一般情况下,都是box充当后代boxescontaining block,我们说它是一个box为它的后代创建了containing block。 一个boxcontaining block,是指它布局所在的那个块,不是指它生成的那个块。

每一个box都会有一个相对于它所在的containing blockposition值(x,y坐标),但是containing block不会限制box的显示,所以box可能会溢出。

containing block具体的定义是什么呢,分以下几种情况:

  • 根元素html所在的containg block称为initial containing block,对网页来说这个containing blockview port大小一致,而且固定在canvas的原点
  • 对于position: relativeposition: staticbox,它所在的containing block就是离它最近的一个block containercontent box区域
  • 对于position: fixedbox,它的containing block就可以看作是view port
  • 对于position: absoultebox,需要先找离它最近的一个祖先元素,并且这个祖先元素的position设置为了relative or absolute or fixed,如果找到了则这个元素的padding box就是这个boxcontaining block,如果没找到,这个boxcontaining block就是initial containing block

总结:containg block不是一个box,只是一个矩形区域,但它一般都是从某个box上拆分出来的,它可能是一个boxcontent box,或者是一个boxpadding box,或者是跟view port相关的一个视觉区域。