# 🌵 CSS

# 001: CSS 盒模型有几种类型?他们之间怎么转换?

HTML 中的每个元素都可以看成一个矩形,这个矩形通过一个盒子模型来描述它。

CSS 盒子模型有两种:W3C 标准盒子模型和 IE 盒子模型,可通过 CSS 属性 box-sizing 进行切换。

# W3C 标准盒模型(box-sizing: content-box

W3C 标准属性 width / height 只包含内容 content,不包含 border 和 padding,即:

width = content width;

height = content height;

# IE 盒模型(box-sizing: border-box

IE 盒模型属性 width / height 包含了内容 content,border 和 padding,即:

width = content width + padding (left & right) + border (left & right);

height = content height + padding (top & bottom) + border (top & bottom);

CSS 盒模型由 content、padding、bottom 和 margin 组成,但 CSS 盒模型的大小仅有 content、padding、bottom 决定,算上 margin 是 CSS 盒模型占据位置的大小,而不是盒子的大小!

有时候在元素基础上添加内距 padding 或 border 会将布局撑破,在页面中声明 box-sizing: border-box 就可避免这种情况,而且使用 box-sizing 可以使在不同浏览器的盒模型统一起来。

# 002:常见的定位方案

定位方案是控制元素的布局,有三种常见的方案:

# 普通流

在普通流中,元素会默认按照其在 HTML 中的先后位置至上而下布局。

在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。

# 浮动

在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。

(即使用 float 脱离文档流时,其他盒子会无视这个元素,但其他盒子内的文本依然会为这个元素让出位置,环绕在周围。)

浮动元素会从普通文档流中脱离,但浮动元素影响的不仅是自己,它会影响周围的元素对齐进行环绕。简单来说,就是 block 元素无视 float 元素,让 inline 元素让流水一样围绕着 float 元素。

以下代码会实现一个文字环绕的效果:

<div>
    <div style="height: 100px;width: 100px;float: left;background: lightblue">
        我是一个左浮动的元素
    </div>
    <div style="width: 200px; height: 200px;background: #eee">
        我是一个没有设置浮动, 也没有触发 BFC 元素, width: 200px; height:200px;
        background: #eee;
    </div>
</div>

若不想浮动元素覆盖,可以通过 BFC 可以阻止元素被浮动元素覆盖。

# 绝对定位

在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。

# 003:介绍下 BFC 及其应用?

# FC(Fomatting context)

FC(Fomatting context)是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。有:BFC(Block Formatting Context, 块级格式化上下文)、 IFC(Inline Formatting Context, 行内格式上下文)、 GFC(Grid Formatting Context, 网格布局格式化上下文)、 FFC(Flex formatting contexts, 自适应格式上下文)。

# BFC(Block fomatting context)

BFC(Block fomatting context) 块级格式化上下文,BFC 它属于定位方案中的普通流。相当于页面隔离的一个区域,类似一个容器,容器里外的元素不会相互影响。

  • BFC 触发的任一条件:
    (1)根元素<html>
    (2)浮动元素(float 不为 none);
    (3)绝对定位元素(position 为 absolute / fixed );
    (4)overflow 不为默认值 visible 的块元素(hidden、auto、scroll);
    (5)display: inline-block || flex || table-cell || table-caption。

  • BFC 具有的特性:
    (1)BFC 区域内,两个相邻 box 的外边框margin垂直方向会发生折叠;(可生成两个 BFC 用于解决外边距 margin 垂直方向重叠问题)
    (2)BFC 区域内,浮动元素会被包裹在内(浮动内容会和周围的内容等高);
    (3)计算 BFC 区域的高度时,浮动元素也会参与计算。(用于解决浮动导致父元素坍陷,overflow:auto);
    (4)BFC 区域可以阻止与浮动元素发生重叠覆盖;(浮动元素会覆盖普通元素,为了解决清除浮动,可将普通元素生成 BFC, 避免重叠覆盖)。

  • BFC 主要作用:
    (1)解决外边距坍塌;
    (2)清除浮动;
    (3)用于自适应两栏布局。

详细例子可参考:
10 分钟理解 BFC 原理 (opens new window)
CSS——可视化格式模型 (opens new window)

# 004:CSS 层叠顺序

层叠顺序受层叠水平上下文、层叠等级、层叠规则影响。

# 层叠上下文:

