1. 层叠上下文
- 什么是层叠上下文
- 层叠上下文理解为 HTML 元素的一个属性,一但 HTML 元素拥有了这个属性,我们可以理解为这个 HTML 元素在Z 轴上就“高人一等”,也就是在 Z 轴上会显示在更上一层,。
- 如何创建层叠上下文
- html 根层叠上下文 (默认的,不需要创建)
- 定位元素的传统层叠上下文(z-index 值为数值时才会创建层叠上下文,z-index:auto 不会创建层叠上下文)。
- 对于包含有
position:relative/position:absolute的定位元素,当其z-index值不是auto的时候,会创建层叠上下文. position值为fixed(固定定位)或sticky(粘滞定位)的元素
- 对于包含有
- css3 与新时代的层叠上下文
z-index值不为auto的flex项(父元素display:flex|inline-flex)- 元素的
opacity值不是1 - 元素的
transform值不是none - 元素
mix-blend-mode值不是normal - 元素的
filter值不是none - 元素的
isolation值是isolate will-change指定的属性值为上面任意一个- 元素的
-webkit-overflow-scrolling设为touch
- 同一层叠上下文中,元素的层叠顺序
z-index可以调节同一层叠上下文中 定位元素的层叠顺序- 如何确定两个元素的层叠顺序
- 在比较两个元素的层叠顺序时,会先比较他们所在的层叠上下文的层叠顺序
- 如果他们所在的是同一层叠上下文,则按同一层叠上下文中的元素排列顺序来计算。
- 如果不在同一层叠上下文中,则他们所在层叠上下文的顺序决定了他们的顺序及其后代元素的层叠上下文顺序。
- 即 A 层叠上下文要高于 B 叠上下文,则 A 中的所有子孙元素都会高于 B 中的所有子孙元素。B 中子孙元素的
z-index再大也没有办法在层级上高于 A 元素中子元素。,因为z-index只能控制同一层叠上下文中的元素堆叠关系。
2. 流光按钮
步骤:
- 一个按钮
- 光影效果用的是一个发光的毛毛球( background属性经典应用(视觉差效果/绘制纸张/绘制棋盘/绘制彩虹/发光的毛毛球/发光按钮/波点背景/彩色饼图/圆环加载指示器) - 掘金)
- 鼠标移动时这个球会围着按钮转
- 发光的球只能显示一小点 是因为又做了一个按钮大小的盒子盖住了按钮
- 把“加入购物车”文字层叠顺序调高
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>流光按钮</title>
<style>
body {
background-color: #000;
}
a.button {
display: block;
width: 160px;
height: 50px;
background-color: #333;
text-align: center;
line-height: 50px;
text-decoration: none;
color: #666;
font-weight: bold;
border-radius: 5px;
overflow: hidden;
position: relative;
/* 相对定位 */
}
a.button:hover {
color: yellow;
}
a.button::before {
content: "";
display: block;
width: 300px;
height: 300px;
background-image: radial-gradient(yellow, transparent 40%);
position: absolute;
/* left: 0px;
top: 0px; */
left: var(--left);
/* 使用自定义属性 --left 来控制彩色毛毛球的位置(水平方向)*/
top: var(--top);
/* 使用自定义属性 --top 来控制彩色毛毛球的位置(垂直方向)*/
margin-left: -150px;
margin-top: -150px;
display: none;
}
a.button:hover::before {
display: block;
/* 鼠标移入时显示彩色毛毛球 */
}
a.button::after {
content: "";
display: block;
position: absolute;
/* 绝对定位 */
left: 2px;
right: 2px;
top: 2px;
bottom: 2px;
background-color: #333;
border-radius: 5px;
}
.m-center {
margin: 50px auto;
}
a.button span {
/* 相对定位用来调整元素层叠顺序 */
position: relative;
z-index: 1;
/* z-index: 1; 提高层级,确保文字在最上层显示 */
}
</style>
</head>
<body>
<a href="#" class="button m-center">
<span>加入购物车</span>
</a>
<script>
// 获取所有按扭
const button = document.querySelector("a.button");
// 遍历按扭,给每个按扭添加鼠标移入事件监听器
button.onmousemove = function (e) {
const pageX = e.pageX; // 获取鼠标与浏览器左边距离
const pageY = e.pageY; // 获取鼠标与浏览器顶部距离
const left = this.offsetLeft; // 获取按扭距离浏览器左边距离
const top = this.offsetTop; // 获取按扭距离浏览器左边距离
// 计算得到 鼠标相对于按扭左边和上边距离
const x = pageX - left;
const y = pageY - top;
// 给伪元素设置自定义属性 --left 和 --top,用来控制彩色毛毛球的位置
this.style.setProperty("--left", x + "px");
this.style.setProperty("--top", y + "px");
// 注意这一步,要将 button::before css 选择器的 中的 top 和 left 修改为
// top:var(--top); left:var(--left);
};
</script>
</body>
</html>
2. 带悬停效果的导航
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>带悬停效果的导航</title>
<style>
body,
ul {
margin: 0;
}
ul {
padding: 0;
list-style: none;
}
a {
text-decoration: none;
color: #000;
}
.nav {
height: 50px;
background-color: skyblue;
text-align: center;
margin-top: 50px;
}
.nav ul {
/* background-color: khaki; */
width: 1200px;
margin: 0 auto; /* 水平居中 */
height: inherit; /* 继承父元素值 */
}
.nav ul li {
float: left;
font-size: 16px;
height: inherit; /* 继承父元素值 */
}
.nav ul li a {
display: block;
padding: 0px 20px;
line-height: 50px;
position: relative; /* 添加相对定位 */
z-index: 0; /* 创建自己的层叠上下文 */
}
.nav ul li a::after {
content: "";
position: absolute; /* 相对a标签绝对定位*/
left: 0;
right: 0;
top: -5px;
bottom: -5px;
background-color: rgb(2, 139, 194);
display: none;
z-index: -1; /* 让滑块显示在文字下面 */
}
.nav ul li a:hover {
color: #fff;
}
.nav ul li a:hover::after {
display: block;
}
</style>
</head>
<body>
<div class="nav">
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">免费直播课</a></li>
<li><a href="#">web前端工程师</a></li>
<li><a href="#">Java架构师</a></li>
<li><a href="#">实战案例视频</a></li>
<li><a href="#">关于我们</a></li>
</ul>
</div>
</body>
</html>
3. 弹性滑动导航
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>弹性滑动导航</title>
<style>
body,
ul {
margin: 0;
}
ul {
padding: 0;
list-style: none;
}
a {
text-decoration: none;
color: #000;
}
.nav {
height: 50px;
background-color: skyblue;
text-align: center;
margin-top: 50px;
}
.nav ul {
width: 1200px;
margin: 0 auto;
height: inherit;
position: relative; /* 相对定位 */
z-index: 0; /* 创建自己的层叠上下文 */
}
.nav ul li {
float: left;
font-size: 16px;
height: inherit; /* 继承 */
}
.nav ul li a {
display: block;
padding: 0px 20px;
line-height: 50px;
}
.nav ul li:first-child a {
color: #fff;
}
.nav ul li:last-child {
width: 72px;
height: 60px;
background-color: rgb(3, 135, 187);
/*这个li用来做底部蓝色滑块,需要相对ul进行绝对定位*/
position: absolute;
left: 0px;
top: -5px;
z-index: -1;
/* 添加过渡动画 */
transition: left 0.3s, width 0.3s;
}
/* 这里的功能需要用js来实现,
以下只是用css简单演示实现原理 */
.nav ul li:hover ~ .move {
width: 110px;
left: 348px;
}
</style>
</head>
<body>
<div class="nav">
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">免费直播课</a></li>
<li><a href="#">web前端工程师</a></li>
<li><a href="#">Java架构师</a></li>
<li><a href="#">实战案例视频</a></li>
<li><a href="#">关于我们</a></li>
<!--这个li是用来做深蓝色的小滑块-->
<li class="move"></li>
</ul>
</div>
<script>
const move = document.querySelector(".move");
const oUl = document.querySelector(".nav ul ");
// 用来保存前一个鼠标移入的元素 (最开始为第一个li中的a )
let prevA = document.querySelector(".nav ul li:first-child a");
oUl.addEventListener("mouseover", function (e) {
// 获取鼠标移入到的元素是否是 a
const target = e.target;
if (target.tagName.toLowerCase() !== "a") return;
// 如果是a元素,则获取a元素的宽、高、与 ul左边的距离
const width = target.offsetWidth;
const height = target.offsetHeight;
const left = target.offsetLeft;
// 动态设置 move的宽度,高度和 left值
move.style.width = width + "px";
move.style.height = height + 10 + "px";
move.style.left = left + "px";
// 当前a标签文字颜色变为白色,其它的全还原
if (prevA) {
console.log(prevA);
prevA.style.color = "#000";
}
move.style.display = "block";
target.style.color = "#fff";
prevA = target;
});
</script>
</body>
</html>