✍CSS 格式化上下文

🔥1 格式化上下文

FC 的全称是: Formatting Contexts,是 W3C CSS2.1 规范中的一个概念。

它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。

🌷1.1 块级格式化上下文(BFC)

BFC(Block Formatting Contexts) 直译为"块级格式化上下文"。Block Formatting Contexts 就是页面上的一个隔离的渲染区域,容器里面的子元素不会在布局上影响到外面的元素,反之也是如此。

🌷1.2 内联格式化上下文(IFC)

IFC(Inline Formatting Contexts) 直译为"内联格式化上下文", IFC 的 line box (线框) 高度由其包含行内元素中最高的实际高度计算而来 (不受到竖直方向的 padding/margin 影响)。

  • 行内元素不能设置竖直方向的 padding/margin,无效;只能设置水平

IFC 中的 line box 一般左右都贴紧整个 IFC,但是会因为 float 元素而扰乱。float 元素会位于 IFC 与与 line box 之间,便得 line box 宽度缩短。同个 IFC 下的多个 line box 高度会不同。

🌷1.3 自适应格式化上下文(FFC )

FFC (Flex Formatting Contexts) 直译为"自适应格式化上下文",display 值为 flex 或者 inline-flex 的元素将会生成自适应容器(flex container) ,Flex Box 由伸缩容器和伸缩项目组成。

通过设置元素的 display 属性为 flex 或 inline-flex 可以得到一个伸缩容器。设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。

简单地说, Flexbox 定义了伸缩容器内伸缩项目该如何布局。

🌷1.4 网格布局格式化上下文(GFC)

GFC(GridLayout Formatting Contexts)直译为"网格布局格式化上下文",当为一个元素设置 display 值为 grid 或者 inline-grid 的时候,此元素将会获得一个独立的渲染区域,我们可以通过在网格容器 (grid container) 上定义网格定义行(griddefinition rows) 和网格定义列 (grid definition columns) 属性各在网格项目 (grid item) 上定义网格行(gridrow) 和网格列 (grid columns)为每一个网格项目(grid item)定义位置和空间。

GFC和FFC有什么区别:

  • GFC是二维网格,理解成一个table。在后续学习过程我们会理解得更深刻,初学可以直接理解成table。
  • FFC是一维,flex-warp

🔥2 BFC 形成条件

  • html根元素

  • float 属性不为 none,只要开启浮动

    • 也就是为什么开启浮动后,元素会自动变成块级block,表现形式和行内块类似
  • position 为 absolute 或 fixed

    • 元素会自动变成块级block,表现形式和行内块类似
  • display 为 inline-block

    • 直接变成行内块
  • overflow 不为 visible ( hidden、auto、scroll )。

    • 必须可以给它设置一个宽度/高度,给block元素直接加上overflow
    • 给block元素设置overflow来开启BFC
    • 如果想让body触发BFC,那么同时直接设置html、body都不为 visible

BFC形成一个完全独立的盒子,盒子中的子元素与外部元素隔绝开来,不管内部元素怎么布局,都不会影响到外部,可以理解内部形成一个独立的文档流。

🔥3 BFC 特性

BFC 布局规则特性:

  1. 在 BFC 中,盒子从顶端开始垂直地一个接一个地排列,文档流的排列顺序,从上到下
  2. 盒子垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻盒子的 margin 会发生重叠
  3. 在 BFC 中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left),从左到右
  4. BFC 的区域不会与浮动盒子产生交集,而是紧贴浮动边缘
  5. 计算 BFC 的高度时,自然也会检测浮动的盒子高度。从而消除浮动子元素的影响。

它是一个独立的渲染区域,只有 Block-level box 参与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。

🔥4 BFC 的主要用途

清除浮动影响

处理外边距穿透&合并

实现两栏、三栏自适应布局

🔥5 html扩散行为

关于html、body设置overflow:hidden扩散问题,body的overflow会受到html的overflow扩散影响。

html只会扩散overflow的默认值给body。

结论1:给body加上overflow:hidden,无法触发BFC创建。