html 页面存在的一个三维概念,就是我们认知里的层叠 z 轴。一般情况下,元素在页面上沿 X 轴 Y 轴平铺,我们察觉不到它们在 Z 轴上的层叠关系。而一旦元素发生堆叠,这时就能发现某个元素可能覆盖了另一个元素或者被另一个元素覆盖。这个时候其实就是和层叠上下文有关系。

如果一个元素含有层叠上下文,(也就是说它是层叠上下文元素),我们可以理解为这个元素在 Z 轴上就“高人一等”,最终表现就是它离屏幕观察者更近。

产生层叠上下文的条件:
(1)HTML 根元素为“根层叠上下文”;
(2)设置 position 为 relative/absolute 的定位元素并设置 z-index 属性为具体数值,会产生层叠上下文(没有设置 z-index 为具体数值,则默认 z-inde:auto 是不会产生层叠上下文);
(3)设置了 position:fixed;,就会产生层叠上下文。
(4)父级 display:flex,子元素的 z-index 不是 auto,必须是数值。此时,这个子元素为层叠上下文元素;
(4)CSS3 中的新属性会产生层叠上下文,比如 opacity 透明元素不是 1, transform 变换不为 none,filter 不为 none,will-change 指定的属性值为上面任意一个;

# 层叠等级

层叠等级,也叫“层叠级别”或者“层叠水平”。可以简单理解为:在同一个层叠上下文中,层叠上下文元素在 Z 轴上的上下顺序。

存在结论:

  • 普通元素的层叠等级 由 其所在的层叠上下文决定;
  • 层叠等级的比较,只有在当前层叠上下文元素中才有意义。不同层叠上下文中比较层叠等级是没有意义的。

就好比:
一个省官(A 拥有秘书 a1 和 保姆 a2)和一个地区官(B 拥有秘书 b1 和 保姆 b2),这个时候的等级比较, A 下属等级和 B 下属没有可比性。
只有在 A 下属比较 a1 和 a2,以及 B 下属比较 b1 和 b2,这种相互比较大小高低才有意义。

# 层叠顺序

前面所说的“层叠上下文”和“层叠等级”是一种概念,而这里的“层叠顺序”是一种规则。

层叠顺序的规则如下:

形成层叠上下文元素的background/border

-> z-index负值

-> block块状盒子
-> float浮动盒子
-> inline-block水平盒子

-> z-index:0/auto || 不依赖z-index的层叠上下文 (这里的不依赖z-index的层叠上下文例子有transform/opacity...,transform 会创建比 z-index 更高层级的层叠上下文,此时同时设置 z-index 会失效。)

-> z-index正值

注意:

  1. 层叠上下文 background/border指的是层叠上下文元素的背景和边框;

  2. inline/inline-block元素的层叠顺序要高于 block(块级) / float(浮动)元素;
    因为网页设计之初最重要的就是文字内容,所以在发生层叠时会优先显示文字内容,需要保证其不被覆盖。

  3. 定位元素会层叠在普通元素的上面;
    因为元素一旦成为定位元素,其 z-index 就会自动生效,此时其 z-index 就是默认的 auto,就会覆盖 inline 或 block 或 float 元素。

  4. 单纯层叠顺序,z-index: autoz-index: 0 在同一层级,但这两个属性值本身是有根本区别的。

如果层叠上下文元素不依赖 z-index 数值,则其层叠顺序是 z-index:auto 可看成 z:index:0 级别。比如:

<!-- 此时pic2会覆盖在pic1上面 -->
<img src="pic1" style="position:relative" />
<img src="pic2" style="transform:scale(1);" />

<!-- 此时pic1会覆盖在pic2上面 -->
<img src="pic2" style="transform:scale(1);" />
<img src="pic1" style="position:relative" />

<!-- 此时pic2会覆盖在pic1上面,因为 z-index正值层叠上下文 的层叠顺序比 不依赖z-index的层叠上下文高 -->
<img src="pic1" style="position:relative; z-index: 1;" />
<img src="pic2" style="transform:scale(1);" />

# 层叠规则

遵循两大规则:

  • 规则 1:谁大谁上:当具有明显的层叠水平标示的时候,如识别的 z-indx 值,在同一个层叠上下文中,层叠水平值大的那一个覆盖小的那一个。

  • 规则 2:后来居上:当元素的层叠水平一致、层叠顺序相同的时候,在 DOM 流中处于后面的元素会覆盖前面的元素。

