理解CSS | 青训营笔记

667 阅读18分钟

理解CSS

tips:全文共7100多个字,建议先收藏噢~

先在这里放一个网址,可以通过这个网址去查关于HTML、CSS、JS、HTTP的相关知识,知识准确度很高,而且很多都有中文版的,方便大家使用。

网址:developer.mozilla.org/zh-CN/ image.png

本文内容包含: image.png

为什么学习css

1996年苹果官网: image.png

2023年苹果官网: image.png

通过以上两张图能够发现,现在的页面具有以下特点:

  • 更丰富的交互行为和视觉效果
  • 能够承载和展现更多的信息量
  • 更精准的传递信息

css发展史

  • CSS 1 :始于1966年。
  • CSS 2 :诞生于1998年,添加定位,Z-index,media 属性。
  • CSS 2.1:诞生于2004~2011年,目前使用最广泛的版本(IE支持)
  • CSS 3:1999年开始起草,把CSS模块化,独立升级各功能。 image.png

基础知识

CSS:Cascading Style Sheet,层叠样式表。

Cascading规则

cascading层叠规则: image.png 我们一般写的样式都归类在作者样式表,作者样式表根据书写位置又分为三类:行内式、内嵌式、外部链接式,这三类样式的优先级要根据选择器的优先级确定。

<!-- html代码 -->
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <meta http-equiv="X-UA-Compatible" content="IE=edge" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Document</title>
    </head>
    <style>
        #title {
            color: red;
        }
    </style>
    <link rel="stylesheet" href="./test.css" type="text/css">
    <body>
        <h1 id="title" style="color: green;">title title title</h1>
    </body>
</html>
/* css样式 */
h1 {
    color: blue;
    font-size: 48px;
}

image.png

选择器

内联样式(写在标签内部的)1000,id选择器100,类和伪类10,元素选择器1,通配选择器0.当选择器中包含多种选择器时,需要将各种选择器的优先级相加然后再比较,但是多个相同级的选择器相加的结果不会超过上一个级别的优先级。(选择越详细精确,权重越高,优先级越高)

image.png

image.png

对于@import的样式,根据@import的顺序

对于link和style标签的样式,根据在document中的顺序决定

基础选择器:

  • *{ }:通配符选择器。选择所有的元素
  • E{ }:元素选择器。其中 E 为任何一个元素,如html、body、p、div等。
  • .class{ }:类选择器。定义时为class="classname",class值可以有多个,用空格隔开。
  • #id{ }:id选择器。定义时为id="idname",相同 id 只能有一个。
  • s1, s2, s3...sn{ }:群组选择器。一次性选择 多个选择器 所对应的元素。
  • s1s2s3...sn{ }:交集选择器。如选择 class 值为 hello 的 div 元素:div.hello{ }

关系选择器:

  • E F{ }:后代选择器。选择 E 元素的一个或多个和 F 相同的后代元素。
  • E>F{ }:子选择器。选择 E 元素的子元素 F。
  • E+F{ }:相邻兄弟选择器。选择紧挨着 E 元素的后一个兄弟 F 元素,如果 F 元素不是 E 元素的后一个兄弟元素,则选择不成功。
  • E~F{ }:兄弟选择器。选择 E 元素后面的所有 F 兄弟元素。
  •   <div class="父元素">
          <span class="子元素 元素1"></span>
          <span class="子元素 元素2 元素1的兄弟元素"></span>
          <span class="子元素 元素3 元素1的兄弟元素"></span>
      </div>
    

