理解CSS | 青训营笔记

91 阅读15分钟

这是我参与「第四届青训营 」笔记创作活动的第二天

CSS是什么?

Cascading Style Sheets

层叠样式表

1658765419544.png

选择器 属性名 属性值(后两个合起来为声明)

选择器就是选中html的某个标签(元素),为其定义样式

css由这一条条的样式规则组成

1658765745804.png

在页面引入css的三种方式

1658765822578.png

推荐第一种,内容和样式的分离,功能上的分工

开发范式上:组件式的开发

做到关注点分离

css是怎么应用到样式里面的?

1658766284759.png

每个dom树节点解析出它的css样式,得到渲染树(每个节点位置在哪里,其中每个属性的样式),最后渲染成完整的页面。

html与css有单独解析的过程,通过dom树把解析出的css附加到dom树上。

选择器

1658766530016.png

通配选择器

(*为选择所有)

* { color: red; font-size: 20px; }

标签选择器

a {}

类选择器

.done{}

id选择器

注:id为唯一值

#logo {}

属性选择器

[disabled]{}

input[type="password"]

a[href^="el"] {}

选中href属性值以el为开头的元素

a[href$=".jpg"] {}

选中href属性值以.jpg为结尾的元素

伪类

(不基于标签和属性定位元素)

状态性伪类

某个元素只有在处于某种状态才会被选中

我们可以用伪类选择器选择不同链接所处的状态,给不同状态下的链接定义样式。

链接的四种状态:

link 默认样式

active 鼠标按下去那刻的样式

focus 聚焦状态(按下去之后的状态)

若冒号前面没有,则默认给所有标签的这个状态定义样式

结构性伪类

根据dom节点在dom树出现的位置来决定是否选中该元素

可以通过元素在父级节点的相对位置来选中节点

li:first-child li父级的第一个节点

还有更复杂的:可以通过父级/同级的某个类型的标签指定,可以写表达式指定是基数/偶数/3的倍数的标签去赋予样式。

组合

可以通过组合的方式把标签放在一块:

1658850641905.png

选择器组

1658851075435.png

颜色

怎么去排文本的样式(——格式化文本),颜色是一方面

两种表示方法:

RGB表示

rgb(red,green,blue)数值0~255

#8fac87每两位数值以十六进制的形式展示,换算十进制也是0~255

(255,255,255)白色

(0,0,0)黑色

HSL表示

hsl(hue,saturation,lightness)

例:hsl(0,100%,50%)

调用关键字

例:blue,black,white...

alpha 透明度

在css实际上是不透明度(0~1),0为完全透明,1为完全覆盖

#ff000080

rgba(255,0,0,0.5)

hsla(0,100%,50%,0.5)

新一点的浏览器不要求写rgba,写rgb然后传四位参数也可以

字体

font-family

'字体族'的概念,要放多个,因为你的网页可能会被不同设备访问,不同设备可以安装拥有的字体是不一样的。

 h1 {
     font-family: Optima, Georgia, serif;
   }

serifsans-serif通用字体族,不是具体的某种字体,它是一类字体

css支持五类通用字体族:(只是一种风格/分类,一定要在定义的font-family最后加上其中一种通用字体族)

1658852813847.png

使用建议

~英文字体放在中文字体前面,避免出现中英文字体没有区分开的情况。

~字体列表最后写上通用字体族

Web Fonts

如果希望字体严格按照样式展示,可以把字体文件放在服务器上,指定字体的名字和字体所在的url,浏览器会先从url下载文件,然后再用这个字体格式进行渲染。可能会带来性能上的开销。

1658853022215.png

如果是中文,用的时候对原本的字体文件进行裁切,用不到的字的字体丢掉。

属性:

font-size

关键字:small,medium,large

长度:px,em

百分数:相当于父元素字体的大小

1658853815053.png

*em 是相对的单位,上面例子中:

 section h2 {
     font-size: 2em;
   }

与下面的同义

 section h2 {
     font-size: 40px;//2em*前面20px得到
   }

同理font-size: 80%;即20*80%px

这是相对的font-size

font-style: italic设置斜体

font-style: normal;非斜体

font-weight: 100重,字的粗细(100~900,400-normal,700-bold)

并不是所有字体都设置了这么多字重

 h1 {
     font-size: 30px;
     line-height: 45px;
   }
 ​
   p {
     font-size: 20px;
     line-height: 1.6;//相对行高,20*1.6px,推荐
   }