再结合上文的层叠上下文、层叠等级和层叠顺序规则,得出一个套路:

  1. 首先,要比较的两个元素是否处于同一个层叠上下文中:

    • 1.1 如果是,谁的层叠等级大,谁在上面(怎么判断层叠等级大小呢?这个根据“层叠顺序”进行判断)。

    • 1.2 如果不在同一层叠上下文中,请先比较他们所在的层叠上下文的层叠等级。

  2. 当两个元素层叠等级相同,层叠顺序相同时,在 DOM 结构中后面的元素层叠等级在前面元素之上。

  3. 层叠上下文嵌套的情况下,内部层叠上下文及其所有子元素都会受制于外部的层叠上下文,整个元素被认为是在父层叠上下文的层叠顺序中。(即外部层叠上下文直接影响内部的,子层叠上下文无法穿透其父级层叠的上下文)。

# 更多例子可参考

# 005:介绍 CSS 的 flexbox(弹性盒布局模型),以及其适用场景,兼容性如何?

flex 布局是一种弹性布局,通过display: flex来设置。

目标在于能够使得父元素在子元素的大小未知或者动态变化的情况下仍然能按照规定来分配好子元素的布局,以最佳方式填充可用空间,从而使得元素达到自适应的效果。

(在 flex 布局中,子元素的设置 float,clear 以及 vertical-align 属性都是没有用的。)

  • 适用场景:
    (1)元素水平垂直居中;
    (2)响应式侧边栏 / tab 栏;
    (3)移动端布局

  • 兼容性:
    IE6~9 不支持,IE11 以上基本支持 flex 布局,其他的主流浏览器包括安卓和 IOS 基本上都支持了。

  • 针对父元素提供的属性有:

    flex-direction
    flex-wrap
    flex-flow (<flex-direction> || <flex-wrap>)
    justify-content
    align-items
    align-content
    

    针对子元素提供的属性有:

    order:配置子元素的排列顺序,数值越小,排列越靠前,默认为0
    
    flex-grow
    flex-shrink
    flex-basis:设置子元素在主轴上的伸缩基准值,单位是长度/百分比(相对父元素的width/height)
    flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ],该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)aligin-self: 配置单个项目有与其他项目不一样的对齐方式; 默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
    
  • 如何适配:
    (1)flex 父元素可通过flex-direction来设置主轴方向,通过主轴(justy-content)和交叉轴(align-items) 规定子元素的对齐模式;

    (2)flex 子元素可通过 flex-basis 来设置主轴方向的大小,而 flex-basis 会根据 flex-grow / flex-shrink 的值来自动改变子元素的宽度来达到自适应的效果。

    flex-basis 指在主轴方向上的初始大小,flex-basis 的设置准则是:

    a. flex-basis 的值如果是一个百分数,这个百分数是相对于其父弹性盒容器主轴尺寸的百分数

    b. 如果设置了 flex-basis 和 width/height(主要看主轴方向;
    除了 flex-basis 值为 auto 时,flex-basis 的优先级会比 width/height 高。

    c. 如果没有设置 flex-basis 属性值,默认值会是 auto,会根据主轴方向检索子元素的 width/height 值作为 flex-basis 的值,即它的大小就是项目设置 width 的大小;
    如果没有设置 width 属性值,那么 flex-basis 的大小就是项目内容的大小。(content->width->flex-basis

    d. 同时 flex-basis 又受元素的 min-width 和 max-widht 来限制。

    e. flex-basis: 0时,即指定了 width/height 为 0。

    (3)flex 子元素可通过orderflex-growflex-shrink来控制子元素根据容器大小变化而导致的顺序和缩放比例变化。

    其中,flex 容器里的子元素设置的 flex 属性的属性值对应是 flex:flex-grow flex-shrink flex-basis

    使元素自适应屏幕可以设置元素的 max-width,然后设置 flex-grow 使 flex-basis 根据 flex 盒子的宽度来自动填充子元素。

  • flex 计算公式

当空间充足时,flex 子项宽度计算公式是:自身的基础宽度 + 容器剩余宽度 *(自身伸张比例 / 所有子项伸张比例之和)

当空间充足不足时,flex 子项的宽度计算公式是: 自身的基础宽度 - 超出宽度 * ((自身宽度 * 收缩比例)/ 总权重):

# 006:flex:1 完整写法

flex:1 代表

flex-grow: 1;
flex-shrink: 1,
flex-basis: 0;

# flex 属性值规则

flex 属性的属性值分别对应:flex-grow, flex-shrink, flex-basis

有非负数 n1、n2,长度值或百分数 x

flex: n1,其等于 n, 1, 0%
flex: n1, n2,其等于 n1, n2, 0%

flex: n1, x,其等于 n 0 x

flex: x,x 代表 flex-basis 的值,等于 1, 1, x;

flex:initial 等同于设置 flex: 0 1 auto

flex:auto 等同于设置 flex: 1 1 auto

flex:none 等同于设置 flex: 0 0 auto

具体用法可戳: flex 例子 (opens new window)

<style type="text/css">
    .parent {
        display: flex;
        width: 600px;
    }
    .parent > div {
        height: 100px;
    }
    .item-1 {
        width: 140px;
        flex: 2 1 0%;
        background: blue;
    }
    .item-2 {
        width: 100px;
        flex: 2 1 auto;
        background: darkblue;
    }
    .item-3 {
        flex: 1 1 200px;
        background: lightblue;
    }
</style>

针对 flex-basis 的属性得:主轴上可剩余的分配空间为:600-(0+100+200)=300

item-10%
item-2:auto -> 即 100px
item-3:200px

针对 flex-grow 属性得:各项目分配得到的空间

item-1 = 0% + 120px【 300 *2/2+2+1))】 = 120px
item-2 = auto + 120px 【 300 *2/2+2+1))】= 220px
item-3 = 200px + 60px 【 300 *1/2+2+1))】= 260px
<style type="text/css">
    .parent {
        display: flex;
        width: 300px;
        height: 100px;
    }
    .item-1 {
        width: 160px;
        flex-shrink: 2;
        background: blue;
    }
    .item-2 {
        width: 140px;
        flex: 2 2 auto;
        background: darkblue;
    }
    .item-3 {
        flex: 1 3 300px;
        background: lightblue;
    }
