css总结

以下文章是我在网上收集的内容,为了记录自己的学习以及为了以后不到处找而记录下来,如果对你有用,请感谢写这些文章的前辈(特别是张鑫旭前辈),这些内容肯定还有一些地方排版不好,比较粗糙,如果你对这个有建议的话,欢迎评论

BFC和IFC:
要想理解它们,必须首先理解FC,即 Formatting Context,它是W3C CSS2.1规范中的一个概念,定义的是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用

常见的Formatting Context 有:Block Formatting Context(BFC | 块级格式化上下文) 和 Inline Formatting Context(IFC |行内格式化上下文),当然还有GridLayout Formatting Contexts(GFC |网格布局格式化上下文 )、Flex Formatting Contexts(FFC | 自适应格式化上下文)分别对应flex布局和grid布局,今天的主角是BFC、IFC,如果想了解GFC、FFC,可以自行查阅资料。

BFC布局规则:

  1. 内部的Box会在垂直方向,一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  3. 每个元素的左外边缘(margin-left), 与包含块的左边(border-left)相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。除非这个元素自己形成了一个新的BFC。
  4. BFC的区域不会与float box重叠。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  6. 计算BFC的高度时,浮动元素也参与计算

怎样形成一个BFC?

  1. 根元素或其它包含它的元素
  2. 浮动 (元素的 float 不是 none)
  3. 绝对定位的元素 (元素具有 position 为 absolute 或 fixed)
  4. 元素具有 display: inline-block,table-cell, table-caption, flex, inline-flex
  5. 块元素具有overflow ,且值不是 visible

用途:

  • 清除浮动,子元素浮动,由于浮动破坏了正常的line boxes(ps:后面会讲),父元素没有了高度,导致高度塌陷,此时让父元素形成BFC,按照上述BFC第六条规则,即可达到清除浮动的效果。
    demo
  • 自适应两栏布局
    demo
  • 防止垂直margin合并(mdn)
    demo

IFC
IFC的line box(线框)高度由其包含行内元素中最高的实际高度计算而来(不受到竖直方向的padding/margin影响)

IFC布局规则:

  • 框会从包含块的顶部开始,一个接一个地水平摆放。
  • 摆放这些框的时候,它们在水平方向上的外边距、边框、内边距所占用的空间都会被考虑在内。在垂直方向上,这些框可能会以不同形式来对齐:它们可能会把底部或顶部对齐,也可能把其内部的文本基线对齐。能把在一行上的框都完全包含进去的一个矩形区域,被称为该行的行框。水平的margin、padding、border有效,垂直无效。不能指定宽高。
  • 行框的宽度是由包含块和存在的浮动来决定

IFC的 ‘line-height’ 与 ‘vertical-align’ 属性以及基线:
介绍这些之前,我们先来张看一段代码

<p>left<em>emem</em>right</p>

不要以为这段代码简单,他居然丧心病狂的涵盖了四个内容:

  1. 内容区域(content-area) 是一种围绕文字看不见的盒子,它的大小跟font-size有关,可以理解成选中文字时的样子
  2. 内联盒子(inline-boxes),他不会让内容成块显示,而是排成一行,<em>emem</em>,如果文字外部出现em、a等内联元素,则属于内联盒子,如果是光秃秃文字就是匿名内联盒子,比如left/right
  3. 行框盒子(line-boxes)每一行就是一个行框盒子,它由一个个内联盒子组成,比如left<em>emem</em>right
  4. p所在的包含盒子(containing-box),此盒子由一个个行框盒子组成,例如<p>left<em>emem</em>right</p>



    line-box 的高度是根据子元素的高度计算出来的,而不是子元素的 content-area 的高度,content-area 的高度是由字体度量定义的,virtual-area 和 content-area 高度的差异叫做 leading。leading 的一半会被加到 content-area 顶部,另一半会被加到底部。因此 content-area 总是处于 virtual-area 的中间,计算出来的 line-height(也就是 virtual-area 的高度)可以等于、大于或小于 content-area。如果 virtual-area 小于 content-area,那么 leading 就是负的,因此 line-box 看起来就比内容还矮了。由于content-area 的高度是由字体度量定义的,它是可变的,所以line-height是不确定的...
    具体来说:

line-box 计算的一些细节:

  • 对于内联元素,padding 和 border 会增大 background 区域,但是不会增大 content-area(不是 line-box 的高度)。一般来说你无法再屏幕上看到 content-area。margin-top 和 margin-bottom 对两者都没有影响。
  • 对于可替换内联元素(replaced inline elements)、inline-block 元素和 blockified 内联元素,padding、margin 和 border 会增大 height,因此会影响 content-area 和 line-box 的高度,行高决定了内联元素的高度