line-height行高,两行文字基准线的距离,默认的1.1~1.2非常不适合阅读

font综合各种字体属性

1658854623792.png

text-align对齐(left,center,right,justify)

justify实际上是将每个单词的间距进行拉伸,以达到两端对齐的效果。(相当于word的分散)

letter-spacing间距(px)

word-spacing间距(px)

text-indent首行缩进(px)

text-decoration(none,underline,line-through,overline)

white-space(normal,nowrap,pre,pre-wrap,pre-line)

空白符处理:

默认情况下,多个连续的空白/换行符会被合并成一个。

调试css

1658855147137.png

选择器的特异度

选择器的特殊程度越高,优先级越高

1658855669854.png

122>022

例一:样式覆盖

1658855899303.png

继承

1658856133227.png

p标签继承父节点font-size属性

css里,和文字相关的都是可以继承的。跟盒模型相关的属性都是不可继承的(比如height、宽度),但可以通过inherit显式继承。

 * {
   box-sizing: inherit;
 }
 // 所有元素box-sizing属性值都从父级继承,好处是可以通过一个容器就改变容器内所有元素的box-sizing属性值。
 html {
   box-sizing: border-box;
 }
 ​
 .some-widget {
   box-sizing: content-box;
 }

初始值

从元素父级一层一层往上找没找到属性值

当元素不可继承,而又没设置属性,就会用到初始值

1658856714286.png

transparent透明的

css求和过程

(html与css如何结合)

下面这个流程实际上是找到页面上每一个元素的每一个css属性值。(遍历)

filter中的css media-query(了解)这一阶段是匹配,得到所有的匹配值也就是Declare Values声明值。最终决定用哪个呢?

cascading瀑布,一层一层往下找,优先级,选出最终获胜的一个值

cascaded value层叠值(唯一)

Specified Value指定值(唯一)

计算值:不是所有的相对值都做计算,比如60%,计算时不会去做一个转换,而会在formating再去做进一步转换。(关键字inherit,百分百60%)

constraining另一个作用是在设置最大宽度为400px而计算出来的是500px时,使实际值为400px

完整流程图:

计算值

浏览器拿到css后,可以马上算出来或者转换出来的相对值。

单纯通过html和css就能计算出的值。

比如:

此标签设置了1.2em,父级设置20px,计算20*1.2px为当前标签font-size。

img的相对地址+当前页面url->绝对地址

使用值

需要把渲染规则拿到渲染环境里,得到浏览器宽度是多少才能进一步转换得到的值。需要实际布局才能决定的值放在formatting阶段去计算。

不能单纯通过html和css就能计算出的值。

例子:百分比

子元素继承的是父元素的计算值!

实践:容器font-size1.2em,h1设置为100px,看h1行高

不是100*1.2px,而是根据父级的计算值,父级的行高计算出来后给子级继承

布局

三种布局方式:

常规流/文档流(normal flow):块级、行级规则

浮动:图文混排。把图片设置为浮动,做成文字环绕图片的效果

绝对定位:完全脱离常规文档流进行绝对定位。盖在常规流上面,可以任意改变元素的位置,而不会对常规流造成什么影响。

会有嵌套,相当于给元素内创建一个新的流

display:flow-root(流的源头)

盒模型

内容、内边距、边框、外边距

1658913551403.png

content内容

auto由浏览器根据其他属性决定,是怎么决定的?

1658913710977.png

1658913725176.png

如果容器高度为auto,需要依赖内容高度确定,内容是百分数是不行的。

height如果为百分数,要确定容器(父级)能不能确定一个确切的高度,或者容器一层一层写了很多高度有继承。

1658913749910.png

padding内边距

(px / 百分数-相对容器的宽度)

一个值:上下左右

两个值:上下 左右

四个值:上 右 下 左(顺时针)

border边框

指定容器边框样式(none/solid/dashed/dotted)、粗细、颜色。

三种属性: border-width border-style border-color

四个方向: border-left border-right border-top border-bottom

可以灵活组合

 border: 1px solid #ccc;
 ​
 border-left: 1px solid #ccc;
 border-right: 2px dotted red;
 ​
 border-width: 1px 2px 3px 4px;
 border-style: solid;
 border-color: green blue;
 ​
 border-left-width: 3px;
 border-top-color: #f00;

当把容器元素宽度和高度设置为0(默认内容的宽高),可以用来画三角形(设置透明、颜色、粗细)

