深入理解CSS

1,134 阅读17分钟

前言

本文主要是对CSS常用的知识点进行梳理和复习。本文主要内容为:

  • CSS3核心思想
  • 响应式
  • 堆叠上下文
  • 常见布局:float布局、flex布局、grid布局
  • 常见动画:Fullpage、轮播、3D变化
  • 常见组件:表单美化常用工具
  • CSS必背知识

CSS3核心思想

从历史角度

问:你知道CSS的发明者是谁吗? 答:???👉🏻 维基百科

截屏2021-10-26 下午2.47.52.png 以上是用谷歌搜索出来的答案。 在没有 CSS 之前, HTML 自己是自带属性的👇 截屏2021-10-26 下午2.58.00.png 那个时候的需求不复杂,大家只是写写文章,后来大家对样式的的要求越来越复杂,现有的 HTML 无法满足,于是大家就想有没有一个东西可以选到这个标签,于是就有了选择器的概念,故而发明了选择器、属性、值,可是这些远远不能满足当时的需求,于是乎浏览器就自己加属性,但是大部分人不会CSS,为了让学术工作者可以专心的写文,于是CSS直接引入就可以自动改变了样式

css 主要用来 写文章 和 打印文章 media="print" 你要啥功能我就加啥属性,于是便有了颜色属性、图文混排(float: left)、绝对定位... CSS的很多属性(效果)都是可以抄出来的(不需要复杂的逻辑)

不正交的表现

  1. 各属性之间相互影响
  • margin V.S. border margin合并问题,为啥加了border就不会合并了???一开始不和并不行吗?我改border,为何会变margin,一开始不合并不行吗? 截屏2021-10-26 下午3.55.59.png 为何display:table /display:flex 会隔开呢? 截屏2021-10-26 下午4.02.29.png 截屏2021-10-26 下午4.04.48.png

父元素没加 border 前 截屏2021-10-26 下午4.14.09.png 加了后 截屏2021-10-26 下午4.16.15.png 这里有篇关于 BFC 的文章 👉🏻 你或许会找到答案 「BFC」块级格式化上下文 到底是个啥???

  • 小圆点 V.S. display display 默认 display: list-item; 我把它改成别的 display 其他的属性,小圆点就不见了

  • position: absolute V.S. display: inline 被position后,它只改变 inline inline-block 截屏2021-10-26 下午4.42.38.png 为啥那么反人类呢?

  1. 各元素之间相互影响
  • position: fixed V.S. transform 正常来说它应该在左下角的,可是为啥加了 transform 后,明明是 fixed 定位, 为啥你还给我加了绝对定位的东西?为啥就不能出现在我想要的地方呢? 截屏2021-10-26 下午4.54.33.png
  • float 影响 inline 元素 为啥文字会被浮动元素影响?
    最初浮动元素是用来做文图混排的,需求就是文字环绕图片,故 hone 就会自动去寻找浮动元素的边缘去环绕着它。

截屏2021-10-26 下午5.08.00.png 那它为啥不影响它旁边的div啊?因为它浮动了啊,那为啥浮起来了还能影响这个div的内容?因为浮动元素的初心在一开始并没有想做成真正的浮动,只是为了做图文混排(通过float属性来实现),这个名字会让我们以为它浮起来了,实际它没有浮起来。

CSS学习的简单点

背一些基本套路

截屏2021-10-26 下午6.59.59.png

  1. 水平居中 在块级元素中
  • child 宽度不确定, margin-left:20px; margin-right:20px;
  • child 宽度确定,margin-left:auto; margin-right:auto;

在行内块元素中:text-align: center;

  1. 垂直居中
    时刻避免parent高度确定的情况
    👉🏻 垂直居中的10种法子 点这里
    兼容 IE 用table ,其他的都可以用 Flex

使用工具

  1. CSS 3 Generator
  2. 盒子阴影
  3. clip 还有很多我就不一一介绍了...

宽度与高度

如果CSS里面有大量的宽度、高度,那么CSS就是有问题,因为对CSS的高度和宽度理解的不深刻。

文档流(Normal Flow)