现在你知道为什么块级元素可以设置宽高,margin、bottom,内联元素不能设置padding-top/padding-bottom。

line-height:normal;默认属性值,与用户浏览器,且与元素字体有关 在body里里面初始化,确保一致性。可以这样全局运用:

body{
  font:14px/1.4286 'microsoft yahei';
}

vertical:用来指定行内元素(inline)或表格单元格(table-cell)元素的垂直对齐方式
vertical-align的默认值就是基线,
那么什么是基线呢?

基线
基线

由一个问题开始。相信大家都碰到过一个div里面包裹一个图片,但是div不能完全包裹图片,还留有间隙,这个问题一直让人很苦恼,
说这个问题之前,我们必须知道一个一个基础知识,浏览器认为每个 line-box 的起始位置都有一个宽度为 0 的字符(CSS 文档将其称为 strut),并将其纳入 line-box 的高度的计算中,因此下次再当我们碰到一个div包裹着图片,一定要提醒自己假装里面有文字,没有也要装着有,那么为什么要知道这个呢?因为每个内联元素都是默认基线对齐,文字的基线在它的下面,由上文可知文字上下有一个1/2leading,所以文字与div有一个1/2leading,所以文字下面没有和div的border接触,所以图片为了对齐这个基线,它就不得不有个间隙!
那么怎么解决呢?无非是解决基线或者line-height(1/2leading与line-height有关)

  1. 让vertical-align失效 图片默认是inline水平的,而vertical-align对块状水平的元素无感
图片默认是inline水平的,而vertical-align对块状水平的元素无感
  1. 使用其他vertical-align值:告别baseline, 取用其他属性值,比方说bottom/middle/top都是可以的
  2. 直接修改line-height值。下面的间隙实际上是1/2leading,注意,我们可以通过改变行高改变这个值,行高足够小,实际文字占据的高度的底部就很小,下面没有了高度区域支撑,自然,图片就会有容器底边贴合在一起了。line-height:0;
  3. line-height为相对单位,font-size间接控制.font-size设置为0, 本质上还是改变line-height值。

有时候我们经常用vertical:middle:middle来居中,但是往往并没有居中,这是为什么呢?vertical:middle:middle 的意思是「用父元素 baseline 高度加上父元素中 x-height 的一半的高度来对齐当前元素的垂直方向的中点」。baseline 所处的高度跟字体有关,x-height 的高度也跟字体有关,所以 middle 对齐也不靠谱,大部分情况下,对齐的是 virtual-area,也就是一个不可见的高度。

一个inline-block元素,如果里面没有inline内联元素,或者overflow不是visible,则该元素的基线就是其margin底边缘,否则,其基线就是元素里面最后一行内联元素的基线。

说到position和float之前,先提一提.normal flow,normal flow(正常流):正常流是默认的定位方式。任何没有具体指定{position:absolute}或者{position:fixed}属性以及没有被浮动的元素都将默认获得此属性。

在这种方式里,块级元素在它们的包含块里一个一个垂直延伸,行内元素在它们的包含块里从左至右的水平排布。

值得注意的是,在正常流里垂直边距(vertical margin)是重叠的。也就是说,上下两个块级盒之间的边距由它们之中边距较大的元素决定,而不是他们的和,也就是说,外边距合并是正常现象,但是因为不符合我们的预期,所以有时候会觉得不正常。

包含块:是视觉格式化模型的一个重要概念,它与框模型类似,也可以理解为一个矩形,而这个矩形的作用是为它里面包含的元素提供一个参考,元素的尺寸和位置往往是由该元素所在的包含块决定的。也就是说一个元素盒子的位置和大小有时是通过相对于一个特定的长方形来计算的,这个长方形就被称之为元素的 containing block