</style>
  • 针对 flex-basis 和 width 的属性得:
    主轴上超出空间为 300-(160+140+300)=300

  • 针对 flex-shrink 和 width 计算总权重:
    sum = a * w1 + b * w2 + c * w3 = 2*160 + 2*140 + 3*300 = 1500

  • 再计算每个元素压缩率:S1 = a * w1 / sum, S2 =b * w2 / sum, S3 =c * w3 / sum
    即分别为:320/1500 = 16/75,280/1500 = 14/75,900/1500 = 45/75

  • 计算得每个元素空间:自身的基础宽度 - 超出宽度 * 压缩率
    即分别为:160-(300*16/75)=96140-(300*14/75)=84300-(300*45/75)=120

# 007:介绍 CSS 的 grid 栅格布局以及其适用场景,与 flex 布局的适用场景的区分?

flex 布局适合小规模的布局,grid 布局面向大规模的布局。

参考文章:
写给自己看的 display: grid 布局教程 (opens new window)

# 008: 实现元素垂直水平居中的方法。

<div class="wrapper">
    <div class="container"></div>
</div>

# 方法 1:知元素宽高,可使用【绝对定位 + margin】实现

.wrapper {
    width: 100%;
    height: 100vh;
    background-color: pink;
    position: relative;
}

.container {
    width: 200px;
    height: 200px;
    background-color: lightyellow;
    position: absolute;
    top: 50%;
    left: 50%;
    margin-left: -100px; /* (-(width/2)px) */
    margin-top: -100px; /* (-(height/2)px) */
}

/* 或者 */

.container {
    width: 200px;
    height: 200px;
    background-color: lightyellow;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    margin: auto;
}

# 方法 2:不知元素宽高,可使用 css3 的新属性 transform:translate(x,y) 属性

.wrapper {
    width: 100%;
    height: 100vh;
    background-color: pink;
    position: relative;
}

.container {
    background-color: lightyellow;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%); /* translate的%相对于自身的宽度和高 */
    -webkit-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
    -moz-transform: translate(-50%, -50%);
    -ms-transform: translate(-50%, -50%);
}

# 方法 3:flex 布局

.wrapper {
    width: 100%;
    height: 100vh;
    background-color: pink;
    display: flex;
    justify-content: center;
    align-items: center;
}

.container {
    width: 200px;
    height: 200px;
    background-color: lightyellow;
}

# 方法 4:行内元素水平垂直居中,可使用 text-align & line-height