块级元素/内联元素的宽高

  • 请问以下元素的高度是多少? 截屏2021-10-26 下午10.01.27.png
  • 你会想到是这个吗?那是啥导致的?行高吗? 截屏2021-10-26 下午10.04.26.png
  • 来看看 截屏2021-10-26 下午10.07.48.png 是nomal!!!,假设是它导致的,那么 28.8/20 = 1.44, 行高默认 1.44, 这对吗? 我认为这种推理不严谨, 如果换一个字体呢?
    以下是默认字体 截屏2021-10-26 下午10.18.34.png 改成 Tahoma 后 截屏2021-10-26 下午10.18.05.png 是的,你没有看错,它变了🙃,那么是因为不同字体对应的行高不一样吗?
    那每一种字体对应的行高是多少???😳😳😳 🚑🚑🚑🚑
    首先我们要知道字体相关知识:
  • 字和字之间是通过基线对齐的,而不是中线对齐的
  • 两排字的时候就会挨在一起 截屏2021-10-26 下午10.36.35.png
  • 故而设计师在设计字体的时候会给一个建议行高 于是得到了默认的行高就是字体设计师写进去的建议行高。 这就是为啥写font-size: 20px的时候,它div的高度却是一个不确定的值。为啥呢?因为上面的28.8是由字体的设计师建议的,要想写死的话给一个line-height: 30px那么它就不会变。

结论

当我们在 div 里面写一个 1 的时候,那么这个 div 的高度是由 (是由这个字的字体) + (它建议的行高) 确定的,跟这个字有多大没关系。

截屏2021-10-26 下午11.19.40.png 这个 div 的高度是由行高确定的。

如果 div 里面只有一个内联元素,那么 div 的高度,就是这个内联元素这一行的行高,这一行(行盒)。

截屏2021-10-26 下午11.25.30.png 为啥我打了很多空格,它只显示一个空格,因为 html 会把它多的空格给缩起来, 给它加上   (no break space)它就可以空两行,或者用全角空格。不同字体的空格宽度是不一样的,不同字体空格的宽度是由设计师确定的。

text-align: justify;

多行文字,没给这个属性是没有靠边的 截屏2021-10-26 下午11.47.42.png 加了后 截屏2021-10-26 下午11.41.54.png 那么又「该如何让 姓名 两端对齐呢?」
使用 :after

截屏2021-10-26 下午11.54.16.png

姓名两端对齐详细代码:

👉🏻 链接

在看 👇,一个回车两个空格,最终变成了一个空格 截屏2021-10-27 上午9.05.01.png 这就是 HTML 的特点,它会把所有内联元素之外的删掉,不显示在页面里,同时内联元素(inline、inline-block)之间的所有看不见的字符全部都显示成一个空格。 举例:ul列表的问题 👇 截屏2021-10-27 上午9.24.02.png 那如何解决? 那就不要用 inline-block 👇 截屏2021-10-27 上午9.20.30.png 如果内联元素足够多,那么一行容不下就会自动换行,这就叫做文档流。

在看一个例子 截屏2021-10-27 上午9.34.45.png 为啥会出现这种情况?
截屏2021-10-27 下午1.51.41.png
中文里的你好写成字母nihao,在中文的意思是两个字,而在英文的意思是1个字,上面的 ahhhh... 被识别为一个字,不过现实中没有这么长的英文,实在不行可以加连字符(-),加了连字符浏览器就会知道这是两个字。

截屏2021-10-27 下午1.57.48.png 那我可以从不加连字符也可以使其断开吗?
使用 word-braek: break-all; 意思是该什么时候断就什么时候断,不用管它是不是一个整体。

总结

当一个div里面只有内联元素的时候,div的高度是由什么确定的呢?如果是一行内容主要是由这一行的行高确定的,如果有多行内容,就是吧每一行的行高加起来一起算,如果中间有一串很长的字,那就用work-break: break-all

解决中文文字不对齐

p{
  text-align: justify;
}

文字溢出省略(多行)

div的宽度不是有文字绝定的

单行文本溢出省略

white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;

多行文本溢出省略