一个元素的containing block按照以下方式定义:

  1. 用户代理(比如浏览器)选择根元素作为 containing block(称之为初始 containing block)。

  2. 对于其它元素,除非元素使用的是绝对位置,containing block 由最近的块级祖先元素盒子的内容边界组成。

  3. 如果元素有属性 'position:fixed',containing block 由视口建立。

  4. 如果元素有属性 'position:absolute',containing block 由最近的 position 不是 static 的祖先建立,按下面的步骤:

  5. 如果祖先是块级元素,containing block 由祖先的 padding edge 形成。

  6. 如果祖先是内联元素,containing block 取决于祖先的 direction 属性。如果 direction 是 ltr(左到右),祖先产生的第一个盒子的上、左内容边界是 containing block 的上方和左方,祖先的最后一个盒子的下、右内容边界是 containing block 的下方和右方。如果 direction 是 rtl(右到左),祖先产生的第一个盒子的上、右内容边界是 containing block 的上方和右方,祖先的最后一个盒子的下、左内容边界是 containing block 的下方和左方。

  7. 如果没有祖先,根元素盒子的内容边界确定为 containing block。

外边距合并:

  1. 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
  2. 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
  3. 两个外边距一正一负时,折叠结果是两者的相加的和

产生折叠的必备条件:margin必须是邻接的,且需要满足如下条件:

  1. 必须是处于常规文档流(非float和绝对定位)的块级盒子,并且处于同一个BFC当中。
  2. 没有线盒,没有空隙(clearance),没有padding和border将他们分隔开
  3. 都属于垂直方向上相邻的外边距,可以是下面任意一种情况:
  • 元素的margin-top与其第一个常规文档流的子元素的margin-top
  • 元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
  • height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
  • 高度为0并且最小高度也为0,不包含常规文档流的子元素,并且自身没有建立新的BFC的元素的margin-top和margin-bottom

值得注意的是,"display:table" 本身并不产生 "block formatting contexts"。但是,它可以产生匿名框, 其中包含 "display:table-cell" 的框会产生块格式化上下文。
是这些元素创建了块格式化上下文,它们本身不是块格式化上下文

float:浮动float的本意是让文字像流水一样环绕浮动元素,因此就他能实现文字环绕效果。
特性:

  • 浮动的包裹性——浮动就是个带有方位的display:inline-block属性,它与display:inline-block不同的地方在于浮动的方向性,display:inline-block仅仅一个水平排列方向,就是从左往右,而float可以从右往左排列,这就是两者的差异。然而,我们又有多少情况需要元素从右往左排列呢?很少,所以,CSS中,没有浮动这一属性不是什么大不了的事情,它其实就那么回事。
  • 浮动的破坏性——浮动破坏了正常的line boxes。文字之所以会环绕含有float属性的图片时因为浮动破坏了正常的line boxes,正常情况下,图片自身就是个inline boxes,与两侧的文字inline boxes共同组成了line boxes,但是,一旦图片加入了浮动,情况就完全变了。我认为是浮动彻底破坏了img图片的inline boxes特性,至少有一点我可以肯定,图片的inline boxes不存在了,被恶魔附体,变身了,而这个恶魔就是浮动。一旦图片失去了inline boxes特性就无法与inline boxes的文字排在一行了,其会从line boxes上脱离出来,跟随自身的方位属性,靠边排列。

在目前的CSS的世界中,所有的高度都是有两个CSS模型产生的,一个是box盒状模型,对应CSS为”height+padding+margin”,另外一个是line box模型,对应样式为”line-height”。前者的height属性分为明显的height值和隐藏的height值,所谓隐藏的height值是指图片的高度,一旦载入一张图片,其内在的height值就会起作用,即使您看不到”height”这个词。而后者针对于文字等这类inline boxes的元素(图片也属于inline boxes,但其height比line-height作用更凶猛,故其inline boxes高度等于其自身高度,对line-height无反应),inline boxes的高度直接受line-height控制(改变line-height文字拉开或重叠就是这个原因),而真正的高度表现则是由每行众多的inline boxes组成的line boxes(等于内部最高的inline box的高度),而这些line boxes的高度垂直堆叠形成了containing box的高度,也就是我们见到的div或是p标签之类的高度了。所以,对于line box模型的元素而言,没有inline boxes,就没有高度了,而浮动却恰恰做了这么龌龊的事情,其直接将元素的inline boxes也破坏了,于是这些元素也就没有了高度。