.wrapper {
    width: 100%;
    height: 100vh;
    background-color: pink;
    text-align: center;
    line-height: 100vh; /* wrapper height */
}

# 009:CSS 常见布局(两列布局/三列布局/圣杯布局/双飞翼布局)

# 两列布局(一边宽度固定,另一边自适应)

  • 方案一:float + 普通元素 margin
.page {
    width: 100%;
    height: 1000px;
    background: yellow;
}

.left {
    width: 200px;
    height: 100%;
    float: left;
    background: pink;
}

.right {
    width: 100%;
    height: 100%;
    margin-left: 200px;
    background: green;
}
  • 方案二:利用 BFC 不会重叠浮动元素特性,float + overflow
.page {
    width: 100%;
    height: 1000px;
    overflow: auto;
    background: yellow;
}
.left {
    height: 100%;
    float: left;
    background: pink;
}

.right {
    height: 100%;
    overflow: hidden;
    background: green;
}
  • 方案三:flex 布局
.page {
    width: 100%;
    height: 1000px;
    background: yellow;
    display: flex;
    justify-content: flex-start;
}

.left {
    width: 20px;
    background: pink;
}

.right {
    flex: 1;
    background: green;
}
  • 方案四:absolute
.page {
    width: 100%;
    height: 1000px;
    background: yellow;
    position: relative;
}
.left {
    height: 100%;
    width: 200px;
    background: pink;
}

.right {
    height: 100%;
    background: green;
    position: absolute;
    top: 10px; /*(加上padding)*/
    left: 210px; /*(加上padding)*/
}

# 三列布局(中间自适应,左右两边固定)

# flex 布局
# BFC 三栏布局
<div class="container">
    <div class="left">1111</div>
    <div class="right">2222</div>
    <div class="center">333</div>
</div>

<style>
    .container {
        width: 100%;
        height: 20vh;
        border: 1px solid #ccc;
    }
    .left {
        width: 200px;
        height: 100%;
        background: yellow;
        float: left;
    }
    .right {
        width: 200px;
        background: yellowgreen;
        float: right;
    }
    .center {
        height: 100%;
        overflow: hidden;
    }
</style>
# 圣杯布局

DOM 结构必须是先写中间列部分,可实现中间列可以优先加载。

<style>
    .container {
        /* width: 100%; */
        /* height: 1000px; */
        background: yellow;

        /*1. 利用内填充,将左右流出空隙*/
        padding-left: 220px;
        padding-right: 220px;
    }

    /*2. 三个部分都设定为左浮动,否则左右两边内容上不去,就不可能与中间列同一行。然后设置center的宽度为100%(实现中间列内容自适应),此时,left和right部分会跳到下一行*/
    .center {
        width: 100%;
        height: 100%;
        float: left;
        background: orange;
    }

    /*3.通过设置margin-left为负值让left和right部分回到与center部分同一行*/

    /*4.通过设置相对定位,让left和right部分移动到两边。*/
    .left {
        width: 200px;
        height: 100%;
        float: left;
        background: pink;

        /*使left往center的左边靠*/
        margin-left: -100%;

        /*使left往container的左边靠*/
        position: relative;
        left: -220px;
    }

    .right {
        width: 200px;
        height: 100%;
        float: left;
        background: green;

        /*使right往center的右边靠*/
        margin-left: -200px;

        /*使right往container的右边靠*/
        position: relative;
        right: -220px;
    }
</style>

<div class="container">
    <div class="center">333</div>
    <div class="left">1111</div>
    <div class="right">2222</div>
</div>

缺点:

  1. center 部分的最小宽度不能小于 left 部分的宽度,否则会 left 部分掉到下一行;
  2. 如果其中一列内容高度拉长(如下图),其他两列的背景并不会自动填充。
# 双飞翼布局(float+margin)

在圣杯布局基础上进一步优化,解决了圣杯布局错乱问题,实现了内容与布局的分离。而且任何一栏都可以是最高栏,不会出问题。(解决圣杯布局的缺点 1)