解释1:本用例中body {overflow:hidden} html {overflow: visible}(html为默认overflow),body的overflow:hidden被应用于视口,body的最终使用值为overflow:visible,因此body没有创建BFC。

结论2:给body和html同时加上overflow:hidden,成功触发BFC创建。

解释2:本用例中body, html{overflow:hidden},html的overflow:hidden被用于视口,body的overflow计算值是hidden,因此创建了BFC。

结论3:给body加上display:inline-block、position:absolute,float成功触发BFC创建。

解释3:这些属性都导致body正常创建了BFC。



✍CSS兼容处理

不同的用户会通过不同的浏览器访问我们的网站, 我们需要针对绝大部分主流用户浏览器进行兼容处理 . 兼容处理主要包括两种方案(优雅降级, 渐进增强) 和两种 技巧(前缀兼容与 HACK 兼容)

  • postcss(含盖很多兼容处理方案)
  • 特别复杂的业务,一般不会涉及太多的兼容性问题
  • 简单的业务,内容管理系统

🔥1 邀请用户升级浏览器

这种方式目前比较普遍 , 在用户通过老版浏览器登录网站的时候 通过服务判断用户 浏览器版本内核 从而返回升级页面. 省时省力 但是对用户不够友好

CSS 格式化上下文 + CSS兼容处理-LMLPHP

广东省住房和城乡建设厅网站:http://zfcxjst.gd.gov.cn/,切换IE9访问:

CSS 格式化上下文 + CSS兼容处理-LMLPHP

🔥2 meta 强制解析模式

x-ua-compatible 用来指定 IE 浏览器解析编译页面的 model

x-ua-compatible 头标签大小写不敏感,必须用在 head 中,必须在除 title 外的其他 meta 之前使用。

使用一行代码来指定浏览器使用特定的文档模式

<meta http-equiv="x-ua-compatible" content="IE=9" />
<meta http-equiv="x-ua-compatible" content="IE=8" />
<meta http-equiv="x-ua-compatible" content="IE=7" />
2、在一些情况下,我们需要限定浏览器对文档的解析到某一特定版本,或者将浏览器限定到一些旧版本的表现中。可以用如下的方式:
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE9" />
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE8" />
<meta http-equiv="x-ua-compatible" content="IE=EmulateIE7" />
使用这种写法,浏览器或者使用标准模式进行解析,或者使用 IE5 Quirks 模式进行解析。
3、为了测试,我们也可以使用下面的语句指定浏览器按照最高的标准模式解析页面。
<meta http-equiv="X-UA-Compatible" content="IE=edge">
4、多个模式的指定。我们可以用逗号分割多个版本,这种情况下,浏览器会从这个列表中选择一个他所支持的最高版本来使用标准模式进行渲染。如下面的例子,在IE8进行浏览时,将会使用IE7的标准模式进行渲染,因为他本身不支持IE9和IE10。
<meta http-equiv="x-ua-compatible" content="IE=7,9,10" />

目前最实用的最新写法为

<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
X-UA-Compatible定义浏览器的渲染方式; 如果存在客户端Chrome
Frame并启用,那么浏览器访问页面会被Chrome内核渲染(这一点没太大意义,因为你开发的项目不能要求用户在客户端来安装Chrome
Frame);也就是说IE浏览器变身Chrome是可以的,但前提是客户端安装了Chrome Frame
使用IE内核浏览器来访问,会渲染至该浏览器的最高版本,比如你使用IE9浏览器,那么就算在兼容模式切换至IE7,但仍会渲染成IE9的样子(当然IE7浏览器是不会渲染成IE9的,不然想想都好美丽)。

对多核浏览器(360 搜狗)等进行强制指定渲染内核

http://se.360.cn/v6/help/meta.html

<meta name="renderer" content="webkit|ie-comp|ie-stand" />
//content的取值为webkit,ie-comp,ie-stand之一,区分大小写,分别代表用webkit内核,IE兼容内核,IE标准内核。
//若页面需默认用极速核,增加标签
<meta name="renderer" content="webkit" />
//若页面需默认用ie兼容内核,增加标签:
<meta name="renderer" content="ie-comp" />
// 若页面需默认用ie标准内核,增加标签:
<meta name="renderer" content="ie-stand" />