margin外边距

指定元素四个方向的外边距

取值:长度、百分数、auto

百分数相对容器的宽度。

使用margin:auto居中

 margin-left: auto;
 margin-right: auto;

上面代码中,浏览器会取容器宽度减去元素宽度后的平均值。

margin collapse边距坍塌/合并/折叠(垂直方向上)

 .a {
     background: lightblue;
     height: 100px;
     margin-bottom: 100px;
   }
 ​
   .b {
     background: coral;
     height: 100px;
     margin-top: 100px;
   }

a与b的距离不是200px而是100px,取两者最大边距,而不是简单相加。方便文字排版。但有些时候不需要边距坍塌,这种情况是有办法解决的。

border-box

对比前面的content-box,指定width:100%结果不同。

实际项目中用border-box多一些。

 * {
     box-sizing: border-box;
 }
 // 指定使用border-box,默认是content-box

overflow

控制溢出

三个值:visible(默认),hidden,scroll(有滚动条),auto(超出了的滚动,没超出的就默认)

常规流

五种排版上下文里面,参与一种规则。

1658996091144.png

块级vs行级

1658996021577.png

行级的宽度和高度是由内容决定的。

1658996005361.png

行级排版上下文(IFC)
  • Inline Formatting Context (IFC)

  • 只包含行级盒子的容器会创建一个IFC

  • 例子:span标签,里面全是文字。

  • IFC 内的排版规则

    • 盒子在一行内水平摆放
    • 一行放不下时,换行显示
    • text-align 决定一行内盒子的水平对齐
    • vertical-align 决定一个盒子在行内的垂直对齐
    • 避开浮动(float)元素*
 <div>
   This is a paragraph of text with long word Honorificabilitudinitatibus. Here is an image
   <img src="https://assets.codepen.io/59477/cat.png" alt="cat">
   And <em>Inline Block</em>
 </div>
 ​
 <style>
   div {
     width: 10em;
     //overflow-wrap: break-word;
     background: #411;//褐色
   }
 ​
   em {
     display: inline-block;
     width: 3em;
     background: #33c;//蓝色
   }
 </style>

div是块级元素,但div里面全是行级元素,符合行级排版上下文

所以遵循像文字式从左到右摆放,一行显示不下时换行。但里面的inline-block元素、图片、一个英文单词不能被拆成两行。

overflow-wrap: break-word;使一个单词超出容器范围时换行。

块级排版上下文(BFC)
  • Block Formatting Context (BFC)

  • 某些容器会创建一个BFC:

    • 根元素,即html标签
    • 浮动、绝对定位、inline-block
    • Flex子项和Grid子项
    • overflow 值不是 visible 的块盒(overflow:hidden;)
    • display: flow-root;
  • BFC 内的排版规则:

    • 盒子从上到下摆放
    • 垂直 margin 合并
    • BFC 内盒子的 margin 不会与外面的合并 (如果不想要两个盒子的margin合并,可以把两个盒子分散到不同的BFC里面,一种方式是把一个个元素嵌套在div,然后把div设置成display: flow-root;overflow:hidden;,这样两个元素就分属于不同的BFC,两个不同的BFC不会重叠)
    • BFC 不会和浮动元素重叠*(清除浮动时用的技巧)

在常规流里,一个盒子内子集的盒子只能都是块级或者都是行级,块级从上到下摆放,行级从左到右一行一行摆放。但如果一个盒子打个比方是div,里面既有块级又有行级,那么浏览器怎么处理呢?

下面例子中,div是块级的,而文字是行级的,块级和行级盒子同属于一个父级,这时浏览器会创建两个匿名的块级盒子把文字包起来。匿名盒子:不是在html写的,在dom树也看不到,只有在排版时在css排版以前(?)有这样的元素存在,包裹着这两段文字。

行级元素的特性:以行为基本单位做排版。(留意第一行和第三行的红色边框) 但为什么会是一行?span是行级元素标签。一个span为一行,可以把div改为em然后把span内容复制多几行,看看效果就明白了。

 <span>
   This is a text and
   <div>block</div>
   and other text.
 </span>
 ​
 <style>
   span {
     line-height: 3;
     border: 2px solid red;
     background: coral;
   }
 ​
   div {
     line-height: 1.5;
     background: lime;
   }
 </style>

表格布局

FlexBox