<style>
    .container {
        /*width: 100%;*/
        height: 1000%;
        background: yellow;
    }

    /*2. 三个部分都设定为左浮动,否则左右两边内容上不去,就不可能与中间列同一行。然后设置center的宽度为100%(实现中间列内容自适应),此时,left和right部分会跳到下一行*/
    .center {
        width: 100%;
        height: 100%;
        float: left;
        background: orange;
    }

    /*主要区别: 1.center部分增加一个内层div,并设margin: 0 200px;*/
    .inner {
        margin: 0 200px;
    }

    /*3.通过设置margin-left为负值让left和right部分回到与center部分同一行*/
    .left {
        width: 200px;
        height: 100%;
        float: left;
        background: pink;

        /*使left往center的左边靠*/
        margin-left: -100%;
    }

    .right {
        width: 200px;
        height: 100%;
        float: left;
        background: green;

        /*使right往center的右边靠*/
        margin-left: -200px;
    }
</style>

<div class="container">
    <div class="center">
        <div class="inner">
            <p>333</p>
            <p>333</p>
            <p>333</p>
            <p>333</p>
            <p>333</p>
            <p>333</p>
        </div>
    </div>
    <div class="left">1111</div>
    <div class="right">2222</div>
</div>
# 圣杯/双飞翼联系与区别
  • 两种布局方式都是把主列放在文档流最前面,使主列优先加载。

  • 两种布局方式在实现上也有相同之处,都是让三列浮动,然后通过负外边距形成三列布局。

  • 两种布局方式的不同之处在于如何处理中间主列的位置:
    1)圣杯布局是利用父容器的左、右内边距 + 两个从列相对定位;
    2)双飞翼布局是把主列嵌套在一个新的父级块中,利用主列的左、右外边距进行布局调整。

# 等高布局

等高布局是指子元素在父元素中高度相等的布局方式,解决了圣杯布局的缺点 2。

利用正 padding+负 margin

我们通过等布局便可解决圣杯布局的第二点缺点,因为背景是在 padding 区域显示的,设置一个大数值的 padding-bottom,再设置相同数值的负的 margin-bottom,并在所有列外面加上一个容器并设置 overflow:hidden 把溢出背景切掉。这种可能实现多列等高布局,并且也能实现列与列之间分隔线效果,结构简单,兼容所有浏览器。

<style>
    .container {
        background: yellow;

        /* 左右留出空隙 */
        padding-left: 220px;
        padding-right: 220px;

        /* 把溢出背景切掉 */
        overflow: hidden;
    }

    /* 所有列设定为左浮动 */
    .center {
        width: 100%;
        height: 100%;
        background: orange;

        float: left;
    }

    /* 通过设置margin-left为负值让left和right部分回到与center部分同一行 */
    /* 通过设置相对定位,让left和right部分移动到两边 */
    .left {
        width: 200px;
        height: 100%;
        background: pink;

        float: left;

        /*使left往center的左边靠*/
        margin-left: -100%;

        /*使left往container的左边靠*/
        position: relative;
        left: -220px;
    }

    .right {
        width: 200px;
        height: 100%;
        float: left;
        background: green;

        /*使right往center的右边靠*/
        margin-left: -200px;

        /*使right往container的右边靠*/
        position: relative;
        right: -220px;
    }

    /* 设置大值的padding-bottom和margin-bottom */
    .center,
    .left,
    .right {
        padding-bottom: 10000px;
        margin-bottom: -10000px;
    }
</style>

# 010:分析比较 opacity: 0 / visibility: hidden / display: none 和它们的适用场景。

# display: none

(1)display: none 浏览器不渲染,不占据空间,并且无法监听触发 DOM 事件;
(2)display: none 切换改变会触发回流重绘,性能消耗较大;
(3)display: none 具有株连性,父元素被隐藏,子孙元素也无法被渲染显示;

# visibility: hidden

(1)visibility: hidden 隐藏元素,占据空间,并且无法监听触发 DOM 事件;
(2)visibility: hidden 切换改变只会触发重绘,性能消耗较小;
(3)visibility: hidden 不具有株连性,父元素被隐藏时,子孙元素可以通过设置 visibility: visible 来取消隐藏;
(4)visibility 不支持 transition 过渡变化。

# opacity: 0

(1)opacity: 0 隐藏元素,占据空间,可以监听触发 DOM 事件;
(2)opacity: 0 切换改变只会触发重绘,性能消耗较小;
(3)opacity: 0 具有株连性,父元素被隐藏,子孙元素也无法被渲染显示;
(4)opacity 支持 transition 过渡变化。

# 011: position 的值有哪些? relative、absolute 定位规则?

