不管怎么说开始学全栈倒了血霉版CSS篇
简单了解CSS
1、什么是CSS
css=Cascading Style Sheet 层叠级联样式表。
2、快速入门
-
首先在idea中新建一个样式表,也就是stylesheet,在中选择css文件,如图所示:
-
新建一个文件夹,以及一个css文件夹,养成良好的习惯,联系格式,如图所示:
-
两种方式写,一种方式在任务html里面写,代码:
<!--规范,<style>可以编写css的代码,每一个声明最好使用分号结尾语法:选择器{声明1: ;声明2: ;}--><style>h1{font-size: 50px;color: orange;text-align: center;}</style>一种方式直接在新建的stylesheet中写,代码:
h1{font-size: 50px;color: orange;text-align: center;}然后在html中的head写代码引入该网页的编辑,代码如下:
<link rel="stylesheet" href="css/style.css">建议使用第二种规范,效果如图所示:
CSS的三种导入方式
-
内部样式:
<!--内部样式--> <style>h1{color: orange;} </style> -
行内样式:
<h1 style="colour:blue">恨 </h1> -
外部样式:
-
第一种写法,链接式:
<link rel="stylesheet" herf="css/style.css">h1{colour:purple; } -
第二种写法,导入式:
<style>@import url("css/style.css"); </style>目前第二种已经基本不用,但需了解。
-
其中三种排序方式的优先级为:就近原则,看谁离元素最近,一层一层覆盖,最后覆盖的那层。
CSS的三大特性
css有三个非常重要的特性:层叠性、继承性、优先级。
-
层叠性:相同选择器给设置相同的样式,此时一个样式就会覆盖(层叠)另一个冲突的样式。层叠性主要解决样式冲突的问题。
案例如下:<style>div{colour:yellow;font-size:50px;}div{colour:blue} </style>可以看到在上面的例子中div同时被赋予了相同的属性,但是属性之间发生了冲突,所以在解决这个问题的时候我们就可以参考css的层叠性,也就是。
层叠性原则:样式冲突,遵循的原则是就近原则,哪个样式离结构近,就执行哪个样式。
所以在上面的案例中,div最后是blue的。
但是注意这里的覆盖只覆盖相同的属性,上例中的font-size就不会被覆盖,因为没有冲突。 -
继承性:css中的子标签会继承亲标签的某些样式,如文本颜色和字号。简单理解就是:子承亲业。
判断一个属性会不会被继承主要是看它会不会影响到盒子模型。
经常看到的子元素宽度与亲元素宽度一样是正常的,因为这里的子元素宽度是默认值,默认值和继承值是完全不一样的。
-
宽度的默认值逻辑
对于块级子元素,它的width默认是auto,也就是:不继承子元素的宽度,但是我会自动伸展,填满亲元素的内容区域,没有设限,无限延伸,这里的亲元素宽度更像是帮子元素圈了一块地,但是你不能说这是子元素的宽度。
-
高度的默认值逻辑
子元素的height默认值也是auto,它的含义是:不继承亲元素的高度,高度完全由子元素里面的内容来决定。
恰当使用继承可以简化代码,降低css样式的复杂性。
text-、font-、line-这些元素开头的可以继承,以及colour属性继承中有个特殊的存在,行高。
body{font:12px/1.5; }行高可以跟单位也可以不跟单位。
接下来的例子:
<style>body{color:pink;font:12px/1.5; }div{/*注意到这个div子元素继承了亲元素body的行高1.5,所以这里的行高px其实是12×1.5*/font-size:12px;}</style>在这里我产生疑问,因为我们之前提到过的em也是相对单位,而这里行高需要额外再乘以一个单位,所以我就想那他们两个不是一个意思吗?实际上不是的,因为当1.5后没有单位的时候,他只是继承了一个倍数,子元素的最终行高还需与子元素被设定的size进行乘法才能形成最终单位,而em的相对单位其实是像px一样,还是固定被继承的亲元素计算出来的具体像素值,固定为某个px值,并不受子元素字体大小影响。
-
-
优先级:当一个元素指定多个选择器,就会有优先级的产生。
核心概念是权重计算法,它不是简单的后写覆盖前写,而是给每种选择器都分配了一个四位数字的分数(从高到低记作a,b,c,d):
等级 选择器类型 权重贡献 类比 a 行内样式 (如 style="color: red;")1,0,0,0贴身上的标签 b ID 选择器 (如 #header)0,1,0,0身份证号 c 类选择器 ( .box)、属性选择器 ([type])、伪类 (:hover)0,0,1,0学号/工种 d 元素选择器 ( div)、伪元素 (::before)0,0,0,1名字 我让d老师又给我出了两道题,我发现了否定伪类<:not()>本身是没有权重的,只有其括号内的选择器产生权重。
伪类 自身权重 参数内选择器的权重是否向外传递? 关键理解 :is()0 是(取参数中最高值) 它像一个“代理”,用最高权限的那个参数的身份说话 :where()0 否(强制清零) 它是一个“匿名者”,参数身份全部作废 :not()0 是(参数正常计入) 它只做排除条件,不改变参数权重 :has()0 否(参数不向外传递) 它只负责“检查内部是否匹配”,外部权重完全由外部选择器决定 其中is是选权重最大值来当参数代表,where是将参数内的所有选择器的权重清零。has中的参数不向外传递。not不算自身的参数但是内部元素的参数正常计算。
在这里d老师给了我两个例子:
例1:
/* 规则 A */ .nav .item { color: blue; } /* 0,0,2,0 */ /* 规则 B */ #sidebar .item { color: red; } /* 0,1,1,0 */ /* 规则 C */ .nav a.item { color: green; } /* 0,0,2,1 */- 比较 A 和 B:B 的 ID 位是
1,A 是0→ B 胜。 - 比较 A 和 C:前三位相同,C 的
d位多 1(因为多了一个元素选择器a) → C 胜。
例2:
/* 规则 X */ ul > li span { } /* 0,0,0,3 (三个元素) */ /* 规则 Y */ ul li:first-child { } /* 0,0,1,2 (一个类伪类,两个元素) */虽然 X 在文件中位置靠后,但 Y 的权重更高(有伪类)。
在这个地方我向d老师提出了疑问,不过我现在发现我的疑问是因为对这两个例子产生了错误的理解,不过我觉得d老师的分析很好,所以在这里我将他贴出来:
关键点:CSS 权重不是十进制的,它不讲究“数量累加升级”。
请记住这个铁律:
一个 ID 的威力,永远大于一万个类。
我们可以把权重的四位数字想象成四个不同的箱子,分别装着不同面额的钱:
- 第一个箱子装的是 万元大钞(ID 位)
- 第二个箱子装的是 百元大钞(类/属性/伪类位)
- 第三个箱子装的是 一元硬币(元素/伪元素位)
比较规则:先看谁的万元大钞多,只有万元大钞一样多时,才看百元大钞。哪怕你有 9999 张百元大钞,也比不上对方手里的 1 张万元大钞。
优先级有三大“例外“与特殊规则:
-
!important(最高优先权,但不是权重)-
它直接打破权重体系。只要一条属性加了
!important,它会凌驾于所有普通声明之上。 -
陷阱:多个
!important冲突时,权重规则重新生效比较它们的a,b,c,d。p { color: red !important; } /* 胜出 */ #content p { color: blue; } /* 权重高,但没 important,输 */
-
-
继承样式(权重为 无)
- 比如给
body设color: black,里面的p会继承。 - 规则:直接作用于元素的任何选择器(哪怕权重是
0,0,0,1),都会覆盖继承来的样式。
- 层叠顺序的最终裁决
- 如果两个选择器 权重完全一样(例如都是
0,0,1,1),则最后出现的那个生效(这符合你学过的“层叠”直观感受)。
- 比如给
- 比较 A 和 B:B 的 ID 位是
CSS属性书写顺序
-
布局定位属性:display/position/float/clear/visbility/overflow
-
自身属性:width/height/margin/padding/border/background
-
文本属性:color/font/text-decoration/text-align/wertical-align/white-space/break-word
-
其它属性(CSS3):content/cursor/border-radius/box-shadow/text-shadow/background: linear-gradient
选择器
作用:选择页面上的某一个或者某一类元素
基本选择器
-
标签选择器
会选择到页面上所有这个标签的元素,格式如下:
h1{color: orange;background-color: #edd5b3;}p{color: orange; } -
类选择器
可以多个标签归类,是同一个class,可以复用。
格式如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>/*.class的名称{ }*/.1{color:blue;}.2{color:purple;}</style></head> <body><h1 class="1">恨</h1> <h1 class="2">恨</h1> <h1 class="2">爱</h1></body> </html>效果如下:
-
id选择器
id必须保证全局唯一,不遵循就近原则,id>class>标签
格式如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>/*#id名称{}*/#one{color: orange;}</style></head> <body><h1 id="one">喵</h1> <h1>喵</h1> <h1>喵</h1> <h1>喵</h1> <h1>喵</h1></body> </html>效果如下:
层次选择器
-
后代选择器:在某个元素的后面 太姥姥 姥姥 妈妈 我
/*后代选择器*/body p{background: blueviolet;} -
子选择器
/*子选择器*/ body>p{background: cadetblue; } -
相邻选择器:选择后面的一个同辈,只有一个,因为只有一个对下的邻区
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style>.active+p{background: orange; }</style> </head><body><p>p0</p> <p class="active">p1</p> <p>p2</p> <p>p3</p></body> </html>效果如下:
-
通用选择器:选择后面所有的同辈
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style> .active~p{background: #91a6fb; }</style> </head><body><p>p0</p><p class="active">p1</p> <p>p2</p> <p>p3</p><ul><li><p>p4</p></li><li><p>p5</p></li><li><p>p6</p></li> </ul><p>p7</p> <p>p8</p></body> </html>
结构伪类选择器
-
nth-child
:nth-child(n)选择亲元素下第n个子元素,且该元素必须同时满足前面的标签类型,计数从1 开始,n可以是数字、关键字或者公式。
/* 选中母元素的第 1 个子元素(等价于 :first-child) */ p:nth-child(1) { font-weight: bold; }/* 奇数子元素(1, 3, 5, ...) */ li:nth-child(odd) { color: red; }/* 从第 2 个开始,每隔 3 个选中(2, 5, 8, 11, ...) */ div:nth-child(3n+2) { border: 1px solid blue; }在这里由于那位老师的阐述,使我对亲元素是如何在nth-child中体现的产生问题,这个就是典型的呃得喝得思维。但我觉得那样讲解肯定会出现问题,为什么不直接讲该元素是在上一级元素也就是亲元素中的第几个,然后直接体现出来呢。
结构如下:
<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>Title</title><style> p:nth-child(1){color: orange; }</style> </head><body><p>p0</p><p>p1</p> <p>p2</p> <p>p3</p><ul><li>利益</li><li>里尔</li><li>离散</li></ul></body> </html>效果如图:
注意到常见误解:nth-child定义在子元素上,但依赖于母元素的子元素列表,并且它必须同时满足标签类型,否则选不中任何的元素。
典型错误例子:
<div><p>第1子元素 → 被 p:nth-child(1) 选中</p><span>第2子元素</span><p>第3子元素 → 被 p:nth-child(3) 选中</p> </div>p:nth-child(2)不选中任何元素,因为第二元素span不是p类型。
-
nth-of-type()
:nth-of-type()是将亲元素下同一类型的元素单独拎出来,从一开始排序,然后选中其中的第n个。
它不关心其它类型的子元素,只数相同标签名的孩子,排序是从上到下,按照在HTML中出现的顺序。
| 对比维度 | :nth-child(n) |
:nth-of-type(n) |
|---|---|---|
| 计数对象 | 亲元素的所有子元素(不分类型) | 亲元素中同类型子元素(相同标签名) |
| 类型匹配 | 必须同时满足标签类型和位置序号 | 只要求位置序号,自动限定标签类型 |
| 跳过其他类型 | 不跳过,其他类型会占位计数 | 跳过其他类型,只数同类 |
| 典型场景 | 需要精确控制第几个子元素(如表格隔行变色) | 需要控制同类型元素的第几个(如每个 section 下的第三个 p) |
-
动态伪类
-
:hover(悬停)
顾名思义,鼠标悬停在元素上时触发,代码如下。
<button class="btn">悬停我</button> <style> .btn:hover {background-color: gold;cursor: pointer; } </style>效果如图:
-
:active
元素被激活时,也就是鼠标按下没有松开时触发,代码如下:
<a href="#" class="link">点击按住我</a> <style> .link:active {color: red;font-weight: bold; } </style>效果如图:
-
:focus
元素获得焦点,如输入框被点击或按tab键聚焦,代码如下:
<input type="text" placeholder="点击我聚焦"> <style> input:focus {outline: 3px solid blue;background: #eee; } </style>效果如图:
-
:empty
选中没有任何子节点,包括文本节点的空元素,代码如下:
<div class="container"><div></div> <!-- 空元素,会被选中 --><div>有文字</div> <!-- 不会被选中 --><div> </div> <!-- 有空格文本,不算空 --> </div> <style> div:empty {width: 100px;height: 20px;background: red; } </style>效果如图:
-
-
否定伪类
:not(selector)用来选中不匹配给定选择器的元素,代码如下:
<ul class="list"><li>普通项</li><li class="special">特殊项</li><li>普通项</li> </ul> <style> .list li:not(.special) {color: blue; } </style>按照上文的代码也就是在list类里面不是special类的项变成蓝色,效果也确实如此:
-
表单相关伪类
-
:checked用来选中被选中的复选框(checkbox)或者单选框(radio),代码如下:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"><title>:checked 完整示例</title><style>/* 当复选框被选中时,紧邻的 span 文字变粗变绿 */input:checked + span {font-weight: bold;color: green;}</style> </head> <body><label><input type="checkbox"> <span>同意用户协议</span></label><br><label><input type="checkbox"> <span>订阅新闻邮件</span></label> </body> </html>我在这里卡住一小会,因为觉得一个叫checkbox一个叫radio,怎么和checked对应上了。这是一个典型的思维误区,导致误区的原因是前面学习的伪类选择器分别用.class的方式定义了类,以至于我短暂地将类与标签混淆,没有分清属性。其实这个问题应该在前面的聚焦就卡住,但是我应该是有点困了,又粗心大意觉得这块很好学习没有注意力集中,以至于到这里才发现思维漏洞。不过及时改正就是好的。
以及,d老师你也困了吗?还是装唐在这里阴我呢,没有给出完整代码在这里无中生让我沉思许久,何意味!
谁能想到在这里还能产生别的疑问呢,我似乎总是在这种问题上给自己找不必要的麻烦。在邻近选择器中的+后面带着的只是标签,更接近于查找意义,比如说我想要找
那么我就应该:+p。其实我觉得我之所以会混淆是因为学这个东西时候的例子正好是一群p,以此导致不必要的混乱,让我学习到这里的时候误以为+号跟着的是上文例子中[.active+p].active本身所指代的那个p标签,所以来到这里当例子给我的是[input:checked+span]时开始思考,明明只有一个span为何span还会变化。
实际上+后面的元素只是单纯的标签,没有任何意义。
-
:disabled与:enabled
:disabled表示选中禁用的表单控件,enabled表示选中可用的,代码如下:
<input type="text" disabled value="不可编辑"> <input type="text" value="可编辑"> <style> input:disabled {background: #ccc; } input:enabled {border: 2px solid green; } </style>效果图如下:
-
属性选择器
属性选择器就是,写一个方括号[],在里面写特征的名字,甚至可以写特征的值长什么样子,然后浏览器会找到这种标签,给他们化妆。
-
属性
最基础的属性选择器,这里看一下代码就可以:
<input type="text" required> <input type="text"> <style>[required] {border: 2px solid red;} </style> -
[属性="完全一样的值"]—有时候光看有没有属性不足以选出我们需要的项,所以我们还要看属性是什么。
比如type="text"和type="password"不一样。
语法:[属性="完全一样的值"]
这里是一个例子:
<input type="text" placeholder="我是文本"> <input type="password" placeholder="我是密码"> <input type="email" placeholder="我是邮箱"> <style>[type="text"] {background: lightyellow;} </style>只有与[type="text"]完全相符的input才会变成黄色。
-
[属性~="值"]—属性是一个词语列表,其中只要有一个词等于这个值就可以。
有些属性的值是用空格隔开的多个词,比如=class="box red big"。
~=的意思是:不管这些词怎么排列,只要某一个词完全等于你给的值,就选中。
也就是≈。
<!--选中所有class中含有warning的元素--> <div class="alert warning">警告!</div> <div class="warning error">错误警告</div> <div class="info">普通信息</div> <style>[class~="warning"] {background: orange;font-weight: bold;} </style>效果:前两个 div 都有橙色背景,第三个没有。
注意:
[class~="warning"]不会选中class="warnings",因为warnings不是完整单词。也不会选中class="big-warning",因为中间有短横线,必须是完整单词,以此和后文会提及到的*=加以区分。 -
[属性|="值"]—属性值等于"值"或者以"值-"开头
这个通常用于语言代码,比如
en、en-US、en-GB。
意思是:要么完全等于en,要么以en-开头。<!--选中所有 lang 属性是中文(zh 或 zh-xx)的元素--> <p lang="zh">中文</p> <p lang="zh-CN">中文(简体)</p> <p lang="zh-TW">中文(繁体)</p> <p lang="en">英文</p> <style>[lang|="zh"] {background: lightblue;} </style> -
[属性^="值"]—属性值以某几个字开头
像一个箭头,指向开头,[href="https"]的意思就是:href的值以https开头。
<!--给所有安全链接(https)加一个小锁标志--> <a href="https://bank.com">银行</a> <a href="http://old.com">老网站</a> <a href="https://shop.com">商店</a> <style>[href^="https"] {background: lightgreen;padding: 2px;} </style>效果:银行和商店链接有浅绿背景,老网站没有。
-
[属性$="值"]—属性以某几个字结尾
$像是尾巴,表示结尾,[src$=".jpg"]的意思就是:src的值以.jpg结尾。
<!--给所有 jpg 图片加红边框,png 图片不加--> <img src="photo.jpg"> <img src="icon.png"> <img src="background.jpg"> <style>[src$=".jpg"] {border: 4px solid red;} </style>效果:第一张和第三张有红边框。
-
[属性*="值"]—属性值里面任意位置包含某几个字,甚至是片段。
(*)表示在任何地方,[class *="btn"]的意思就是:不管在前面(btn)中间(xxxbtnxxx)后面(xxxbtn)只要出现btn这三个字母就选中,但是必须是这三个连在一起。
<!--选中所有 class 里面带有 btn 的按钮--> <button class="btn">按钮</button> <button class="big-btn">大按钮</button> <button class="btn-primary">主按钮</button> <button class="button">普通</button> <!-- 这个没有 btn 字符串,不选中 --> <style>[class*="btn"] {background: gold;} </style> -
组合使用—多个条件同时满足
我可以写多个方括号,表示”并且“:
<input type="text" required> <input type="text"> <input type="email" required> <style>[type="text"][required] {background: lightcoral;} </style> -
不区分大小写—在方括号最后写"i"
正常情况下,属性值区分大小写。
"text"和"TEXT"不一样。
但有时候你希望不管大写小写都匹配,可以加一个i。<!--匹配 type="text" 或 type="TEXT" 或 type="Text"--> <input type="text" placeholder="小写text"> <input type="TEXT" placeholder="大写TEXT"> <input type="email" placeholder="email"> <style>[type="text" i] {border: 3px solid purple;} </style>
通配符选择器
在CSS中,通配符选择器使用"*"定义,它表示选取页面中所有元素(标签),代码如下:
<style>*{color: red;}</style>
它对CSS权重没有任何贡献,是优先级最低的选择器之一,也就是(0,0,0,0)
注意*不会选中::before和::after伪元素,如果希望重置也包括它们,必须写:
*,*::before,*::after
美化网页
字体样式
字体粗细,字体大小,字体
<style>body{font-family:华文楷体;}h1{font-size:50px;}.p1{font-weight: inherit;}</style>
其中字体大小可以用px和em
px(像素),他是绝对单位,1px在屏幕上通常对应一个物理像素点,不随母元素变化。
em是相对单位,相对于当前元素的字体大小,如果当前元素没有显式设置,则继承母元素的font-size。
- 计算公式:
1em = 当前元素的 font-size
例如:font-size: 16px;时,1em = 16px;font-size: 20px;时,1em = 20px。
rem也是相对单位,但是它只相对于根元素的字体大小,不受嵌套影响。通常比em更容易控制。
也可也直接写成:
<style>body{font:family:华文楷体; size:50px;weight: inherit;}</style>
文本样式
文本样式就是改变文本的样式。废话。
关于
关于
| 属性值 | 描述 |
|---|---|
| none | 默认,没有装饰线(最常用) |
| underline | 下划线。链接a自带下划线(常用) |
| overline | 上划线。(几乎不用) |
| line-through | 删除线。(不常用) |
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>文本样式</title><style>p {font-size: 20px; /* 大小 20像素 */color: blue; /* 蓝色 */font-weight: bold; /* 加粗 */text-align: center; /* 居中 */text-decoration: underline; /* 下划线 */}</style>
</head>
<body><p>我是变过样子的文字</p>
</body>
</html>
文本阴影和超链接伪类
文本阴影:让文字有影子,像立体字
写法:
超链接伪类:链接在不同状态下的样子。
:link– 从来没点过的链接:visited– 点过的链接:hover– 鼠标放上去的时候:active– 鼠标按住瞬间
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>文本阴影和链接伪类</title><style>h1 {text-shadow: 3px 3px 5px gray;}a:link {color: green;text-decoration: none;}a:visited {color: purple;}a:hover {color: red;text-decoration: underline;}a:active {color: orange;}</style>
</head>
<body><h1>我有阴影</h1><a href="https://www.baidu.com">点我试试看(鼠标放上变红,按住变橙,点过后变紫)</a>
</body>
</html>
列表样式练习
列表样式:改变列表前面的小圆点或者数字的样子。
list-style-type:改成圆点、方块、罗马数字等list-style-image:用自己的图片做标记
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>列表样式</title><style>ul {list-style-type: square; /* 方块标记 */}ol {list-style-type: upper-roman; /* 大写罗马数字 */}</style>
</head>
<body><ul><li>苹果</li><li>香蕉</li></ul><ol><li>第一步</li><li>第二步</li></ol>
</body>
</html>
背景图像应用及渐变
背景图像:给盒子(比如 div)加一张背景图。
渐变:不用图片,用代码生成颜色过渡。
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>背景和渐变</title><style>.bg-img {width: 300px;height: 200px;background-image: url('https://picsum.photos/300/200?random=1');background-size: cover;color: white;font-weight: bold;padding: 10px;}.gradient {width: 300px;height: 100px;background: linear-gradient(to right, red, yellow);margin-top: 10px;text-align: center;line-height: 100px;}</style>
</head>
<body><div class="bg-img">我是背景图片</div><div class="gradient">我是红到黄渐变</div>
</body>
</html>
这里没有加图片但是自动形成了一个红到黄的渐变块就是因为我们之前有提到过的块级元素
没想到它有这样的用途。
盒子模型
我理解的盒子就是将元素装入盒子中,方便后续布局移动。确实是如此,d老师的解释为:
HTML 元素本身就是盒子,CSS 只是描述这个盒子长什么样的说明书。
可以这样类比:
- HTML = 快递包裹里的货物(文字、图片、按钮)
- CSS 盒子模型 = 包裹的纸箱 + 泡沫 + 外包装
content= 货物本身padding= 货物和纸箱之间的泡沫缓冲border= 纸箱的厚度margin= 这个包裹和别的包裹之间要保持的距离
利用css摆盒子。
盒子模型:每个 HTML 元素都是一个盒子,从里到外:内容 → 内边距 → 边框 → 外边距。
边框
border 可以设置粗细、样式、颜色。
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>盒子模型和边框</title><style>.box {width: 200px;height: 100px;padding: 20px; /* 内边距:内容和边框的距离 */border: 5px solid blue; /* 边框 */margin: 30px; /* 外边距:和其他盒子的距离 */background: lightgray;}</style>
</head>
<body><div class="box">我是盒子</div>
</body>
</html>
边框的常见类型:
-
border—solid.html—实现边框
<!DOCTYPE html> <html lang="zh"> <head><meta charset="UTF-8"><title>CSS 边框:solid(实线)</title><style>body {background: #f4f6f9;display: flex;justify-content: center;align-items: center;min-height: 100vh;font-family: system-ui, sans-serif;margin: 0;}.demo-box {width: 260px;padding: 30px 20px;background: white;/* 实线边框 */border: 4px solid #2563eb;border-radius: 12px;text-align: center;box-shadow: 0 4px 8px rgba(0,0,0,0.02);}code {background: #eef2ff;padding: 4px 8px;border-radius: 20px;font-size: 0.9rem;}</style> </head> <body><div class="demo-box"><h2 style="margin-top: 0;">🔵 solid</h2><p>实线边框,最常用的类型。</p><code>border: 4px solid #2563eb;</code></div> </body> </html>效果如图:
-
border-dotted.html—点状边框
<!DOCTYPE html> <html lang="zh"> <head><meta charset="UTF-8"><title>CSS 边框:dotted(点线)</title><style>body {background: #f4f6f9;display: flex;justify-content: center;align-items: center;min-height: 100vh;font-family: system-ui, sans-serif;margin: 0;}.demo-box {width: 260px;padding: 30px 20px;background: white;border: 5px dotted #8b5cf6;border-radius: 12px;text-align: center;}code {background: #ede9fe;padding: 4px 8px;border-radius: 20px;}</style> </head> <body><div class="demo-box"><h2 style="margin-top: 0;">🟣 dotted</h2><p>圆点虚线边框,间距均匀。</p><code>border: 5px dotted #8b5cf6;</code></div> </body> </html>效果如下:
-
border-dashed.html—虚线边框
<!DOCTYPE html> <html lang="zh"> <head><meta charset="UTF-8"><title>CSS 边框:dashed(虚线)</title><style>body {background: #f4f6f9;display: flex;justify-content: center;align-items: center;min-height: 100vh;font-family: system-ui, sans-serif;margin: 0;}.demo-box {width: 260px;padding: 30px 20px;background: white;border: 4px dashed #16a34a;border-radius: 12px;text-align: center;}code {background: #dcfce7;padding: 4px 8px;border-radius: 20px;}</style> </head> <body><div class="demo-box"><h2 style="margin-top: 0;">🟢 dashed</h2><p>短横线虚线,常用于分隔或临时状态。</p><code>border: 4px dashed #16a34a;</code></div> </body> </html>效果如下:
边框其实可以分开来写:
border-top:1xp solid red;
border-bottom:10xp dashed white;
注意层叠性,如果同时写:
border:blue;
border-top:purple;
那么效果只覆盖上边框。但如果两个的顺序反过来就不可以,触犯到了就近原则。
另外需要注意的是边框会影响盒子的实际大小,因此我们有两种方案解决:
-
测量盒子大小的时候,不量边框。
-
如果测量的时候包含了边框,则需要width/height减去边框宽度。
表格的细线边框
border-collapse属性控制浏览器绘制表格边框。它控制相邻单元格的边框:
border-collapse:collapse;
仍旧英人世界,collapse的意思就是合成。
如果我希望相邻的表格边框合并就可以直接打:
td{border:1xp solid pink;border-collapse:collapse;
}
内边距
d老师你有事吗,前面一直有用内外边距,结果到这里才继续给我讲。对不起d老师误会你了,是我太心急了。
水平居中:给块级元素(如 div)设置 margin: 0 auto;,并且要有宽度。
内边距:padding,让内容不贴边。
外边距:margin,让盒子之间有空隙。
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>内外边距和居中</title><style>.center {width: 300px;margin: 0 auto; /* 左右自动,实现居中 */padding: 20px;background: lightgreen;text-align: center;}</style>
</head>
<body><div class="center">我水平居中啦!</div>
</body>
</html>
效果如图:
注意margin padding也有复合写法:
padding:5px 10px 6px 10px;
| 值个数 | 示例 | 含义 | 等效完整写法 |
|---|---|---|---|
| 1 个值 | padding: 10px; |
上 右 下 左 都是 10px | padding: 10px 10px 10px 10px; |
| 2 个值 | padding: 10px 20px; |
上下 10px,左右 20px | padding: 10px 20px 10px 20px; |
| 3 个值 | padding: 10px 20px 30px; |
上 10px,左右 20px,下 30px | padding: 10px 20px 30px 20px; |
| 4 个值 | padding: 10px 20px 30px 40px; |
上 10px,右 20px,下 30px,左 40px | (本身已完整) |
如图所示:
注意padding也会影响盒子的大小,在这里我产生了疑惑,因为我理解的物理模型的width是指一个盒子的大小是200px,而padding代表的是他的内容物,但是d老师告诉我我的理解不对是因为css的width不是代表整个盒子大小是200px,只代表中间content内容物盒子的大小是200px。这也就是说明为什么border和padding都会影响盒子的大小,因为他们都像是给杯子又套了一层杯罩。
至于他为什么设计的这么反直觉,是因为在1996年的时候网页主要是通过文字来排版,当时的设计师说的是我需要这个段落的文字区域200px也就是我只需要这个杯子,周围稍微空白出来就好。
所以浏览器开始一层一层往外套东西。
但我们现在做的是UI界面开发,我们说的是整个卡片的宽度,也就是我们将这个杯子层层包裹后端出来,所以也就导致了,这个杯子内容缩水。
哇怎么不算一种过度包装(
接下来是padding的妙用:
-
在导航栏中运用padding这个特性:遇到导航栏中字数不一样多的情况,可以不用给每个盒子宽度,而直接给padding。
复习的时候学到这里突然忘记了什么意思,其实也就是如果给这个元素盒子,就像是强行包装一个元素,而元素和盒子之间的空隙并不一样,而从内部贴着元素给他padding间距就更加灵活。
-
老师在这里举了一个新浪首页的例子,注意到这里我们之前学到的行内元素和块内元素起了一些用处:因为表示链接的a元素是行内元素,高对它不起作用,所以为了能够更好的让我的元素,既像行内元素一样并排,又像块级元素一样拥有完整的盒模型能力,所以我们需要将它转换为行内块元素。
以及还有一种情况padding不会改变盒子大小:如果盒子本身没有指定width/height属性,则此时padding不会撑开盒子大小。
那不就是和上面那个案例差不多吗。
所以本质上还是,padding像是泡沫纸裹着内容,所以不是所谓的撑开盒子大小,而是直接就是在盒子外面加了一层包装。
外边距
外边距可以让块级盒子水平居中,但是必须满足两个条件:
- 盒子必须指定了宽度。
- 盒子左右的外边距都已经设置了auto。
设置auto有三种常用手法:
- margin-left: auto;margin-right: auto;
- margin:auto
- margin: 0 auto(上下是0,左右auto)
基本上只要保证左右是auto就可以了。
注意:以上方法是让块级元素居中,行内元素或者行内块元素水平居中给其亲元素添加text-align: center即可。
其实也就是类似于word文档中让它的文字居中对齐啦。。。。。这样说会更高级一点吗。。。
示意代码:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>行内元素之auto</title><style>.center {width: 300px;margin: 0 auto; /* 左右自动,实现居中 */}</style>
</head>
<body><div class="center">我水平居中啦!<span>里面的文字</span></div>
</body>
</html>
此时图像为:
所以我们注意到,该块内元素相较于整体网页来讲为居中,但是里面的文字是靠右对齐的,并没有居中对齐。而因为span是行内元素,所以无法使用auto来直接实现居中。
这里的代码有所误导,因为只给.center写了margin:0 auto,注意此处的margin完全不会对span有影响,因为这个和盒子模型有关,在上文我们提到了和盒子模型有关的东西是无法继承的。
所以margin不生效确实是因为span是行内元素所以无法影响它。
因为行内元素本身的宽度完全由内容撑开,没有一个固定的盒子宽度可以让浏览器去分配剩余空间,所以auto计算出来只能是0。无法被margin当作盒子来推动,用auto来直接定义它来实现居中。
修改一个误区,之前学习这里的时候我没有注意到margin被赋予在亲元素身上,所以亲元素之所以要添加text-align,是为了影响块级元素内部的子元素的行内元素。
在这里我又开始思考那行内元素还算是盒子吗,答案是算的,只是这种盒子遵守的规则和块级盒子不一样,可以这样理解:
- 块级盒子是一个硬纸箱,明码标宽高,独占一行,margin四通八达。
- 行内盒子像是塑料袋,包住内容就可以,宽度跟着内容走,不换行,margin只能在左右方向推得动别人,上下方向基本只管自己看起来多大不管别人位置,接下来可以在下面的笔记为什么尽量不要给行内元素设置padding和margin中看到示例图。
将此时的代码修改为:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>行内元素之auto</title><style>.center {width: 300px;margin: 0 auto; /* 左右自动,实现居中 */text-align:center; /*亲元素添加*/}</style>
</head>
<body><div class="center">我水平居中啦!<span>里面的文字</span></div>
</body>
</html>
此时的图片则为:
注意对于典型的行内块元素图像标签来说,它也是这样水平居中对齐的,效果图如下:
在使用margin定义块元素的垂直外边距时,可能会出现外边距的合并,有两种塌陷的方式。
-
相邻块元素垂直外边距的合并
当上下两个相邻的块元素相遇时,如果上面的元素有下外边距margin-bottom,下面的元素有上外边距margin-top,则它们之间的垂直间距并不是margin-bottom和margin-top之和。而是取其中的较大者,这种现象被称为相邻块元素垂直外边距的合并。
如图所示:
解决的方案就是尽量只给一个盒子添加margin。
-
嵌套块元素垂直外边距的塌陷
<!DOCTYPE html> <html> <head><meta charset="UTF-8"><title>行内元素之auto</title><style>.parent {width: 400px;height:400px;background-colour:purple;margin-top:50xp;}.child {width: 200px;height:200px;background-color:pink;} </style> </head> <body><div class="parent"><div class="child"></div></div> </body> </html>效果图如下:
此时我们给子元素和亲元素都增加一个margin-top值,但是发现子元素并没有如预期值般和亲元素产生差距,反而是亲元素又往下空了刚才设置的本属于子元素的margin-top值,这就是亲元素的塌陷。
也就是对于两个嵌套关系的块元素,亲元素有上外边距同时子元素也有上外边距,此时亲元素会塌陷较大的外边距值。
效果如图所示:
解决方法:
-
可以给亲元素加内边距:
.parent {padding-top: 1px; /* 一点内边距就能阻隔 */ } -
可以为亲元素定义上边框:
.parent {border-top: 1px solid transparent; /* 透明边框,看不见但能阻隔 */ } -
给亲元素添加overflow: hidden:
.parent {overflow: hidden; /* 触发 BFC(块级格式化上下文) */ }简单了解overflow:hidden,它的本意是控制当子元素超过亲元素范围时怎么显示。
-
overflow: hidden的本职工作:控制溢出
想象一个相框(亲元素),里面的照片(子元素)比相框大:
值 效果 比喻 visible(默认)超出部分照常显示,不裁剪 照片戳出相框,不管 hidden超出部分被剪掉,不可见 照片被相框严格裁切 scroll超出部分被剪掉,但出现滚动条 相框带滑轨,可以滑动看 auto需要时才出现滚动条 自动判断 示例代码:
<div style="width: 200px; height: 100px; border: 2px solid black;">我没有 overflow 限制,内容会溢出<div style="width: 300px; height: 50px; background: lightcoral;">我很宽</div> </div><div style="width: 200px; height: 100px; border: 2px solid black; overflow: hidden; margin-top: 20px;">我有 overflow: hidden,超出部分被隐藏<div style="width: 300px; height: 50px; background: lightcoral;">我很宽</div> </div>效果如图:
可以看到上文的overflow: hidden将框里的红色块裁切掉了。
-
为什么overflow: hidden可以解决外边距塌陷。
当亲元素设置了overflow: hidden,浏览器就会为它单独创建一个独立的布局隔间,专业术语为BFC,块级格式化上下文。
这个隔间有两条规矩:
- 子元素溢出的部分会真的被裁掉。
- 子元素的垂直外边距不会穿透这个隔间去和外部合并。
因为第二条规则,就可以组织嵌套块元素的margin塌陷,overflow: hidden将亲元素的“天花板”封死了。
-
根据上面的三种解决方法我注意到了塌陷机制的本质:之所以会造成塌陷是因为两个外边距之间没有任何的阻碍,导致了两个垂直外边距直接接触,而margin合并是CSS的默认行为,在此基础上自然地发生了合并,所以只要把它们隔开它们就不会像是橡皮泥一样黏在一起了。
其实我觉得应该先解释塌陷机制的本质再讲解决方法,这样就一目了然而且不用说很多的废话补充说明,外边距塌陷必须还满足两个元素都是常规流中的块级盒子这个特点,以及它们是属于同一个BFC。
每天就这样学一个callback一点。 -
清除网页自带的内外边距
网页元素很多都带有默认的内外边距,而且不同浏览器默认的也不一致。因此我们在布局前要清楚网页元素自带的内外边距。
孩子们这个狂神根本没有讲通配符选择器啊何意味!
立刻使用我们的通配符选择器!代码如下:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>边距清理大师</title><style>*{margin:0;padding:0;}</style>
</head>
<body>123<ul><li>abcd</li></ul>
</body>
</html>
这样就没有内外边距了,一般来讲这也是CSS的第一行代码。
注意:行内元素为了照顾兼容性,尽量只设置左右内外边距,不要设计上下内外边距。但是转化为块级和行内块元素就可以了。
下面为示例代码:
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>边距清理大师</title><style>*{margin:0;padding:0;}span{background-color:purple;margin:20px;}</style>
</head>
<body>123<ul><li>abcd</li></ul><span>行内元素尽量只设置左右内外边距</span>
</body>
</html>
正常来讲该代码会让拥有上下左右的外边距,但是效果图如下:
我们发现只有左右显示了margin值,所以设置上下没什么用。
。不过有个问题啊,反正也不会显示为什么不直接合并写了。
好了我问了d老师,d老师说上下padding/border是可以看见的,浏览器的背景色和边框线会如实地把他们画出来,d老师你的视觉效果做的好啊……,为什么不设置padding的原因如图所示:
而不设置margin的原因其实是因为写了白写,原因可以参考上文的margin还算是个盒子吗:
圆角边框及阴影
圆角边框:border-radius 让角变圆,可以同时输入多个px,输入顺序对应的分别是:左上右上右下左下。如果输入两个px就是以左上对右下,左下对右上的方式形成边框。
圆圈:圆角=半径
<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title>圆角和阴影</title><style>.card {width: 200px;height: 200px;background: #ffc107;border-radius: 20px; /* 圆角 */box-shadow: 5px 5px 15px rgba(0,0,0,0.3); /* 阴影 */text-align: center;line-height: 200px;margin: 30px auto;}</style>
</head>
<body><div class="card">圆角+阴影</div>
</body>
</html>
盒子阴影:box-shadow 给盒子加影子,基本语法如下:
box-shadow: h-shadow;v-shadow;blur;spread;color;inset水平偏移 垂直偏移 模糊半径 扩散半径 颜色 内阴影;
| 参数 | 含义 | 默认值 | 说明 |
|---|---|---|---|
| 水平偏移 | X轴移动 | 必填 | 正值右移,负值左移 |
| 垂直偏移 | Y轴移动 | 必填 | 正值下移,负值上移 |
| 模糊半径 | 模糊程度 | 0(清晰) | 越大越模糊 |
| 扩散半径 | 阴影扩大/缩小 | 0(和元素一样大) | 正扩大,负缩小 |
| 颜色 | 阴影颜色 | 黑色 | 支持任何颜色写法 |
| inset | 内部阴影 | 不加是外阴影 | 写在最前面或最后面(但建议写在前面) |
最常用写法举例:
/* 1. 简单阴影(右下偏移+模糊) */{box-shadow: 6px 6px 8px rgba(0,0,0,0.2);}/* 右下偏移,模糊10px,半透明黑色 */
box-shadow: 5px 5px 10px rgba(0,0,0,0.3);
/* 2. 无偏移四周发光 */ {box-shadow: 0 0 16px 4px #3b82f6;}
/* 3. 扩散半径为负值(更小的阴影) */{box-shadow: 0 8px 12px -4px rgba(0,0,0,0.3);}
/* 4. 内阴影 inset */{box-shadow: inset 0 4px 8px rgba(0,0,0,0.3);background: #f1f5f9;}
文字阴影:
text-shadow: h-shadow;v-shadow;blur;color;水平偏移 垂直偏移 模糊半径 颜色 ;
浮动
老天我终于学到这里了我去。
。。。。黑马什么都好,就是太墨迹了,能不能讲重点!
传统网页布局有三种方式,本质是用CSS来拜访盒子,把盒子摆放到相应位置:
-
普通流(标准流)
标签按照规定好默认方式来排列,也就是块级元素独占一行,行内元素从左到右排序。
-
浮动
-
定位
立刻开始学习这个浮动!
为什么我们需要浮动
-
即使行内块元素可以实现一行显示,但是它们之间会有大的空白缝隙,很难控制。
-
很多布局效果,标准流没有办法完成,这个时候就可以利用浮动来完成布局,因为浮动可以改变元素标签默认的排序方式。
-
网页布局第一准则:多个块级元素纵向排列找标准流,多个块级元素横向排列找浮动。
float的核心属性
float: left; /* 元素向左浮动 */
float: right; /* 元素向右浮动 */
float: none; /* 默认值,不浮动 */
很好,其实浮动的核心原理就是:浮动元素挤压了原本亲元素中子元素的活动区域,起到了占位符的作用,注意这里的子元素为行内元素。块内元素会完全无视浮动元素,直接占据它的原位置,仿佛浮动元素不存在,但是图层在浮动元素之下。如图所示:
而作为背景亲元素的块级元素,假设我们的网页是可以图层覆盖的,那么浮动元素是可以覆盖在亲元素的块级元素图层之上的。接下来是浮动元素与块级元素行内元素对比示意图:
浮动特性
-
脱离文档流:
-
脱离标准普通流的控制移动到指定位置(也就是脱标)。
-
浮动的盒子不再保留原先的位置。
如图所示:
-
添加浮动后:
还是图层覆盖,浮动盒子已飞升。
-
如果多个盒子都设置了浮动,则它们会按照属性值一行内显示并且顶端对齐排列,如图所示:
-
浮动元素会具有行内块元素特性
任何元素都可以浮动。不管原先是什么模式的元素,增加浮动之后都会具有行内块元素相似的特性。
我们先写一个常见的span代码,我们知道span是行内元素它的高和宽是无效不显示的:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"><title>浮动特性</title><style>span{width:200px;height:100px;background-color:purple;}</style> </head> <body><span></span> </body> </html>效果图如下:
无显示,此时我们将代码更改为:
<!DOCTYPE html> <html> <head><meta charset="UTF-8"><title>浮动特性</title><style>span{float:left;/*亲亲这边为您添加了一位float*/width:200px;height:100px;background-color:purple;}</style> </head> <body><span></span> </body> </html>我们可以看到增加了float的网页效果图为(我知道这是粉色,就当它是紫色吧!):
span显示出来了,这就是它的特性三,块级元素更不用说了。
-
宽度收缩:
我们上文说了当一个元素增加了浮动元素尤其是行内元素,那么它就会具有块级元素的特定。而如果浮动元素没有显示设置宽度,那么它的宽度会由自身内容决定,而不再是块级元素默认的占满亲元素的一整行,这种行为类似于将行内元素转化为行内块元素,如图所示:
神ai大D老师我看你也是有这里帮您添加了一位padding的大病,我让你演示宽度收缩你就不要自顾自在你代码里还加一点padding再加一点border误导我,让我以为这个特性可以对上面的padding来直接设置导航栏大喝一声彼可取而代之 -
亲元素高度塌陷
当亲元素所有的子元素都浮动升天,又或者除浮动元素外没有普通流内容时,亲元素在计算高度时会忽略浮动子元素,
生完孩子了肚皮回缩了这就导致亲元素的高度会变为零。导致亲元素的背景、边框无法包裹浮动子元素,后续元素也可能上移造成布局混乱。有点地狱笑话了在这个Typora中写元素上移造成布局混乱效果如图所示:
注意到第一个亲元素没有了高度,而第二个亲元素在清楚完浮动后又包裹住了浮动子元素。
天杀的大D老师又在这里装唐阴我了。天杀的这里还有两个必要条件:
- 亲元素没有设置height
- 亲元素内部的所有子元素都浮动了
我和我最后的倔强。
浮动元素经常与标准流亲级搭配使用
如果只有浮动元素,当我们给它左浮动和右浮动,它们就会很极端飘到最两边,所以我们需要给它们设置一个亲级盒子限制它们的移动范围,如图所示:
清除浮动
前面的浮动元素都有一个标准流的亲元素,而它们共同的特点就是它们都有规定好的高度,但是我们需要更好的兼容性,使能让新产生的子元素撑开它的亲元素盒子。
而在前文我们提到了浮动的一大特性就是所有子元素升天会导致没有规定height的亲元素塌陷。亲元素:一切都是强撑罢了
所以我们就需要清除浮动。
清除浮动的本质
清除浮动不是删除浮动或者改变浮动元素本身,而是通过特定的CSS机制,强制亲元素的计算高度包含浮动子元素。以下是两种主流的技术路线:
-
触发BFC(会计格式化上下文):让亲元素形成一个独立的渲染区域,自动包裹内部浮动元素。
-
使用clear属性:在浮动元素之后插入一个换行点,使其下方内容换到浮动元素之下,从而撑开亲元素的高度。
clear属性(隔墙法/额外标签法)
clear属性的语法为:
<!--clear:left|right|both|none;--><div class="parent"><div class="float-left">浮动</div><div style="clear: both;"></div> <!-- 额外的空标签 -->
</div>
在前文我们已知如果前面的元素浮动起来,那么块级元素会向前自动补位,而加了clear:both的块级元素则会强制要求自己必须处于所有浮动元素的下方,抵住亲元素盒子的下方,防止亲元素盒子塌陷。
在这里我又用了一些时间来思考为什么会这样,其实感觉还是大D老师给我的配图出了很大的问题吧,在配图中它给我的配图纷纷写了长宽高,以至于我的思考陷入误区那就是如果有高度那它不也把盒子撑大了吗,然而呢,事实洽洽瓜子啊。
我们上文的代码零个给额外的空标签盒子设置height啊,所以它根本是一个透明不会显示的。
其实我觉得这也和我惯性思维思考它是一个盒子就一定有占位的体积有关系,实则不然。
注意现在的浮动元素下面也就是亲元素盒子和占位盒子同图层的那块区域还是什么都没有的。
注意,这个新增的盒子要求必须是块级元素,不可以是行内元素。
触发BFC (overflow:hidden/auto/scroll)
根据上文已知BFC是一个独立的渲染区域,容器内的元素不会与外部元素相互影响。BFC的一个特性就是:在计算BFC的高度时,浮动子元素也参与计算。
操作代码如下:
.parent {overflow: hidden; /* 触发 BFC */
}
优点是代码简洁,缺点是无法显示溢出的部分。
什么是伪元素
我不是很喜欢把问题留到后面所以我选择在这里就把什么是伪元素学习完毕。
伪元素可以理解为一个用CSS凭空创造出来的、存在于HTML结构之外的虚拟子元素。
它的行为像是一个真实的HTML标签,可以给它设置宽高、背景、边框、内外边距等,但是它并不会真实存在于代码之中,也就是无法在页面上看到它,也不能在开发者工具的HTML面板中直接选中。它是CSS渲染引擎生成的一种隐形盒子。
最常见的两个伪元素是:
- ::before:在元素内容的最前面,生成一个虚拟子元素。
- ::after:在元素内容的最后面,生成一个虚拟子元素。
伪元素有一个生成的铁律就是必须要写content属性,哪怕是空字符串"",没有content,伪元素根本不会生成,因为伪元素本质上是CSS通content属性“注入”到页面中的虚拟内容。代码如下:
/* 错误:伪元素不会出现! */
.clearfix::after {clear: both;/* 缺少 content,浏览器直接忽略这个伪元素 */
}/* 正确:必须写 content */
.clearfix::after {content: ""; /* ← 这一行是伪元素的“激活开关” */clear: both;
}
通过content插入的文本内容,不会被鼠标选中,也无法被复制。
:after伪元素
利用伪元素在亲元素内容的最末尾生成一个不可见的块级元素,并设置clear:both。这样既能撑开高度,又不用添加多余的HTML标签。
注意这里的伪元素生成后只是普通元素,让它成为透明支柱的因素是display: block。
操作代码如下:
.clearfix::after {content: "";display: block;clear: both;
}
在清除浮动的场景中,一个更稳健、更老派但是兼容性更好的写法是使用display: table而非display: block。因为display: table会创建一个匿名表格单元表,在某些旧版的浏览器中可以触发更强的BFC隔离,避免极微小的边距穿透,不过在现代浏览器中两者几乎是一样了。每次写到这种东西我就开始脑补某一天面试hr问到我这种问题,何尝不算是前端的茴字四种写法呢?
根据前文关于伪元素的介绍以及clear属性的缺点我们不难发现用伪元素来创造一个透明支撑会更好,语义干净而且可以复用,也不影响溢出表现。是目前业界清除浮动的标准做法。
双伪元素
已知单伪元素::after已经在浮动元素的下方撑开了高度,而双伪元素在这个基础上,再额外多设置了一个::before在浮动元素上方也加了一个看不见的薄片,可以用来防止亲元素自身和其子元素发生上外边距塌陷。
因为亲元素和子元素发生上外边距塌陷的本质是两个垂直外边直接接触会触发margin的自合成机制选择更大的一个margin塌陷。
我去就像是overflow: hidden给它们隔开了,但是双伪元素可以更轻松简单,也让这个代码更轻松简单地做到了,一举解决两个问题,妈妈再也不用为我担心。
伪元素必须加content。卧槽差点下辈子才想起来我当时怎么没写。
标准代码写法如下:
/* 双伪元素清除浮动 */
.clearfix:before,
.clearfix:after {content: "";display: table;
}
.clearfix:after {clear: both;
}/* 兼容IE6/7,现代项目可省略 */
.clearfix {*zoom: 1;
}
定位
我们为什么需要定位
浮动可以让多个块级盒子一行没有缝隙排列显示,经常用于横向排列盒子,而定位则是可以让盒子自由地在某个盒子内移动位置或者固定在屏幕中某个位置,并且可以压住其它盒子。
定位的核心属性
定位由定位模式和边偏移组成。定位模式用于指定一个元素在文档中的定位方式,边偏移则决定了该元素的最终位置。
position : static ;(默认值)
含义:元素就待在文档流里,正常排序。top/left等边偏移完全无效。
如图所示:
position : relative ;(相对定位)
含义:元素仍然占据在文档流中的原始位置,但可以在视觉上偏移,往自己原位的左右上下挪动。肉体还留在原地但是灵魂已飞升。
核心特点:
- 元素不会脱离文档流,它的坑位还在
- 移动时,是相对于自己原来的位置为基准。
- 移动后,原始位置留白依然在,其它元素不会补位。
如图所示:
position : absolute ;(绝对定位)
含义:元素完全脱离文档流,它的位置相对于最近的非static定位的祖先元素。如果没有找到,就相对于浏览器的第一屏(html)来定位。
核心特点:
- 完全脱离文档流,不占空间,后面的元素会顶上来
- 定位参考物逐层向上寻找,直到找到第一个带有position : relative/absolute/fixed的祖先。
- 如果没有这样的祖先,就相对于浏览器视口。
如图所示:
position : fixed ;(固定定位)
含义:元素完全脱离文档流,相对于浏览器窗口定位。页面滚动时,它纹丝不动。
核心特点:
- 完全脱离文档流。
- 参考物永远是浏览器窗口,不管嵌套多深。
- 常用于:固定在顶部的导航栏、回到顶部的按钮、弹窗遮罩。
如图所示:
fixed有时会没有相对于视口固定,而是相对于某个祖先元素固定了,通常失效原因是因为fixed元素的任意祖先元素设置了诸如transform(即使none也可能触发)/perspective/filter的元素,导致浏览器把那个祖先当作fixed元素的包含块,导致fixed不再参照视口。
position : sticky ; (粘性定位)
含义:粘性定位是CSS中的一种混合定位模式。它允许元素在页面滚动到某个临界点之前,像普通文档流元素一样正常排列;一旦滚动超过这个临界点,元素就会粘在屏幕上,表现得像是
核心特点:
-
定位参考是视口,但仍受亲容器约束。如图所示:
-
在触发黏性之前,元素占据正常的文档流空间,后面的元素不会顶上来。这与fix和absolute完全不同。
-
必须配合偏移属性,告诉浏览器在距离视口边缘多远时开始“黏住”。最常用的是top:0。
-
粘性定位是条件性的,只有当滚动位置达到指定偏移量,且亲容器还有空间容纳它时,元素才会粘住,如果亲容器高度不够,粘性效果不会出现。
如图所示:
多个粘性标题滚动页面,每个分类标题会在到达顶部时粘住,直到下一个标题把它顶走(通讯录效果),其代码如下:
<!DOCTYPE html>
<html lang="zh">
<head><meta charset="UTF-8"><title>多个粘性标题演示</title><style>body {background: #f4f6f9;font-family: system-ui, sans-serif;margin: 0;padding: 20px;min-height: 200vh; /* 确保页面足够长可以滚动 */}h1 {text-align: center;margin-bottom: 20px;}.section {margin-bottom: 30px;}/* 粘性标题样式 */.sticky-header {position: sticky;top: 0; /* 距离视口顶部 0 时开始粘住 */background: #8b5cf6;color: white;padding: 14px 20px;border-radius: 10px;font-weight: bold;margin: 0;font-size: 1.2rem;z-index: 10;}.content {background: white;border-radius: 0 0 12px 12px;padding: 16px;box-shadow: 0 4px 8px rgba(0,0,0,0.05);}.content p {margin: 8px 0;padding: 8px;background: #f1f5f9;border-radius: 6px;}</style>
</head>
<body><h1>📇 多个粘性标题(通讯录效果)</h1><p style="text-align:center; color:#475569;">向下滚动页面,每个标题会依次粘在顶部,下一个标题会把上一个顶走。</p><div class="section"><h2 class="sticky-header">A 字母开头</h2><div class="content"><p>Alex</p><p>Alice</p><p>Amy</p><p>Adam</p><p>Anna</p><p>Arthur</p><p>Amanda</p><p>Aaron</p></div></div><div class="section"><h2 class="sticky-header">B 字母开头</h2><div class="content"><p>Bob</p><p>Bill</p><p>Betty</p><p>Bruce</p><p>Bonnie</p><p>Brian</p><p>Bella</p><p>Barry</p></div></div><div class="section"><h2 class="sticky-header">C 字母开头</h2><div class="content"><p>Charlie</p><p>Chris</p><p>Cindy</p><p>Clark</p><p>Catherine</p><p>Connor</p><p>Chloe</p><p>Carl</p></div></div><div class="section"><h2 class="sticky-header">D 字母开头</h2><div class="content"><p>David</p><p>Diana</p><p>Daniel</p><p>Donna</p><p>Derek</p><p>Daisy</p><p>Dominic</p><p>Dylan</p></div></div><div class="section"><h2 class="sticky-header">E 字母开头</h2><div class="content"><p>Edward</p><p>Emily</p><p>Eric</p><p>Eva</p><p>Ethan</p><p>Eleanor</p><p>Elliot</p><p>Elena</p></div></div><div class="section"><h2 class="sticky-header">F 字母开头</h2><div class="content"><p>Frank</p><p>Fiona</p><p>Felix</p><p>Flora</p><p>Fred</p><p>Faith</p><p>Finn</p><p>Freya</p></div></div>
</body>
</html>
效果如图所示:
关于sticky不生效还可能的原因是sticky元素的任意祖先元素设置了overflow : hidden/overflow : scroll/overflow : auto,那么sticky效果会被破坏,元素不再黏住。
浮动与绝对定位的核心区别
绝对定位和浮动都可以让元素脱离文档流,但是它们的设计目的、行为逻辑和适用场景完全不同。
从设计目的的角度来看,浮动是为了实现文字环绕图片,而绝对定位是为了将元素精确地放置在某个容器内的任意位置。特么你早说浮动已经被Flex/Grid取代了啊我怎么感觉根本不用学这个浮动
二者脱离文档流的本质也不同。浮动让元素脱离文档流,但是仍然会影响行内内容。文字、等行内元素会环绕浮动元素。块级盒子本身会补位,但是盒子内部的文字也会绕开。而在绝对定位中,元素完全脱离文档流,对任何后续内容,无论是块级盒子还是行内文字都没有影响。后续元素就当它不存在,直接占据其位置。浮动是对块级盒子是三维了但是对行内元素还是二维,绝对定位是所有人都三维起来。
接下来是两者对亲元素高度的处理不同,两者都会导致亲元素高度塌陷,但是清除浮动的方法诸如clear对绝对定位无效。通常解决方法是给亲元素设置固定高度,或者用JavaScript动态计算。
二者定位参考和位置控制也有所不同,浮动只能向左或者向右靠拢,而绝对定位可以相对于最近的非static定位祖先用边偏移精确到像素级控制位置。
在元素重叠能力上,多个浮动元素无法重叠只能紧挨着排列,而多个绝对定位元素可以完全重叠在同一位置。
子绝亲相
子绝亲相的核心目的是让子元素以亲元素为参考坐标系,自由地放置在亲元素内部的任何位置,同时不破坏亲元素在文档流中的布局。
其实就是设定一小块移动范围而已。
定位的叠放次序z-index
在使用定位布局时,可能会出现盒子重叠的情况。此时可以使用z-index来控制盒子的前后次序(z轴)。
z-index用来控制定位元素在垂直与屏幕方向(Z轴)上的堆叠顺序。数字越大,元素越靠上,越靠近用户的眼睛。我去立体来了立体真的来了。一条直线直接穿透大脑(。
z-index特点为:
- 数值可以是正整数、负整数和零,默认是auto。数值越大图层越前。
- 如果属性值相同,则按照书写顺序,后来居上。
- 数字后面不可以加单位。
- 只对设置了定位的元素生效,注意这里的定位元素仍然不包括static。
定位拓展
绝对定位的盒子居中
加了绝对定位的盒子是不能通过margin : 0 auto水平居中的,但是可以通过二分法:将子盒子移动到亲盒子的二分之一处,再向负方向移动自己的二分之一,如图所示:
代码如下:
<style>.box{position:absolute;/*left:50% 走百分之五十,亲容器的一半*/left:50%;/*margin-left 负值 往左边走 自己盒子宽度的一半*/margin-left:-100px;widtn:200px;height:200px;back-ground:purple;}
</style><body><div class="box"></div>
</body>
而垂直居中也是相同的道理,先移动到亲盒子的一半百分之五十,然后倒车自己盒子大小的半个身位。、
定位特殊特性
绝对定位和固定定位也和浮动类似:
- 行内元素添加绝对或者固定定位,可以直接设置高度和宽度。
- 块级元素添加绝对或者固定定位,如果不给宽度或者高度,默认大小是内容的大小。
脱标的盒子不会触发外边距塌陷
浮动元素、绝对定位元素都不会触发外边距合并的问题。此二元素已飞升。
绝对定位(固定定位)会完全压住盒子
也就是前面说的人没了影子也没了。
弹性盒子布局
一想到这个狗屎的鱼网站让我走了浮动的冤枉路我就想要骂人特么的。。。老娘的时间也是时间。
老天爷能不能给我一个机会,让面试官莫名其妙问我点浮动的问题然后说天呐我们要的就是你这样的严谨人才!
。。。特么我为什么要那么努力去记高度塌陷造成的原因啊,特么弹性盒子布局直接全解决了。。。
诶哟我说命运啊
Flexbox的核心思想:给一个亲元素设置display : flex,它就能完全控制内部直接子元素(items)的排列、对齐和尺寸分配。子元素们变得”弹性“,能自动伸缩填满空间。
Flexbox的核心概念:
-
两个角色:
-
Flex容器:设置了display : flex的亲元素。
-
Flex项目:容器内部的直接子元素,会自动变成弹性项目,其中有一些注意事项如下:
-
如果子元素有大小,则按照给定大小来显示,如果没有大小,则拉伸充满亲容器。
-
若子元素总宽度超过亲容器的宽度,默认会压缩子元素,如图所示:
可以看到第二个盒子我们给它设定的元素是两百,但是根据压缩,我们在页面查看时发现它们的宽度只有一百多像素。
-
-
-
两根轴:
-
主轴(Main Axis):弹性项目沿着排队的方向。默认是水平方向(row)。
-
交叉轴(Cross Axis):永远垂直于主轴。
-
可以用flex-direction改变主轴方向,使整个坐标系随之旋转,概念如下:
flex-direction: row (默认)
主轴: → (左→右)
交叉轴: ↓ (上→下)flex-direction: column
主轴: ↓ (上→下)
交叉轴: → (左→右)
其中:
- 凡是justify-*开头的属性,永远管理主轴方向。
- 凡是align-*开头的属性,永远管理交叉轴方向。
Flex容器的属性
flex容器的属性如下所示:
-
display : flex;
激活弹性榕溪,容器本身表现为块级元素。
-
flex-direction—设定主轴方向。
值 主轴方向 row(默认)水平方向,从左到右 row-reverse水平方向,从右到左 column垂直方向,从上到下 column-reverse垂直方向,从下到上 -
flex-wrap—控制是否换行
值 效果 nowrap(默认)不换行,所有子元素挤在一行,可能溢出 wrap换行,第一行在上方 wrap-reverse换行,第一行在下方 -
flex-flow—flex-direction和flex-wrap的简写
flex-flow:row wrap; -
justify-content—沿主轴对齐子元素
值 效果 flex-start(默认)子元素挤在主轴起点 flex-end挤在主轴终点 center居中 space-between两端对齐,子元素之间间距相等 space-around每个子元素两侧间距相等(两端间距是中间的一半) space-evenly所有间距(包括两端)完全相等 -
align-items—沿交叉轴对齐子元素(单行)
值 效果 stretch(默认)如果子元素未设高度/宽度,会拉伸填满交叉轴 flex-start挤在交叉轴起点 flex-end挤在交叉轴终点 center交叉轴居中 baseline子元素内文本的基线对齐 -
align-content—多行时,行与行之间沿交叉轴对齐
这个属性只在flex-wrap : wrap且有多行时生效。值与justify-content类似:stretch、flex-start、flex-end、center、space-between、space-around、space-evenly。
也是被坑了导致学了一大堆已经淘汰的技术,后面的笔记之后有时间补一下吧,主播先去写JavaScript的笔记了。