在一个容器里面,有很多子元素,可以通过flex box的属性去控制里面的子元素。

  • 一种新的排版上下文

  • 它可以控制子级盒子的:

    • 摆放的流向 ( → ← ↑ ↓ )
    • 摆放顺序
    • 盒子宽度和高度
    • 水平和垂直方向的对齐
    • 是否允许折行(换行)
 .container {
     display: flex;
   }

让container创建一个flex布局上下文,里面的子元素行为受容器内的flex属性控制。

flex默认流向为从左到右。每个元素宽度默认由它内部内容决定。

属性:

flex-direction:摆放的流向 ( row→ row-reverse← column↓ column-reverse↑ )

1659179321158.png

对齐(主轴方向上)

justify

1659179395413.png

对齐(侧轴方向上)

align-items(默认值stretch,里面所有元素高度和容器高度相同)

1659189535686.png

baseline 所有子元素的基线对齐

align-self

align-items是设置在上下文/容器里面的,也可以针对某个特定的元素设置一个不同的样式。

1659189952193.png

order通过css控制页面摆放顺序,从小到大排列。

1659189969170.png

  • Flexibility
  • 可以设置子项的弹性:当容器有剩余空间时,会伸展;容器空间不够时,会收缩。
  • flex-grow 有剩余空间时的伸展能力
  • flex-shrink 容器空间不足时收缩的能力
  • flex-basis 没有伸展或收缩时的基础长度
 flex-grow: 2;
 flex-shrink: 0;

flex-grow

如果一个元素值为2,另一个值为1,那么按照2:1分配剩余空间

flex-shrink

值为0时不能压缩,剩余完全没有定义flex-shrink值的元素因为宽度相同所以压缩后仍然宽度相同。

flex综合属性,代表着子属性(flex-grow,flex-shrink,flex-basis)的集合

FLEX看文档查一下就好*
flex: 1flex-grow: 1;flex-shrink: 1;flex-basis: auto;
flex: 100pxflex-basis: 100px
flex: 2 1flex-grow: 2; flex-shrink: 1
flex: 1 100pxflex-grow: 1; flex-basis: 100px
flex: 2 0 100pxflex-grow: 2; flex-shrink: 0; flex-basis: 100px
flex: autoflex: 1 1 auto
flex: noneflex: 0 0 auto

flex- wrap:设置子元素的是否自动换行(在空间不够的情况下)和排列方向

Grid布局

1659190323236.png

display: grid

  • display: grid 使元素生成一个块级的 Grid 容器
  • 使用 grid-template 相关属性将容器划分为网格(二维)
  • 设置每一个子项占哪些行/列
 grid-template-columns: 100px 1fr 1fr;
 grid-template-rows: 100px 1fr

1fr,fraction一份,这里是把剩余的都占满

 grid-template-columns: 30% 30% auto;
 grid-template-rows: 100px auto

auto也是把剩余的占满

划分网格后,把子元素放在格子里,通过网格线grid line指定

通过区域的线标识区域。

两种写法:

 .a {
   grid-row-start: 1;
   grid-column-start: 1;
   grid-row-end: 3;
   grid-column-end: 3;
 }
 .a {
   grid-area: 1/1/3/3;
 }

如果指定中有重叠,排版也会重叠。

可以通过浏览器开发者工具检查,在display: grid;打开baseline

grid是最强大的布局。

浮动

实现文字环绕效果。

float:left;这么给图片靠左放置后,

p标签位置不受影响,只不过里面的行级元素会绕开图片。

其他浮动、清除浮动可以通过flex box、grid实现

绝对定位

position属性

属性值含义备注
static默认值,非定位元素静态,参与常规流里面的布局
relative相对自身原本位置偏移,不脱离文档流1+ 在常规流里面布局 2+ 相对于自己本应该在的位置进行偏移 3+ 使用top、bottom、left、right设置偏移长度 4+ 流内其他元素当它没有偏移一样布局
absolute绝对定位,相对非static祖先元素定位1+ 脱离常规流 2+ 相对于最近的非static祖先定位 3+ 使用top、bottom、left、right设置相对于祖先容器的位置 4+ 不会对流内元素布局造成影响,即当这个元素不存在
fixed相对于视口绝对定位1+ 脱离常规流 2+ 总是相对于窗口进行定位 3+
sticky看mdn文档 粘性定位 这个元素原本不在顶部,、滚动到顶部时让这个元素吸附在顶部不动。

学习 CSS 的几点建议

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