浮动破坏了图片的inline box,产生了两个结果:一是图片无法与文字同行显示,脱离了其原来所在的line box链;二是没有了高度(无inline box -> 无line box -> 无高度)。而这些结果恰恰是文字环绕图片显示所必须的。
我们可以拿浮动元素与绝对定位元素做对比或许可以帮助理解。与浮动元素一样,绝对定位元素也具有“包裹性”,此“包裹性”适用于任何元素。那么,浮动元素与绝对定位元素的差别在哪里呢?我觉得最主要的差别在于:绝对定位的元素脱离了文档流,而浮动元素依旧在文档流中;而这造成的显示上的差异就是:同处于文档流中的文字实体不会与浮动元素重叠,而会与绝对定位元素重叠。这就是文字环绕显示的重要原因之一:虽然图片实际占据的高度为0,但是由于其宽度实体存在(包裹性),同样是content area 实体的文字不会与之重叠(外部的容器盒子containing box(p,div,ul,li)会重叠

absolute:position:absolute与float:left两者有两大共性:包裹性,破坏性。
包裹性换种说法就是让元素inline-block化,例如一个div标签默认宽度是100%显示的,但是一旦被absolute属性缠上,则100%默认宽度就会变成自适应内部元素的宽度

破坏性:float是欺骗父元素,让其父元素误以为其高度塌陷了,但float元素本身仍处于文档流中,文字会环绕着float元素,不会被遮蔽,但absolute其实已经不能算是欺骗父元素了,而是出现了层级关系。如果处于正常的文档流中的父元素算是凡人的话,那absolute已经得道成仙,用现在的话说已经不在一个次元上。从父元素的视点看,设成absolute的图片已经完全消失不见了,因此从最左边开始显示文字。而absolute的层级高,所以图片遮盖了文字

relative:relative主要用于限制absolute,如果absolute元素没有position:static以外的父元素,那将相对body定位,天空才是它的极限。而一旦父元素被设为relative,那absolute子元素将相对于其父元素定位,就好像一只脚上被绑了绳子的鸟

z-index:以下情况根本不需要设z-index:

  1. 让absolute元素覆盖正常文档流内元素(不用设z-index,自然覆盖)
  2. 让后一个absolute元素覆盖前一个absolute元素(不用设z-index,只要在HTML端正确设置元素顺序即可)

那什么时候需要设置z-index呢?当absolute元素覆盖另一个absolute元素,且HTML端不方便调整DOM的先后顺序时,需要设置z-index: 1。非常少见的情况下多个absolute交错覆盖,或者需要显示最高层次的模态对话框时,可以设置z-index > 1.

relative,absolute,fixed的区别:

  1. 绝对定位和浮动都会产生包裹性。block元素不指定width的话,默认是100%,一旦让该div浮动起来,立刻会像inline元素一样产生包裹性,宽度会跟随内容自适应。(这也是通常float元素需要手动指定width的原因)
  2. relative:生成相对定位的元素,相对于其正常位置进行定位。
  • 元素的位置通过left、right、top、button属性进行规定, 可以通过z-index进行层次分级。
  • 元素仍保持其未定位前的形状,原本所占的空间仍将保留。
  • 如果没有定位偏移量,对元素本身没有任何影响
  1. absolute:生成绝对定位元素。使元素脱离文档流,并相对于其包含块进行定位,包含块可能是文档中的另一个元素或者是初始包含块。
  • 元素原先在正常文档流中所占的空间会被后面元素占据;

  • 元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框;

  • 设置了absolute一定要设置left或者top,否则他就按照文档流的默认位置(auto),若同时设置top/bottom或者left/right,那么只有top或者left有效

  • 绝对定位元素的包含块由离它最近的 ‘position’ 属性为 ‘absolute’、’relative’ 或者 ‘fixed’ 的祖先元素创建。只要父级元素设置了position并且不是static(默认既是static),那么设定了absolute的子元素即以此为包含块(最近的)。如果都没有定义,那么就相对于整个文档body定位(注意不是相对于浏览器窗口定位)

  • 相对定位一般都是配合绝对定位元素使用。

  1. fixed:生成绝对定位元素,相对于浏览器窗口(viewport)的定位。通常配合z-index一起来使用。比如说网页上悬挂的聊天图标或者广告就是用了fixed

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 10,158评论 1 88
  • 1、样式种类:浏览器默认样式、带有样式的标签、内联样式、style标签、link引入样式文件。2、选择器(http...
    Mystic_1阅读 266评论 0 4
  • 复习完CSS后总结一下,首先看一下CSS的一个体系结构图: 大体上分为这八个部分,参考一下vivijind的css...
    苏敏阅读 122评论 0 3
  • 图片引入标签: 超链接标签: 百度 base标签: base标签可以给页面的链接加上默认的路径,或者默认的打开方式...
    钱钱_e3a6阅读 50评论 0 0
  • 凝听着6月的风雨声, 眨眼我便27岁, 在英国的时候我很渴望能快点回国, 因为心里不断在回味根的感觉。 直到回国后...
    莒箬小姐阅读 43评论 1 1