特性选择器:

  • E[att]:选择具有 att 特性的 E 元素,不考虑特性的值。如选择具有class属性的div元素div[class]
  • E[att="val"]:选择具有 att 特性且特性值等于 val 的 E 元素。如选择具有class属性为且 class 值为 name 的 div 元素div[class="name"]
  • E[att~="val"]:选择具有 att 特性且特性值为 用空格分隔的单词,其中一个单词为 val 的 E 元素(如<p class="my val">xdy</p>
  • E[att|="val"]:选择具有 att 特性且特性值为 用连接符分隔的字符串,并以 val 开头的 E 元素(如<h1 lang="en">hello<h1>或者<p lang="en-us">hello</p>都能被*[lang|="en"]选择,即选择特性 lang 的值为“en”或以“en-”开头的元素)
  • E[att^="val"]:选择具有 att 特性且特性值 以 val 开头的 E 元素。
  • E[att$="val"]:选择具有 att 特性且特性值为 以 val 结尾的字符串的 E 元素。
  • E[att*="val"]:选择具体 att 特性且特性值为 包含 val 的字符串的 E 元素。
  • ......

伪元素选择器(用::符号。一般会创建一个新的元素。所以是 伪的):

  • E::first-letter:设置元素内容第一个字符的样式(仅作用于块元素,一般用于制作首字下沉的效果)
  • E::before:设置在元素显示前发生的内容(一般将它和CSS的content属性一起使用,且所添加的内容无法选中)
  • E::after:设置在元素显示后发生的内容(一般将它和CSS的content属性一起使用,同before,可解决高度塌陷问题)
  • ......

伪类选择器:(用:符号。表示选择处于某一种特殊状态的元素)

  • E:nth-child(n):(n 表示第 n 个元素,从 0 开始的)(even 表示偶数位置的元素)(odd 表示奇数位置的元素)选择父元素的第几个子元素且该元素为 E。-child是在所有子元素中找匹配的元素,而-of-type 是在同类型中找匹配的元素
  • E:not(F):用于剔除含 F 属性的元素。
  • ......

开发小提示:

选择器尽量少用 id;

尽量不要用 !important;

自己的样式加在引用库样式的后面。

隐藏福利~ 关注gong zhong hao【安酱xx】,输入【js高级学习笔记】获取3万多字的js高级笔记噢~,输入【html+css】获取html+css学习笔记(这个是早期记录的笔记,有点混乱~)

继承

image.png

值和单位

image.png

盒模型

image.png 外边距(margin): 可正可负可auto

  • 提供4个数据:(如margin:20px 20% 0.2em 20px;)将依次作用于上,右,下,左。(顺时针)
  • 提供3个数据:将依次作用于上,左右,下
  • 提供2个数据:将依次作用于上下,左右
  • 提供1个数据:将依次作用于上下左右

margin负值最终减少的是外界可感知的宽高。

image.png

不提倡使用负外边距,因为这会增加代码复杂度。

内边距(padding): 不可为负,其余同上。

由盒模型的特性能够实现一些展现形式: image.png

<!-- 三角形 -->
<div class="triangle-bottom"></div>

.triangle-bottom{
    width: 0;
    height: 0;
    border-left: 50px solid transparent;
    border-right: 50px solid transparent;
    border-bottom: 50px solid red;
}
<!-- 固定比例矩形,也可以使用新特性aspect-ratio:https://developer.mozilla.org/zh-CN/docs/Web/CSS/aspect-ratio -->
<div class="ratio-box"></div>

.ratio-box{
    /* 新特性写法 */
    /* aspect-ratio: 4 / 3;
    background-color: greenyellow; */
    
    background-color: cadetblue;
    width: 100%;
    height: 0;
    padding: 0;
    /* 是父元素宽度的75% */
    padding-bottom: 75%;
}
<!-- 水平居中 -->
    <div class="wrap">
        <div class="h-center"></div>
    </div>
    
.wrap{
    width: 100%;
    height: 100%;
    border: 1px dashed grey;
}
.h-center{
    width: 100px;
    height: 50px;
    background-color: navajowhite;
    /* 使用auto将左右2侧的剩余空间均分 */
    margin: 10px auto;
}
<!-- 渐变边框,这块有点疑问 -->
<div class="awesome-border"></div>

.awesome-border{
    width: 150px;
    height: 100px;
    border: 8px solid transparent;
    border-radius: 12px;
    background-clip: padding-box,border-box;
    background-origin: padding-box,border-box;
    background-image: linear-gradient(to right,#fff,#fff),linear-gradient(135deg,#e941ab,#a557ef);
}

布局和定位

image.png image.png

常规流中的任意盒子都只会参与一种格式化上下文。 image.png

BFC

image.png

外边距塌陷或外边距重叠问题: image.png

IFC

内联格式化上下文: image.png

实现单行元素居中对齐常用方式:

  • line-heightheight设置为相同的高度即可
  • 使用flex布局的align-items:center即可

flex布局

flex布局学习参考地址:www.ruanyifeng.com/blog/2015/0…

flex布局实例地址:www.ruanyifeng.com/blog/2015/0…

开启了 flex 布局的元素叫 flex container;flex container 里面的直接子元素flex item

flex item 的布局将受 flex container 属性的设置来进行控制和布局;flex item 不再严格区分块级元素和行内元素;flex item 默认情况下是包裹内容的,但是可以设置宽度和高度。

display: flex:flex container 以 block-level 形式存在,即块元素。

display: inline-flex:flex container 以 inline-level 形式存在,即行内元素。

flex 模型示意图:

1660569413024.png

flex-container 父元素属性

flex-direction:该属性决定主轴的方向,有 4 种取值:row(默认值)、row-reverse、column、column-reverse。

1660570251171.png

flex-wrap:决定元素单行显示还是多行显示。有 3 种取值:nowrap(默认值)、wrap(单行显示)、wrap-reverse(修改了交叉轴,即从下到上排列)。

如果一行显示不下,那么其宽度或者高度将会被压缩。也就是设置的宽度与其显示的真正宽度没有必然关系

flex-flow:是 flex-direction 和 flex-wrap 的简写属性。任何顺序,都是可省略的。

justify-content:该属性决定了 flex-item 在 main axis 上的对齐方式。 有以下常见可选值: 1660572086740.png

align-items:该属性决定了 flex-item 在 cross axis 上的对齐方式。 有以下常见可选值:

1660573608967.png

基准线是 flex-item 中的文本底部的水平线。

align-content:space-evenly 有兼容性问题。 在 flex container 设置高度后有剩余空间才可能会设置该属性,但是一般开发中都不会设置盒子的高度,而是由内容撑开。(多行)

1660616599539.png

flex-item 子元素属性

order:决定 flex-items 的显示顺序。(使用 css 来决定显示的顺序)

值为任意整数(正整数,负整数,0),默认值为 0;顺序按照值从小到大依次排。

align-self:单独设置某一个 flex-item 在 cross axis 上的排布方式。

有 6 种取值:auto(默认值)、stretch、flex-start、flex-end、center、baseline。

flex-grow:决定 了 flex items 如何扩展或拉伸或成长

值为任意非负数字(正整数、正小数,0),默认值为 0 。(设置小数有不一样的效果)

注意:当 flex container 在 main axis 上有剩余空间时,flex-grow 属性才会有效。 flex items 扩展后的最终 size 不能超过 max-width 或者 max-height 。

flex-shrink:决定了 flex items 如何缩小。 值为任意非负数字(正整数、正小数,0),默认值为 1

注意:当 flex items 在 main axis 方向上超过了 flex container 的 size ,flex-shrink 才会生效。 flex items 缩小后的最终 size 不能小于 min-width 或者 min-height

flex-basis:用来设置 flex items 在 mian axis 方向上的 base size(基本尺寸)。 值:auto(默认值),具体的宽度数值。

注意:如果设置了 flex-basis 之后,一个内容在设置的宽度中不能全部显示,则会被拉伸。最终显示的大小会被如下顺序因素影响(优先级从高到低):

  1. max-width、max-height、min-width、min-height。
  2. flex-basis
  3. width、height
  4. 内容本身的 size

flex:是 flex-grow 、flex-basis 和 flex-shrink 的缩写属性。 值:none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ] (该语法可通过将鼠标悬浮在属性上进行查看) 1660621356412.png

浏览器可快捷查看各个属性的显示样式: image.png

查看属性的具体效果: image.png

grid布局

2017年推出的布局方式,可以定义由行和列组成二维布局,然后将元素放置到网格中。元素可以只占其中一个单元格,也可以占据多行或多列。

通过 grid-template-columns 和 grid-template-rows 属性来定义网格中的列和行。如现在创建了一个网格,包含了三个 200 像素宽的列轨道。子元素将在网格上每个网格单元中展开。

<div class="wrapper">
   <div>One</div>
   <div>Two</div>
   <div>Three</div>
   <div>Four</div>
   <div>Five</div>
</div>
.wrapper {
  display: grid;
  grid-template-columns: 200px 200px 200px;
}

image.png

轨道可以使用任何长度单位进行定义。网格还引入了一个另外的长度单位来帮助我们创建灵活的网格轨道。新的fr单位代表网格容器中可用空间的一等份。

.wrapper {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}

image.png

grid-template-areas CSS 属性是网格区域 grid areas 在 CSS 中的特定命名。 image.png

学习更多建议查看以下 MDN 学习地址。

MDN 学习地址:developer.mozilla.org/zh-CN/docs/…

grid和flex布局的使用策略

使用建议: image.png

学习参考地址:developer.mozilla.org/zh-CN/docs/…

position定位

为了我们可以在文档流的基础上,让元素移动,做出更多灵活的改变。当position属性的取值非static的时候,可以使用top, right, bottom, left对其进行定位。 image.png

层叠上下文

层叠上下文:The Stacking Context。是对HTML元素的三维构想,将元素沿着垂直屏幕的虚构的 Z 轴排开。 image.png

浏览器渲染部分过程示意图(英文):www.chromium.org/developers/…

形成条件

文档中的层叠上下文由满足以下任意一个条件的元素形成:

  • 文档根元素(<html>);
  • css3之前
    • position 值为 absolute(绝对定位)或 relative(相对定位)且 z-index 值不为 auto 的元素;
    • position 值为 fixed(固定定位)或 sticky(粘滞定位)的元素(沾滞定位适配所有移动设备上的浏览器,但老的桌面浏览器不支持);
    • flex (flex) 容器的子元素,且 z-index 值不为 auto
    • grid (grid) 容器的子元素,且 z-index 值不为 auto
  • opacity 属性值小于 1 的元素(参见 the specification for opacity);
  • mix-blend-mode 属性值不为 normal 的元素;
  • 以下任意属性值不为 none 的元素:
  • isolation 属性值为 isolate 的元素;
  • will-change 值设定了任一属性而该属性在 non-initial 值时会创建层叠上下文的元素(参考这篇文章);
  • contain 属性值为 layoutpaint 或包含它们其中之一的合成值(比如 contain: strictcontain: content)的元素。

在层叠上下文中,子元素同样也按照上面解释的规则进行层叠。重要的是,其子级层叠上下文的 z-index 值只在父级中才有意义。子级层叠上下文被自动视为父级层叠上下文的一个独立单元。

总结:

  • 层叠上下文可以包含在其他层叠上下文中,并且一起创建一个层叠上下文的层级。
  • 每个层叠上下文都完全独立于它的兄弟元素:当处理层叠时只考虑子元素。
  • 每个层叠上下文都是自包含的:当一个元素的内容发生层叠后,该元素将被作为整体在父级层叠上下文中按顺序进行层叠。

层叠上下文介绍:developer.mozilla.org/zh-CN/docs/…

层叠顺序

层叠顺序不仅指不同的层叠上下文的顺序,同一个层叠上下文内,元素间也有顺序: image.png

z-index 只在同一个层叠上下文内比较

子元素的z-index无法超越父元素的z-index显示顺序 image.png

编写 z-index 的建议: image.png

变形、过渡、动画

transform 变形

image.png

image.png

在线试一试: codepen.io/yao-mo/pen/…

transition 过渡

通过指定某些元素属性从一种起始状态,在-段时间内以某种变化节奏,过渡到终止状态。

语法:transition: <property> <duration> <timing-function> <delay> image.png

animation 动画

image.png

animation 属性参考:developer.mozilla.org/zh-CN/docs/…

css 动画样式参考:animate.style/

transform、transition、animation性能

image.png

重绘(repaint):是指一个元素外观属性的变化触发浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

回流(reflow):当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变需要重新构建,这就是回流。每个页面至少需要一次回流,就是在页面第一次加载的时候。

重绘和回流的关系:在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。

所以,回流必定会引发重绘,但重绘不一定会引发回流

硬件加速详情:www.chromium.org/developers/…

动画性能相关深入了解:fed.taobao.org/blog/taofed…

响应式设计

响应式设计原则

  • 优先选用流式布局,如百分比、flex、 grid等
  • 使用响应式图片,匹配尺寸,节省带宽
  • 使用媒体查询为不同的设备类型做适配
  • 给移动端设备设置简单、统一的视口
  • 使用相对长度,em、rem、vw 做为长度度量

媒体查询

媒体查询允许某些样式只在页面满足特定条件时才生效。我们可以将媒体类型(如screen、print) 以及媒体特性(如视口宽度、屏幕比例、设备方向:横向或纵向)做为约束条件。

使用媒体查询的一些Tips:

  • 媒体查询同样遵循cascading层叠覆盖原则,min- 和max-选择一个
  • 由于设备的多样化逐渐不可枚举,断点的选择尽量根据内容选择,而不是屏幕大小
  • 由于断点的增加会增加样式处理的复杂度,所以尽量减少断点

image.png

媒体查询学习参考:developer.mozilla.org/zh-CN/docs/…

设备像素

设备像素(物理像素) :显示器上绘制的最小单位,显示屏通过控制每个像素点的颜色,使屏幕显示出不同的图像。

设备像素和设备相关,屏幕从工厂出来那天起,它上面的物理像素点就固定不变了。

image.png

CSS像素

CSS像素也叫参考像素。CSS像素(reference pixel) 其实是一个视角单位。规范给出的定义是,1css像素是从一臂之遥看解析度为96DPI (即1英寸96点)的设备输出时,1点(即1/96英寸)的视角。

通常认为常人臂长为28英寸,那么视线与水平线的夹角是:(1/96)in / (28in* 2 * PI/ 360deg) = 0.0213度 image.png

存在意义:保证在不同设备上的阅读体验是相对一致的。

image.png

image.png

viewport

布局视口(viewport)是页面中html元素(根元素)的包含块,默认情况下,window.document.documentElement.clientWidth 就是viewport的宽度。在移动设备中,默认的布局视口由于历史兼容pc屏幕的原因,并不符合需求,我们经常需要用<meta>标签对viewport进行设定,来完成移动端设备的适配。 image.png

移动端 viewport 的 meta 标签中的属性:

  • width
  • height
  • initial-scale
  • minimum-scale
  • maximum-scale
  • user-scalable:是否允许用户缩放

initial-scale在未设定时,如果width设定了,那么它会自动设置放缩值:initial-scale =屏幕宽度(例子中是390) / 980 ≈ 0.398。相比scale=1的时候,缩小了0.398倍

image.png

<meta name="viewport" content="width=device-width, initial-scale=1.0">

相对长度

em image.png

rem:根据根元素的字体大小确定。通过伪类:root或者html选择器选定。由于是根元素的font-size,所以不会像 em 那样出现多重嵌套问题,减少了复杂性,同时作为一个相对单位,可以进行适配放缩,可以用来做响应式布局. image.png

vw 和 vh:vw:视窗宽度的1%。vh:视窗高度的1%。同样,vw 也可以作为响应式布局的基准单位。由于vw天然是视口宽度的1%,所以不需要js动态配置。和rem方案类似,方案设定可以如下: image.png

移动端页面适配方案参考:www.w3cplus.com/css/vw-for-…

CSS生态相关

因为目前CSS的可编程性较差,不可维护性较高,代码污染啊等等问题催生出一系列的处理器。

常见样式处理流程

image.png

语言增强-CSS预处理器

image.png

预处理器如何提高研发效率?

  • 自定义变量:提高可复用性image.png
  • 嵌套、作用域:避免全局污染、结构层次清晰、减少复杂组合选择器image.png
  • mixins、继承:提高可复用性、可维护性image.png
  • 操作符、条件或循环语句、自定义函数:提高可编程能力、增加灵活性image.png

SCSS、less、stylus简单对比: image.png

语言增强-CSS后处理器

image.png

cssnano:cssnano.co/

stylelint:github.com/stylelint/s…

autoprefixer:github.com/postcss/aut…

postcss-custom-properties:github.com/csstools/po…

postcss-custom-media:github.com/csstools/po…

postcss-nested:github.com/postcss/pos…

doiuse:github.com/anandthakke…

postcss pluginspostcss.org/docs/postcs…

postcss 机制浅析

image.png

AST抽象语法树格式化网址:astexplorer.net/

工程架构-CSS模块化

CSS Module就是为了解决全局污染问题出现的方案,解决CSS全局污染,本质上是保证样式集合对应的选择器是唯一的,从这个角度看,主流的单纯针对于防止全局污染的方案大概有: image.png

css-loader:github.com/webpack-con…

postcss-module:github.com/webpack-con…

css-modulesgithub.com/css-modules…

工程架构-CSS in JS

将应用的CSS样式写在JavaScript文件里面,利用js动态生成css。

  • inline-style:代表radium(已弃用)
  • unique classname:代表styled-component

image.png

css in js playground(styled-component例子):www.cssinjsplayground.com/?activeModu…

工程架构-styled component机制浅析

image.png

css in js 优缺点

image.png

工程架构-CSS原子化

原子化CSS是一种CSS的架构方式,它倾向于小巧且用途单一的class,并以视觉效果进行命名。 image.png

现有的库或框架:

tailwind:tailwindui.com/

windicss:cn.windicss.org/

tachyons:tachyons.io/

unocss:github.com/unocss/unoc…

Tailwind基本使用: image.png

CSS原子化优缺点

image.png

Facebook重构拥抱 atomic css:sebastienlorber.com/atomic-css-…

总结

image.png

资源网址

知识点与某节关联性较大,则该节也会将网址贴出。这里做一个简单总结(部分地址都是MDN中的,就不重复贴出,直接在网站内搜索即可)。