直接在谷歌搜 css multiple line ellipsis 截屏2021-10-27 下午2.18.38.png 3行

display: -webkit-box;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;

2行

display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden; 

适配IE的(不管了) 截屏2021-10-27 下午2.23.04.png

文字垂直居中

截屏2021-10-27 下午2.31.38.png 以上这种法子是可以让文字垂直居中,但是它有一个问题,一旦字多了(把单行省略去掉)就会出现以下情况 👇。 截屏2021-10-27 下午2.32.56.png 丑的很嘞,代码写的太死了,采用以下写法,文字就居中了 截屏2021-10-27 下午2.39.29.png 这样写的好处就死不会出现前面的那种bug 截屏2021-10-27 下午2.42.31.png 那么也就是说:高度 = 行高 + 上下内边距, 不要把高度写死!!!

margin合并

加margin 之前 截屏2021-10-27 下午2.53.19.png 加margin 之后 截屏2021-10-27 下午2.52.08.png 它没有变高!!!margin 合并了 截屏2021-10-27 下午3.00.53.png 截屏2021-10-27 下午3.03.17.png 如果父元素没有什么东西挡住 margin ,那么子元素的外边距就会和父元素的上下外边距合并
如果一个 div 里面,还有 div ,那么这个 div 的高度,就是由它里面 div 的高度 + padding + margin
那么该如何取消合并? 加个 padding 就可以了,其他的比如overflow: hidden 不建议使用,会用副作用

max/min-content及fit-content等width值

张鑫旭 fit-content

width:fit-content可以实现元素收缩效果的同时,保持原本的block水平状态

堆叠上下文

堆叠顺序

  1. background
  2. border
  3. 块级
  4. 浮动
  5. 内联
  6. z-index: 0
  7. z-index: + 截屏2021-10-27 下午6.12.20.png 如果是兄弟元素重叠,那么后面的盖在前面的身上 👉🏻 代码链接 截屏2021-10-27 下午4.43.52.png 截屏2021-10-27 下午5.17.46.png 截屏2021-10-27 下午5.27.29.png

堆叠上下文

MDN堆叠上下文 可以理解为堆叠作用域,就和 BFC 一样,无法定义,但是知道一些属性会触发堆叠上下文。

堆叠上下文主要影响z-index

移动端页面

配置环境:

npm i -g http-server
http-server -c-1

媒体查询

  • @media (max-width: 800px){} 如果媒体宽度满足 0~800px 之间就对其查询
  • @media (min-width: 801px){} 如果媒体宽度满足大于 800px 就对其查询
  • @media (min-width: 320px) and (max-width: 375px){} 如果媒体宽度满足 320~375px 就对其查询
  • <link rel="stylesheet" href="style.css" media="(max-width: 320px)"> 只有在设备满足最大宽度为320px的时候才会生效(提前下载好在满足这个条件时 link 才会生效)

meta viewport

<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">

视口
宽度=设备的宽度
用户是否可以缩放:不要
初始缩放倍数/最大缩放倍数/最小缩放倍数 1.0 \

viewport-fit=cover (为了适配iPhoneX)

iOS11 新增特性,苹果公司为了适配 iPhoneX 对现有 viewport meta 标签的一个扩展,用于设置网页在可视窗口的布局方式,可设置三个值:

  • contain: 可视窗口完全包含网页内容(左图)
  • cover:网页内容完全覆盖可视窗口(右图)
  • auto:默认值,跟 contain 表现一致

Flex布局

对于flex布局google一哈,大家都有系统的总结
我这里经常看的是天天写的 👉🏻链接🔗

然后在给大家推荐一些练习网站:

说到CSS那肯定的要看一下 张鑫旭 的博客了

截屏2021-10-23 下午5.15.21.png

使用flex布局的小效果:

Flex之前

主要使用的布局

截屏2021-10-28 上午9.03.19.png

  • normal flow
  • float + clear
  • position relative + absolute
  • display inline-block
  • 负 margin

Flex到来

  1. 块级布局侧重垂直方向、行内布局侧重水平方向,flex布局与方向无关
  2. flex布局可以实现空间自动分配、自动对对齐(flexble: 弹性、灵活)
  3. flex布局适用于简单的线性布局,更复杂的布局要交给 grid 布局

