字节跳动讲师:韩广军
笔记撰写整理:百里飞洋

版权声明:因内容版权与个人意愿等多方面原因,可以分享本文链接,但绝对不接受转载,违者必究,谢谢配合!

一、深入CSS

接下来讲的主要关于继承和布局的一些知识。

想一想下面的CSS会生效的是哪个?

1
2
3
4
5
6
7
8
9
10
11
12
<article>
<h1 class="title">拉森火山国家公园</h1>
</article>

<style>
.title {
color: blue;
}
article h1 {
color: red;
}
</style>

答案是第一个,为什么呢,这就涉及到选择器的特异度的问题了。

1. 选择器的特异度(Specificity)

即选择器的特殊程度:

7aosij.png

2. 覆盖

“高的优先级选择器”的值会覆盖“低优先级选择器”相同属性的值

3. 继承

除了覆盖,还有继承:某些属性会自动继承其父元素的计算值,除非显示特定一个值。

CSS中一般和文字相关的字体大小这样的属性是可以继承的,但和宽度高度这样的盒模型相关的属性是不可以继承的。

4. 显式继承

让本身不可继承的属性,想让它继承

1
2
3
4
5
6
7
8
9
10
11
12
* {
box-sizinginherit;
/* 让所有元素的box-sizing默认继承父元素 */
}

html {
box-sizing: border-box;
}

.some-weight {
box-sizing: content-box;
}
  1. inherit 关键字指定一个属性应从父元素继承它的值。
  2. inherit 关键字可用于任何 HTML 元素上的任何 CSS 属性。

5. 初始值

  • CSS中每个属性都有一个初始值
    1. background-color 的初始值为 transparent(透明的)
    2. margin-left 的初始值为0
  • 可以使用initial关键字显式重置为初始值
    1. backgr-color: initial

6. CSS求值过程

接下来讲怎么样从一个DOM节点去生成一棵渲染树,或者是对应到渲染节点这样的一个过程。

7abzut.png

7aqaVK.png

7aqcrt.png


二、盒模型

盒模型示意图:

盒模型.png

width

  • 指定 content box 宽度
  • 取值为长度百分数auto
    1. auto由浏览器根据其他属性决定
    2. 百分数相对于容器的 content box 宽度

height

  • 指定 content box 高度
  • 取值为长度百分数auto
    1. auto取值由内容计算得来
    2. 百分数相对于容器的 content box 高度
    3. 容器有指定的高度时,百分数才生效

padding

  • 指定元素四个方向的内边距
  • 百分数相对于容器宽度(即便是高度的百分数,也是相对于容器宽度的)
  1. padding: 10px;:上下左右都为10px
  2. padding: 10px 20px;:上下为10px,左右为20px
  3. padding: 10px 20px 10px 20px;:上右下左

border

border: 1px solid #ccc;
粗细,颜色,线条种类(虚线、实线、点状线等)

  • 三种属性:
    1. border-width
    2. berder-style
    3. berder-color
  • 四个方向
    1. berder-top
    2. berder-right
    3. berder-bottom
    4. berder-left

还能够这样:border-left-width: 3px;border-top-color: #f00;

可以用border去模拟下面的正方形:

  • 当box-sizing: content-box;时:

  • 当box-sizing: border-box;时:

  • 当其他三个边都设置为透明,则可以模拟出三角形:

margin

  • 指向元素四个方向的外边距
  • 取值可以是长度百分数auto
    • 百分数相对于容器宽度

边距的合并和折叠(margin collapse):
可以理解为margin不是实体,是虚的,上下两个相邻div之间的margin并不会相加,而是取最大者的。
注意:水平方向上的margin不会合并!

box-sizing

box-sizing: border-box;(最常用)

box-sizing: content-box;