🔥3 兼容前缀

不同浏览器因为内核不同,针对同一条 css 属性的兼容支持程度也不同,我们可以通过加 兼容前缀的方式 让一些标准样式在浏览器内可以使用。

使用方式:

如果 css 样式在主流浏览器中需要加兼容前缀才能生效, 就先写兼容写法 最后写标准写法。

.selector {
  -moz-box-shadow: 2px 2px 5px #969696; /*firefox*/
  -webkit-box-shadow: 2px 2px 5px #969696; /*webkit*/
  box-shadow: 2px 2px 5px #969696; /*opera或ie9*/
}

关于 chrome 浏览器内核小知识:

chrome 的内核确切的 bai 说是 Chromium 引擎,它是使用苹果公司的 WebKit 作为浏览器内核 du 原型,是 WebKit 内核的 zhi 一个分支。

Chromium 引擎虽然是属于 WebKit 的分支,却把 WebKit 的代码梳理得可读性提高很多,所以以前可能需要一天进行编译的代码,现在只要两个小时就能搞定。因此 Chromium 引擎和其它基于 WebKit 的引擎所渲染页面的效果也是有出入的。基于以上原因,有的地方会把 Chromium 引擎跟 WebKit 区分开来,有的地方则直接把 Chromium 引擎归为 WebKit 都是可以的。

关于国内浏览器内核小知识:

国内浏览器内核基本为 webkit 内核或 chrominm 引擎内核 拼接 Edge 或 IE 内核形成 , 比如 360 浏览器就有内核切换模式, 针对 css 属性规则上都直接沿用了 webkit 内核规则, 所以国内开发以 chrome 为开发浏览器也是考虑这层原因。

🌷3.1 兼容查询

学会利用工具网站 查询样式在各个浏览器的兼容情况,从而选择更合适的方案。

🔫3.1.1 工具网站

地址:https://www.caniuse.com/

使用方法:

1、在输入框输入需要查询兼容性的 样式属性

CSS 格式化上下文 + CSS兼容处理-LMLPHP

2、查看下方浏览器兼容表

CSS 格式化上下文 + CSS兼容处理-LMLPHP

表头为不同的浏览器品牌 主要查看 IE Edge firefox chrome safari opera 这几个主流浏览器的兼容情况

倒数第二行是当前用户主流浏览器版本,以黑色背景包裹。为主要兼容参考

一般我们只看倒数三行的兼容情况

红色标签代表 完全不兼容

绿色标签代表 完全兼容

黄色标签代表 兼容但需要加 兼容方案

🔫3.1.2 兼容方案

鼠标移入黄色版本的标签会提示兼容方案

CSS 格式化上下文 + CSS兼容处理-LMLPHP

鼠标移入 绿色标签 (左上角有黄色图标) 时会提示添加对应的兼容前缀

CSS 格式化上下文 + CSS兼容处理-LMLPHP

随着发展 css 的兼容性会越来越好 目前绝大部分 css 属性都是主流浏览器全兼容, CSS3 样式大部分兼容 IE8 以上大部分浏览器。

🌷3.2 HACK 兼容

hack 兼容方式主要应对老版本 IE 浏览器(IE6 IE7 IE8 IE9) 进行单独样式处理

由于不同的浏览器对 CSS 的支持及解析结果不一样,还由于 CSS 中的优先级的关系。我们就可以根据这个来针对不同的浏览器来写不同的 CSS。

CSS Hack 大致有 3 种表现形式,CSS 类内部 Hack、选择器 Hack 以及 HTML 头部引用(if IE)Hack,CSS Hack 主要针对 IE 浏览器。  类内部 Hack:比如 IE6 能识别下划线"“和星号” * “,IE7 能识别星号” * “,但不能识别下划线”",而 firefox 两个都不能认识。等等

选择器 Hack:比如 IE6 能识别html .class{},IE7 能识别+html .class{}或者*:first-child+html .class{}。等等