基本概念

截屏2021-10-28 上午9.16.11.png

flex container 的六个属性

截屏2021-10-28 上午9.32.19.png

  • flex-direction 方向 (默认 row, 从左到右排)

parent 加了 flex-direction: row-reverse;属性,从右到左排

截屏2021-10-28 上午9.34.08.png

parent 加了 flex-direction: column;属性,从上往下排

截屏2021-10-28 上午9.38.10.png

parent 加了 flex-direction: column-reverse;属性,从下往上排

  • flex-wrap 换行(flex默认不换行) parent 加了 flex-wrap: wrap;属性, 换行显示

截屏2021-10-28 上午9.46.55.png

  • flex-flow 上面两个的简写
  • justify-content 主轴方向对齐方式 justify-content: center

截屏2021-10-28 上午9.52.30.png

justify-content: space-between

截屏2021-10-28 上午9.53.57.png

justify-content: space-around

截屏2021-10-28 上午9.54.52.png

justify-content: flex-start 截屏2021-10-28 上午9.56.20.png

justify-content: flex-end 截屏2021-10-28 上午9.57.47.png

  • align-items 侧轴对齐方式 align-items: stretch;默认值,在高度没有写死的情况下,把所有的元素伸开(和最高的元素一样高) align-items: flex-start; 所有的元素往侧轴的起点靠,不要延伸

截屏2021-10-28 上午10.11.18.png

align-items: center; 垂直居中,往中间靠,不要延伸 截屏2021-10-28 上午10.12.13.png

  • align-content 多行/列 内容对齐方式 align-content: space-between;

截屏2021-10-28 上午10.23.49.png

align-content: flex-start

截屏2021-10-28 上午10.24.45.png

align-content: flex-end;

截屏2021-10-28 上午10.25.13.png

flex item 的六个属性

截屏2021-10-28 上午10.39.22.png

  • flex-grow 增长比例(空间过多时) flex-grow: 1; 它吃独食,剩余空间它都占了

截屏2021-10-28 上午10.40.10.png 按比例分配剩余空间 截屏2021-10-28 上午10.42.05.png

  • flex-shrink 收缩比例(空间不够时) flex-shrink: 0;经常用于图文混排的时候,让图片不flex。

  • flex-basis 默认大小(一般不用) 不写的话就是原始大小,写了这个属性就是按照它给的大小分配

  • flex 上面3个的缩写 flex: flex-grow flex-shrink flex-basis
    flex: 1 2 100px
    这个元素,在涨的时候它吃1份,缩的时候是它吐2份,原始100px

  • order (顺序,代替双飞翼)

截屏2021-10-28 上午10.50.28.png 以上是各大浏览器的兼容性 截屏2021-10-28 上午10.54.26.png

  • align-self 自身的对齐方式

可以让每个孩子,自己选择自己的对齐方式 截屏2021-10-28 上午11.18.45.png

例子

1.手机页面布局(topbar + main + tabs) 链接
2. 产品列表(ul>li*9) 使用flex布局的justify-content: space-between
3. pc页面布局 链接
4. 完美居中

display: flex;
justify-content: center; 
align-items: center;

Grid布局

概述

CSS网格布局(Grid Layout),一个二维系统,先定好网格在摆放元素,可以同时处理行列

参考文献

雷切尔·安德鲁(Rachel Andrew)
Chris Coyier

截屏2021-10-28 下午3.10.46.png

Grid容器的孩子(grid item)类似于 ul>li{} 而不是 ul li{}
网格线(grid line)虚拟的网格线
相邻网格线(grid track)
网格单元(grid cell)
网格区域(grid area)
针对父级设置网格线,把这一片区域进行逻辑划分,然后对于子元素让它放到哪个盒子上/哪些格子上,去做一个适当的对齐

Grid属性列表