overflow

  1. visible:默认属性,内容过多会溢出显示
  2. hidden:超出内容隐藏
  3. scroll:超出内容可以滚动(没有溢出也会有滚动条)
  4. auto:没有溢出时正常显示(溢出之后再显示滚动条

三、布局(Layout)是什么?

  • 确定内容的大小和位置的算法
  • 依据元素、容器、兄弟节点和内容等信息来计算

布局相关技术:

  1. 常规流(文档流):行级、块级、表格布局、FlexBox、Grid布局
  2. 浮动
  3. 绝对定位

1》常规流 Normal Flow

  • 根元素、浮动和绝对定位的元素会脱离常规流
  • 其他元素都在常规流之内(in-flow)
  • 常规流中的盒子,在某种排版上下文中参与布局
    (排版上下文靠的就是display属性)
  1. 行级排版上下文(会创建IFC)
  2. 块级排版上下文(会创建BFC)

(1)块级vs行级

  • 块级Block Level Box

    1. 不和其他盒子并排放
    2. 所有盒模型属性都适用
  • 行级Inline Level Box

    1. 和其他盒子一起放在一行或拆开成多行
    2. 盒模型中widthheight属性不适用

display

  1. block
  2. inline
  3. inline-block 本身是行级,但可以设置宽高,且不会被拆散成多行
  4. none 排版时完全忽略

(2)Flex Box 是什么?

  • 一种新的排版上下文
  • 它可以控制子级盒子的:
    1. 摆放流向(↑ ← ↓ →)
    2. 摆放顺序
    3. 盒子宽度和高度
    4. 水平和垂直方向的对齐
    5. 是否允许折行

摆放流向flex-direction

把指定的方向称为主轴方向,跟它垂直的方向称为侧轴方向(交叉轴)。

7dOpPU.png

主轴对齐flex-content

7dOuGD.png

侧轴对齐align-items

7dObFK.png

可以给“不想合群”的家伙单独设置align-self

7dXdk6.png

摆放顺序order

可以给元素加上order属性,让其跳出书写的顺序,按照从小到大的顺序摆放。如果不设置,默认为0。

7dXhh8.png

弹性Flexibllity

  • 可以设置子项的弹性:当容器有剩余空间时,会伸展;容器空间不够时,会收缩。
  • flex-grow 有剩余空间时的伸展能力(抢夺剩余空间的能力,数字越大能力越大,默认数字是不能伸展的0)
  • flex-shrink 容器空间不足时收缩的能力(被压缩的能力,数字若为0则代表刚性的不压缩,默认数字是可被压缩的1)
  • flex-basis 自然情况下,没有伸展或收缩时的基础长度

多个flex属性可以写到一起:

7wpj41.png


(3)Grid 布局是什么?

Flex 布局只能一个方向(从上到下/从左到右),

Grid 是二维的布局方式,多了一个维度。

7wPqHg.png

display: grid

设计思路:

  • display: grid 使元素生成一个块级的 Grid 容器
  • 使用 grid-template 相关属性将容器划分为网格
  • 设置每一个子项占哪些行/列

划分网格

7wipvV.png

7wiPDU.png

7wiAUJ.png

网格线 grid line

先标记网格线编号:

7winv6.png

网格区域 grid area

再根据网格线标记区域,比如下图表示:

第1行、第1列开始,到第3行、第3列结束

7wiDaQ.png

代码示例:

7wiRMV.png

7wi7GR.png

7wiHR1.png


2》浮动 float

是除了常规流外的另一种模式,早期是用来做图文环绕效果的。

3》绝对定位 position

  1. static:默认值,非定位元素
  2. relative:相对自身原本位置偏移(上下左右),不脱离文档流
  3. absolute:绝对定位,相对于最近的非 static 祖先元素定位
  4. fixed:相对于视口绝对定位

四、学习 CSS 的几点建议

  1. 充分利用 MDNW3C CSS 规范
  2. 保持好奇心,善用浏览器的开发工具
  3. 持续学习,CSS 新特性还在不断出现

【提问专区】

  1. 那我想设置12px以下的字体咋办呐?

    在电脑上或者Chrome上没办法安全设置12px以下字体,因为有默认限制。但在大部分手机浏览器上是支持小字号显示的。真想在电脑上其实也能做,比如利用CSS的zoom属性或者用transform属性把它scale一下也能做。

  2. BFC用的多吗,如果不需要float布局的话

    不怎样用了,因为这些概念吧随着flex、grid这些布局方式的越来越强大,提的比较少了。但也有一些场景,比如说像垂直方向上的margin它不是会折叠在一块嘛,但有一些不光是相邻的两个元素。比如这个元素它可以穿透父元素跟它外面的元素有一个折叠,如果想避免的话,可以把它的父元素设置成一个BFC。如果有时候你把父元素设置成overflow: hidden;有副作用的话,你就可以设置display: flow-root;也是OK的。

  3. 宽高会有默认值这个概念吗,比如块级元素的width的默认值是100%,而height的默认值是0

    其实是有的吧,就像块级元素宽度默认值就是100%,高度是auto。

  4. 如果一个块级盒子包含一个行级盒子。且块级盒子没有高度,行级元素的高度被设定了。那块级元素的高度是不是默认会被行级元素的高度顶起来?那这种时候overflow属性是不是很尴尬?

    行级元素(display:inline;)的高度是不可以被指定的,你只能控制每一行的高度(line-height)。
    overflow属性生效的条件是你给这个容器一个确切的高度,不然是默认值auto的话,里面的内容是不会溢出的。

  5. 有了flex还会用float吗?

    应该也不会了

  6. 浮动和定位现在还常用吗?

    浮动确实不太常用了,但绝对定位有些时候还是没法避免的要使用的。

  7. margin设为负值是什么效果?

    margin确实是可以设置为负值的,大不了这两个元素重叠到一块呗。

  8. 触发repaint/reflow,他的css重新计算是计算对应元素,还是全部css的呀?

    (此处省略若干字…)总之不同属性的改变,会触发不同的流程吧。可以看一个网站,好像叫 CSS Triggers ,可以查看属性改变之后触发哪些流程。

  9. 0.5px的使用场景有哪些?

    主要在一些高分辨率的手机上吧,这里面涉及到DPR设备像素密度的问题。

  10. style解析是先进行层叠继承还是进行值的计算?

    先进行层叠的计算。就比如说一个元素先看它是不是可以继承的,如果可以就不往下算了,直接继承就OK了。
    (百里飞洋留言:怎么和第一句说的自相矛盾…口误吧)

  11. 浏览器滚动条如何设置一个好看的样式?

    这个可以搜一下,有些浏览器是可以自定义滚动条样式的。不是用DOM去模拟一个实现,而是原生的滚动条它也是可以去设置相应的CSS属性,通过一些伪元素的属性去设置的。

  12. overflow:hidden有什么缺点呢?

    溢出就看不到了,比如说在一个弹窗里面有一个很长的下拉框,下拉的这部分如果也是放在这个弹窗的这个容器里面,那么会有一部分看不着了么就。我们可以通过其他手段去规避。

  13. 新规范中只有流式元素和短语元素的描述了,请问可以将流式元素看作块级元素,短语元素看作行内元素吗?

    这涉及到CSS的演化嘛,(此处省略若干字,回答内容与问题无关)…

  14. 现在是不是不用table来布局了?

    对的,但还会用的table做表格。

  15. 宽度从0到100px会有一个transition的过渡效果,但是从0到100%则不会触发transition的过度效果,有什么解决方案吗?

    我印象中是从0到auto是没有效果的,但从0到100%好像新版的浏览器解决了这个问题。如果你不能用新版的浏览器做的话,你可以用一些hack的一些技巧,比如说你不去改变它的高度或者宽度,而是改变它的max-width这样的一些属性。就是说你的宽度还设置100%,但你再设置一个max-width是一个固定的值,然后让max-width去做动画然后应该就OK了。

    【拓展】前端中的hack是什么意思?
    hack在软件系统中意思翻译为:基于程序的基础,对其代码进行增加、删除或者修改、优化,使之在功能上符合新的需求。在前端中理解为:不同的浏览器对CSS的解析不同,会导致生成的页面效果不同,这时候需要编写额外代码兼容所有游览器,这个编写过程叫做hack。

  16. static 粘性定位用在哪些场景?

    比如说你常规的页面肯定有导航栏是吧,导航栏下面你可能展示了一个数据表格,表格的内容特别多比较长,然后你往上滚动的时候,正常情况下你把表头滚动走了之后就不知道表格的每一列对应的表头了。这个时候我们可以用position:sticky把那个表头给固定下来。(在线演示
    这个sticky还是跟fixed还是有些区别的,sticky是当它滚动到你想让它待的位置再停下来,当没有滚动到的时候,它就是页面内的普通元素。

  17. 图片横向设置100vw,如果出现竖直方向的滚动条,就会出现一个横向滚动条,怎么消除竖直方向滚动条带来的影响?

    这个看你的图片在哪个容器里面吧,正常情况下要是出现了,可以用overfl:hidden把它滚动条遮一下的其实。

  18. 父盒子div 宽度设为100px,子盒子不设置宽度但宽度会自动为100px,这算是继承了父盒子的宽度吗?但是之前有说宽度是不会继承的

    这不算继承的,和继承是两个概念,这是块级盒子的一个属性吧,默认宽度是100%。本身的宽高属性是不可继承的。

  19. 粘性布局 的滚动条会出现闪烁的原因是什么?

    没遇到过。

  20. 老师可以讲讲层叠上下文吗?

    如果在绝对定位这个场景里面,如果你是绝对定位,它脱离了正常的文档流,它可能会有好几个绝对定位的,这几个绝对定位的元素之间,该怎么样去决定它们在Z轴上的谁在上面谁在下面这样的一个关系呢?这个就涉及到那个层叠上下文嘛。正常情况下我们用z-index去控制它的谁在上谁在下的一个关系。但z-index是必须在同一个里面才可以层叠上下文进行比较,如果不在同一个层叠上下文里边,应该是没办法直接去比的,而是应该先去比层叠上下文谁在上谁在下,然后再去看里面的。
    层叠上下文就是说给了我们对不同的Z轴上的管理的机制嘛。这个层叠上下文的创建它也有一个比较复杂的创建的一个规则,总体的原则就是,需要你是定位元素且z-index不是0和auto,应该是这样的一个规则才会创建这样的一个上下文。这个在MDN的文档上应该是有比较详细的解释的。