HTML 头部引用(if IE)Hack:针对所有 IE:<!–[if IE]> <![endif]–>,针对 IE6 及以下版本:<!–[if lt IE 7]> <[endif]–>这类 Hack 不仅对 CSS 生效,对写在判断语句里面的所有代码都会生效。

书写顺序,一般是将识别能力强的浏览器的 CSS 写在后面。这里进行简单举例 资料后配一份 hack 常见兼容处理方案(虽然对于当前开发环境来说基本用不上).

条件注释法:

属性前缀法:

说明:在标准模式中

  • “-″减号是 IE6 专有的 hack
  • “\9″ IE6/IE7/IE8/IE9/IE10 都生效
  • “\0″ IE8/IE9/IE10 都生效,是 IE8/9/10 的 hack
  • “\9\0″ 只对 IE9/IE10 生效,是 IE9/10 的 hack
.selector {
  background-color: red; /* 所有浏览器 */
  background-color: blue !important; /* 除了ie6的浏览器 */
  *background-color: black; /* IE6, IE7 */
  +background-color: yellow; /* IE6, IE7*/
  background-color: gray\9; /* IE6, IE7, IE8, IE9, IE10 */
  background-color: purple\0; /* IE8, IE9, IE10 */
  background-color: orange\9\0; /*IE9, IE10*/
  _background-color: green; /* 只有IE6生效 */
  *+background-color: pink; /*  只有IE7生效 具体小版本有差别 */
}

选择器前缀法:

*html *前缀只对 IE6 生效*

+html *+前缀只对 IE7 生效

@media \0screen {body { background: red; }}只对 IE8 有效

@media \0screen,screen\9{body { background: blue; }}只对 IE6/7/8 有效

@media screen\0 {body { background: green; }} 只对 IE8/9/10 有效

@media screen and (min-width:0\0) {body { background: gray; }} 只对 IE9/10 有效

@media screen and (-ms-high-contrast: active), (-ms-high-contrast: none) {body { background: orange; }} 只对 IE10 有效等等

示例代码:

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8" />
    <!-- <meta http-equiv="X-UA-Compatible" content="IE=edge" /> -->
    <meta http-equiv="x-ua-compatible" content="IE=9" />
    <title>Document</title>
    <style>
      .box {
        width: 500px;
        height: 300px;
        margin: 30px auto 0;
        border: 1px solid black;
        -webkit-transform: rotate(75deg);
        -ms-transform: rotate(45deg);
        transform: rotate(60deg);
        background-color: red; /* 所有浏览器 */
        *background-color: black; /* IE6, IE7 */
        +background-color: yellow; /* IE6, IE7*/
        background-color: gray\9; /* IE6, IE7, IE8, IE9, IE10 */
        background-color: purple\0; /* IE8, IE9, IE10 */
        background-color: orange\9\0; /*IE9, IE10*/
        _background-color: green; /* 只有IE6生效 */
        *+background-color: pink; /*  只有IE7生效 具体小版本有差别 */
      }
    </style>
  </head>
  <body>
    <div class="box"></div>

  </body>
</html>

🔥4 优雅降级和渐进增强(取决于需求)

什么是渐进增强(progressive enhancement)、优雅降级(graceful degradation)呢?

渐进增强 progressive enhancement:

针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

农村包围城市的味道

先说一个简单的例子,例如先完成了页面的基本布局,没有任何特效,那么加个小动画,加个文字阴影等,就是渐进增强

优雅降级 graceful degradation:

一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

类似蹦极,由高处往低处下落

让一部分人先富起来带动另一部分人富起来的感觉

区别:渐进增强是向上兼容,优雅降级是向下兼容。

建议: 现在互联网发展很快, 连微软公司都抛弃了 ie 浏览器,转而支持 edge 这样的高版本浏览器,我们很多情况下没有必要再时刻想着低版本浏览器了,而是一开始就构建完整的效果,根据实际情况,修补低版本浏览器问题。

推荐使用:优雅降级。

04-19 11:56