Grid Container 的全部属性(设置网格相关信息)

  • display
  • grid-template-columns
  • grid-template-rows
  • grid-template-areas
  • grid-template
  • grid-column-gap
  • grid-row-gap
  • grid-gap
  • justify-items
  • align-items
  • justify-content
  • align-content
  • grid-auto-columns
  • grid-auto-rows
  • grid-auto-flow
  • grid

Grid Items 的全部属性(设置自己的位置/排列方式)

  • grid-column-start
  • grid-column-end
  • grid-row-start
  • grid-row-end
  • grid-column
  • grid-row
  • grid-area
  • justify-self
  • align-self

如何使用Grid布局

1.display(定义Grid属性)

  • grid - 生成一个块级(block-level)网格
  • inline-grid - 生成一个行级(inline-level)网格
  • subgrid - 如果你的 grid container 本身就是一个 grid item(即,嵌套网格),你可以使用这个属性来表示你想从它的父节点获取它的行/列的大小,而不是指定它自己的大小。
.container {
  display: grid | inline-grid | subgrid;
}

注意:columnfloatclear, 以及 vertical-align 对一个 grid container 没有影响

2.grid-template-columns / grid-template-rows(设置网格列/行)

.container {
  grid-template-columns: <track-size> ... | <line-name> <track-size> ...; 
  grid-template-rows: <track-size> ..  . | <line-name> <track-size> ...;
}

例子:

(如果未显示的给网格线命名),轨道值之间仅仅有空格时,网格线会被自动分配数字名称:

.container {
  grid-template-columns: 40px 50px auto 50px 40px;
  grid-template-rows: 25% 100px auto;
}

截屏2021-10-28 下午4.32.26.png

fr

fr可以将轨道大小设置为网格容器自由空间的一部分。 例如,下面的代码会将每个 grid item 为 grid container 宽度的三分之一:

.container {
  grid-template-columns: 1fr 1fr 1fr;
}

自由空间是在排除所有不可伸缩的 grid item 之后计算得到的。 在下面的示例中,fr单位可用的自由空间总量不包括50px:

.container {
  grid-template-columns: 1fr 50px 1fr 1fr;
}

3.grid-template-areas (网格如何摆放)

通过引用 grid-area属性指定的网格区域的名称来定义网格模板。 重复网格区域的名称导致内容扩展到这些单元格。 点号表示一个空单元格。 语法本身提供了网格结构的可视化。

值:

  • <grid-area-name> - 使用 grid-area 属性设置的网格区域的名称
  • . - 点号代表一个空网格单元
  • none - 没有定义网格区域
<div class="container">
  <div class="header">header</div>
  <div class="main">main</div>
  <div class="aside">aside</div>
  <div class="footer">footer</div>
</div>
.container {
  height: 100vh;
  border: 1px solid red;
  display: grid;
  grid-template-columns: 10% auto 10%;
  grid-template-rows: 50px auto 50px; 
  grid-template-areas: 
    "header header header"
    ".  main aside"
    "footer footer footer"
}

.header {
  grid-area: header;
  background: red;
}

.main {
  grid-area: main;
  background: blue;
}

.aside {
  grid-area: aside;
  background: yellow;
}

.footer {
  grid-area: footer;
  background: grey;
}

截屏2021-10-28 下午6.45.47.png 声明每一行有相同数量的单元格。 .来声明单个空单元格。 点号之间没有空格,代表了一个单一的单元格。

这个是在命名区域。 区域两端的网格线实际上是自动命名的。

grid-template

grid-template-rows、grid-template-columns、grid-template-areas的简写

  grid-template-columns: 10% auto 10%;
  grid-template-rows: 50px auto 50px; 
  grid-template-areas: 
    "header header header"
    ".  main aside"
    "footer footer footer"

以上简写为👇

  grid-template: 
    "header header header" 50px
    ". main aside" auto
    "footer footer footer" 50px
    / 10% auto 10%

"header header header" 50px指的是每一列都是header, 每行高度 50px

". main aside" auto 第一列是空单元格 第二列是 main 第三列是 aside,这一行的高度 auto

"footer footer footer" 50px 指的是每一列都是 footer,每行高度 50px
/ 10% auto 10% 这个的意思就是 行比例为 10% auto 10%