常用:

  • position: staic:默认值,按照元素在当前文档流中的正常布局位置定位。

  • position: relative:生成相对定位元素,会相对于元素的原有位置进行定位,不脱离文档流,在文档流中依然保着原有的默认位置。

    1. 如果 top、left、right、bottom 使用百分比,其**相对于其包含块的实际内容 width(不包含 border 和 padding)**进行计算(会和 box-sizing 值有关系)。

    2. 定位起始位置为相对于元素的原有位置进行定位。

  • position: absolute:生成绝对定位元素,会相对于最近的设置了非 static 定位的祖先元素进行定位,如果没有,则相对于浏览器窗口进行定位,会脱离文档流,不在文档流里面占位置。

    1. 如果 top、left、right、bottom 使用百分比,其值是**相对于其包含块的(padding + 实际内容 width)**进行计算(会和 box-sizing 值有关系)。

    2. 定位元素的起始位置为其包含块的内边距开始的地方(不包括在 border 里,除非使用负值,会在 padding 里)

    .contain {
        padding: 10px;
        background: yellow;
        height: 100px;
        width: 100px;
        position: relative;
    }
    
    .ab {
        width: 50px;
        height: 50px;
        background: pink;
        position: absolute;
        top: 10%;
        left: 10%;
    }
    
    <!-- border-box情况下 -->
    // top = 100px * 10% = 10px ,left = 10px
    
    <!-- ontent-box情况下 -->
    // top = (10px + 100px  + 100px) * 10% = 12px ,left = 12px
    
  • position: fixed:生成绝对定位元素,默认相当于浏览器窗口进行定位,但如果其被包含在 transform 元素下,会相对 transform 元素定位

  • position: inherit:规定从父元素继承 position 属性。

参考文章:
前端重构范式之 position (opens new window)

# 013:CSS 解析规则

  • css 选择器是从右向左进行解析。
    从右向左匹配,先找到所有的最右节点,对于每一个节点,向上寻找父节点直到找到根元素或者满足条件的匹配规则,则结束这个分支的遍历。

    两种匹从右向左的匹配在第一步就可以筛选掉了大量的不符合条件的最右节点(叶子节点),

# 014:CSS 选择器

  1. !important
  2. 行内样式 style=""
  3. ID 选择器#id
  4. 类选择器 / 属性选择器 a[href] a[title='test'] / 伪类选择器 a:link a:visited a:hover a:active
  5. 元素选择器/ 关系选择器 后代: ul li ,子元素:h1 > strong ,兄弟:h1 + p / 伪元素选择器 span::after
  6. 通配符选择器*

# 015:CSS 权重规则

权重口诀:important 最高权重,然后从 0 开始,一个行内样式+1000,一个 id 选择器+100,一个属性选择器、class 或者伪类+10,一个元素选择器,或者伪元素+1,关系选择器和通配符+0。

  • 当两个样式都使用!important 时,权重值大的优先级更高

  • !important > 行内样式 > 内联样式 and 外联样式,内联样式和外联样式的优先级和加载顺序有关。

# 016:伪类和伪元素

联系:

伪类和伪元素都是用来表示文档树以外的"元素",对在 dom 树里面存在的元素进行修饰。

区别:

  • 表示方法

伪类用单冒号表示,伪元素用双冒号::表示;

但是浏览器同样接受 CSS2 时代已经存在的伪元素(:before, :after, :first-line, :first-letter 等)的单冒号写法。

对于 CSS2 之后所有新增的伪元素(如::selection),应该采用双冒号的写法。但是因为兼容性问题,大部分还是用的单冒号。

  • 定义不同

伪类的操作对象是文档树中已有的元素,而伪元素则创建了一个文档数外的元素。因此,伪类与伪元素的区别在于:有没有创建一个文档树之外的元素。

1) 伪类即假的类,通常可以添加类来达到效果,例子:

想要一个 p 标签文字的首字母给特定颜色,如果不创建一个 元素,我们可以通过设置 p:first-letter 伪元素来为其添加样式。这个时候,看起来好像是创建了一个虚拟的 元素并添加了样式,但实际上文档树中并不存在这个 元素。

2)伪元素即假元素,需要通过添加元素才能达到效果,例子:

h1:before {
    content: "Hello ";
}

# 017:实现 div 固定宽高比(width: height = 4: 3 )

实现详细:实现一个 div,宽度是 body 的一半,固定宽高比满足 4:3

这里涉及两个知识点,就是:

padding 四个方向值是百分比时,这个百分比是相对于其父元素的宽度而言的,即使对于 padding-bottom 和 padding-top 也是如此。
更多属性值百分比相对可戳一个知乎问题答案 (opens new window)

利用这个知识点,可以采用如下思路解决问题:

width:height = 4:3,那么 height=width*(3/4)=width*75%。

但此时由于宽度并不是全屏,而是 body 的一半,所以需要在外面套一个 div 且使这个 div 的宽度为 body 的一半,然后内层 div 宽度为 100%。

将内层 div 高度设置为 0,然后利用 padding-bottom/padding-top 来代替 height 来实现高度与宽度成比例的效果

<body>
    <div class="wrapper">
        <div class="contain">
            <p class="content">content content content content</p>
        </div>
    </div>
</body>
.wrapper {
    width: 50%;
}

.contain {
    width: 100%;
    height: 0;
    padding-bottom: 75%;
    position: relative;
    background-color: yellow;
}

更多解决方案可以戳 (opens new window)

# 018:em rem vh vw calc line-height 百分比

  • em :相对单位,参考物是父元素的 font-size,具有继承的特点。如果字体大小是 16px(浏览器的默认值),那么 1em = 16px

  • rem:相对单位,相对根节点 html 的字体大小来计算。

  • vw:viewpoint width,视窗宽度,1vw 等于视窗宽度的 1%。

  • vh:viewpoint height,视窗高度,1vh 等于视窗高度的 1%。

  • vmin:取当前 vw 和 Vh 中较小的那一个值, vmax:取当前 Vw 和 Vh 中较大的那一个值

  • line-height 相对百分比 (opens new window)

# 其他属性的百分比相对元素

  • 相对于父级宽:wdith(min,max)paddingmarginleftright、grid-auto-columns/grid-template-columns、column-gap

  • 相对于父级高:heighttopbottom、grid-auto-rows/grid-template-rows、row-gap

  • 相对于自身宽高:border-radiusbackground-sizetransform: translate()、border-image-width、transform-origin、zoom、clip-path

  • flex-basis 相对主轴

  • position:fixed的元素,一般情况下 top/bottom 相对于浏览器视口高度,left/right相对于浏览器视口宽度。
    但是,若position:fixed的元素被含有translate属性的元素包围,则 fixed 元素定位属性值的百分比会变成会相对 translate 元素。

# 019: css 字符串溢出

# 单行文本溢出

.overflowText {
    /* 需要有宽度 */
    width:200px;

    overflow:hidden; (顾名思义超出限定的宽度就隐藏内容)
    white-space: nowrap; (设置文字在一行显示不能换行)
    text-overflow: ellipsis;(规定当文本溢出时显示省略符号来代表被修剪的文本)
}

# 多行文本溢出

.overflowText {
    /* 将对象作为弹性伸缩盒子模型显示 */
    display: -webkit-box;

    /* 设置或检索伸缩盒对象的子元素的排列方式 */
    -webkit-box-orient: vertical;

    /* 用来限制在一个块元素显示的文本的行数,2表示最多显示2行。 为了实现该效果,它需要组合其他的WebKit属性) */
    -webkit-line-clamp: 2;

    overflow: hidden;
    text-overflow: ellipsis;
}

# 020: 控制 div 内的元素自动换行

.autoWrap {
    word-break: break-all;
    word-wrap: break-word;
}

# 021:清除浮动方法

# 生成 BFC:对父元素增加 overflow 属性

# clear:both

1)创建相对浮动节点的新兄弟节点,并设置 clear:both属性

2)创建父元素的伪元素标签,并设置 clear:both属性

# 022:行内元素和块状元素区别

  • 块状元素

    • 块状元素独占一行,自动填满为父元素的宽度;垂直方向上进行排列;
    • 可以设置width/height,但尽管设置了非填满的 width 依然会占一行;
    • 可以设置四个方向的 margin 和 padding;
    • 可以嵌套行内元素。
  • 行内元素

    • 行内元素会和其他行内元素在同一行内,水平方向进行排列,直到填充满进行换行;
    • 不可以设置width/height,一般宽度是直接由内部的文字或者图片等内容撑开;
    • 只可以设置水平方向的 margin 和 padding;
    • 不可以嵌套块状元素,行内元素只能容纳文本或者其他行内元素。

# 023:postcss

# 024:css 预处理器 less sass

# 025:transition

# 026:transfrom

# 027:animation