grid-column-gap / grid-row-gap 行列之间的缝隙

  grid-column-gap: 10px;
  grid-row-gap: 15px;

grid-column-gap 每一列
grid-row-gap 每一行

grid-gap grid-row-gap 和 grid-column-gap 的缩写

justify-items 水平方向

align-items 垂直方向

值:

  • start: 内容与网格区域的左端对齐
  • end: 内容与网格区域的右端对齐
  • center: 内容位于网格区域的中间位置
  • stretch: 内容宽度占据整个网格区域空间(这是默认值)

justify-content (网格容器内的网格的对齐方式)

类似 flex 布局的 justify-content 值:

  • start - 网格与网格容器的左边对齐
  • end - 网格与网格容器的右边对齐
  • center - 网格与网格容器的中间对齐
  • stretch - 调整g rid item 的大小,让宽度填充整个网格容器
  • space-around - 在 grid item 之间设置均等宽度的空白间隙,其外边缘间隙大小为中间空白间隙宽度的一半
  • space-between - 在 grid item 之间设置均等宽度空白间隙,其外边缘无间隙
  • space-evenly - 在每个 grid item 之间设置均等宽度的空白间隙,包括外边缘 align-content类似 flex 布局的 align-content

grid-auto-columns / grid-auto-rows

指定自动生成的网格轨道(又名隐式网格轨道)的大小

.item-a {
  grid-column: 1 / 2;
  grid-row: 2 / 3;
}
.item-b {
  grid-column: 5 / 6;
  grid-row: 2 / 3;
}

截屏2021-10-28 下午9.33.41.png

.container {
  grid-auto-columns: 60px;
}

指定隐式轨道的宽度 截屏2021-10-28 下午9.34.08.png

grid-auto-flow

值:

  • row - 告诉自动布局算法依次填充每行,根据需要添加新行
  • column - 告诉自动布局算法依次填充每列,根据需要添加新列
  • dense - 告诉自动布局算法,如果后面出现较小的 grid item,则尝试在网格中填充空洞
.item-a {
  grid-column: 1;
  grid-row: 1 / 3;
}
.item-e {
  grid-column: 5;
  grid-row: 1 / 3;
}

截屏2021-10-28 下午9.36.12.png

.container {
  display: grid;
  grid-template-columns: 60px 60px 60px 60px 60px;
  grid-template-rows: 30px 30px;
  grid-auto-flow: column;
}

截屏2021-10-28 下午9.36.38.png

Grid Items

.item-a {
  grid-column-start: 2;
  grid-column-end: five;
  grid-row-start: row1-start;
  grid-row-end: 3;
}

截屏2021-10-28 下午9.41.51.png

.item-b {
  grid-column-start: 1;
  grid-column-end: span col4-start;
  grid-row-start: 2
  grid-row-end: span 2
}

截屏2021-10-28 下午9.42.19.png

grid-column / grid-row

.item-c {
  grid-column: 3 / span 2;
  grid-row: third-line / 4;
}

截屏2021-10-28 下午9.43.12.png

grid-area

给一个网格项命名

.item-d {
  grid-area: header
}

作为 grid-row-start + grid-column-start + grid-row-end + grid-column-end 的简写:

.item-d {
  grid-area: 1 / col4-start / last-line / 6
}

截屏2021-10-28 下午9.44.08.png

justify-self

.item-a {
  justify-self: start;
}

截屏2021-10-28 下午9.45.18.png

.item-a {
  justify-self: end;
}

截屏2021-10-28 下午9.45.39.png

.item-a {
  justify-self: center;
}

截屏2021-10-28 下午9.46.07.png

.item-a {
  justify-self: stretch;
}

截屏2021-10-28 下午9.46.28.png

align-self

.item-a {
  align-self: start;
}

截屏2021-10-28 下午9.47.29.png

.item-a {
  align-self: end;
}

截屏2021-10-28 下午9.48.18.png

.item-a {
  align-self: center;
}

截屏2021-10-28 下午9.48.42.png

.item-a {
  align-self: stretch;
}

截屏2021-10-28 下午9.49.01.png

CSS常用布局套路

链接

动态 rem

链接