CSS 常见效果实现集锦
本文收集了一些常见且实用的 CSS 效果实现方案。从基础的悬停动画到现代的 Houdini API,这些效果都经过精心设计和优化,可以直接应用到实际项目中。
目录
导航栏下划线跟随效果
这是一个常见的导航栏交互效果,当鼠标悬停在导航项上时,下划线会平滑地跟随移动。
实现要点
- 使用
transition实现平滑动画 - 记录最后停留位置,实现鼠标离开时的回归动画
- 通过 JavaScript 动态计算下划线宽度和位置
效果预览
代码实现
html
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>导航栏下划线跟随效果</title>
<style>
.nav {
display: flex;
position: relative;
width: 800px;
margin: 100px auto;
}
.nav-item {
padding: 20px;
font-size: 18px;
cursor: pointer;
text-align: center;
flex: 1;
}
.nav-item:hover {
color: #1890ff;
}
.indicator {
position: absolute;
bottom: 0;
height: 2px;
background-color: #1890ff;
transition: all 0.3s ease 0.1s;
}
</style>
</head>
<body>
<div class="nav">
<div class="nav-item">首页</div>
<div class="nav-item">产品</div>
<div class="nav-item">服务</div>
<div class="nav-item">关于我们</div>
<div class="indicator"></div>
</div>
<script>
const items = document.querySelectorAll('.nav-item');
const indicator = document.querySelector('.indicator');
let lastHoveredItem = items[0]; // 记录最后停留的位置
// 初始化indicator位置
function initIndicator() {
indicator.style.width = `${items[0].offsetWidth}px`;
indicator.style.left = `${items[0].offsetLeft}px`;
}
items.forEach(item => {
item.addEventListener('mouseenter', () => {
indicator.style.width = `${item.offsetWidth}px`;
indicator.style.left = `${item.offsetLeft}px`;
lastHoveredItem = item;
});
});
// 鼠标离开导航区域时,回到最后停留的位置
document.querySelector('.nav').addEventListener('mouseleave', () => {
indicator.style.width = `${lastHoveredItem.offsetWidth}px`;
indicator.style.left = `${lastHoveredItem.offsetLeft}px`;
});
// 初始化
initIndicator();
</script>
</body>
</html>玻璃镜片流光效果
这是一个现代化的卡片设计,结合了玻璃拟态(Glassmorphism)和流光溢彩的动画效果。
实现要点
- 使用
linear-gradient创建渐变背景 - 通过伪元素实现流光动画
- 利用
opacity和transition控制动画效果
效果预览

关键CSS属性解析
css
/* 玻璃镜片效果 */
.box::before {
background: linear-gradient(
110deg,
rgba(255, 255, 255, 0.9),
rgba(255, 255, 255, 0) 20%,
rgba(255, 255, 255, 0) 70%,
rgba(255, 255, 255, 0.9)
);
}
/* 流光动画效果 */
.box::after {
transform: skew(-20deg); /* 创建倾斜效果 */
box-shadow: 0 0 10vmin 2.5vmin rgba(255, 255, 255, 1); /* 发光效果 */
}代码实现
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>玻璃镜片流光效果</title>
<style>
/* 容器样式 */
.container {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #1a1a1a;
/* 深色背景突出效果 */
}
/* 卡片基础样式 */
.box {
position: relative;
/* 相对定位,作为伪元素的定位父级 */
width: 400px;
height: 200px;
background: linear-gradient(45deg, #2196f3, #ff4685);
border-radius: 15px;
overflow: hidden;
/* 隐藏溢出部分,使流光效果不超出卡片 */
cursor: pointer;
}
/* 玻璃镜片效果 - 使用::before */
.box::before {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
/* 创建渐变效果,形成玻璃质感 */
background: linear-gradient(110deg,
rgba(255, 255, 255, 0.9),
rgba(255, 255, 255, 0) 20%,
rgba(255, 255, 255, 0) 70%,
rgba(255, 255, 255, 0.9));
opacity: 1;
transition: opacity 0.65s ease;
/* 过渡动画 */
}
/* 流光效果 - 使用::after */
.box::after {
content: "";
position: absolute;
background-color: rgba(255, 255, 255, 0.6);
width: 5vmin;
top: 0;
bottom: 0;
left: -100%;
/* 初始位置在卡片外 */
transform: skew(-20deg);
/* 倾斜效果 */
/* 发光效果 */
box-shadow: 0 0 10vmin 2.5vmin rgba(255, 255, 255, 1);
transition: all 0.25s ease;
}
/* 悬停时玻璃效果消失 */
.box:hover::before {
opacity: 0;
}
/* 悬停时触发流光动画 */
.box:hover::after {
left: 400px;
/* 移动到卡片右侧 */
transition: left 0.5s ease;
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
</div>
</body>
</html>轮盘按钮效果
这是一个创意十足的交互设计,适用于需要展示多个快捷操作的场景。按钮初始呈现为圆形,悬停时展开成扇形菜单。
效果预览

关键技术
- 扇形计算
css
/* 扇形区域计算公式:
* 旋转角度 = -160° + (n-1) * 50°
* 其中 n 为扇形序号(1,2,3)
*/
.sectorBox:nth-child(1) {
transform: rotate(-160deg) skewY(40deg);
}
.sectorBox:nth-child(2) {
transform: rotate(-110deg) skewY(40deg);
}
.sectorBox:nth-child(3) {
transform: rotate(-60deg) skewY(40deg);
}- 文字方向修正
css
/* 文字需要反向旋转以保持正确方向 */
.sectorBox:nth-child(1) span {
transform: skewY(-40deg) rotate(160deg);
}使用注意事项
- 建议控制菜单项数量在3-5个之间
- 注意移动端触发区域的大小
- 可以通过调整 transform-origin 改变展开中心点
代码实现
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>轮盘按钮效果</title>
<style>
html,
body {
background-color: #000;
}
/* 外层容器:固定定位,初始状态为圆形 */
.RouletteOut {
background: rgba(255, 255, 255, 0.2);
border-radius: 500px;
width: 120px;
height: 120px;
position: fixed;
bottom: 1.5vw;
left: 3vw;
transform-origin: center center;
/* 变形的原点设置为中心 */
transition: all 0.3s ease;
/* 添加过渡效果 */
overflow: hidden;
cursor: pointer;
}
/* 内层圆形:始终保持在外层容器的中心 */
.RouletteIn {
background: rgba(255, 255, 255, 0.6);
border-radius: 100px;
width: 88px;
height: 88px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
/* 使用transform居中 */
transform-origin: center center;
transition: all 0.3s ease;
z-index: 1;
/* 确保在扇形区域上方 */
overflow: hidden;
}
/* 鼠标悬停时外层容器的样式 */
.menuShow.RouletteOut {
width: 337px;
height: 337px;
/* 扩大尺寸时,调整位置保持中心点不变 */
bottom: calc(1.5vw - 108px);
left: calc(3vw - 108px);
}
/* 鼠标悬停时内层圆形的样式 */
.menuShow .RouletteIn {
width: 112px;
height: 112px;
}
/* 扇形区域的容器 */
.circleContainer {
position: relative;
width: 337px;
height: 337px;
border-radius: 50%;
overflow: hidden;
z-index: -1;
display: none;
/* 初始状态隐藏 */
}
/* 显示扇形区域 */
.menuShow .circleContainer {
display: block;
}
/* 单个扇形的基础样式 */
.sectorBox {
position: absolute;
top: 50%;
left: 50%;
width: 50%;
height: 50%;
transform-origin: 0 0;
/* 变形原点设置在左上角 */
font-size: 14px;
font-family: Arial-Regular, Arial;
font-weight: 400;
color: #FFFFFF;
}
/* 扇形内的文字 */
.sectorBox span {
position: absolute;
white-space: nowrap;
}
/* 三个扇形区域的旋转和倾斜角度 */
.sectorBox:nth-child(1) {
transform: rotate(-160deg) skewY(40deg);
}
.sectorBox:nth-child(1) span {
transform: skewY(-40deg) rotate(160deg);
}
.sectorBox:nth-child(2) {
transform: rotate(-110deg) skewY(40deg);
}
.sectorBox:nth-child(2) span {
transform: skewY(-40deg) rotate(110deg);
}
.sectorBox:nth-child(3) {
transform: rotate(-60deg) skewY(40deg);
}
.sectorBox:nth-child(3) span {
transform: skewY(-40deg) rotate(60deg);
}
/* 扇形hover效果 */
.sectorBox:hover {
background: linear-gradient(63deg,
rgba(215, 255, 55, 0.9) 0%,
rgba(215, 255, 55, 0.8) 32%,
rgba(215, 255, 55, 0.18) 71%,
rgba(74, 0, 224, 0) 100%,
rgba(215, 255, 55, 0) 100%);
box-shadow: 0px 0px 16px 0px rgba(200, 173, 255, 0.8);
color: #373737;
}
</style>
</head>
<body>
<!-- 主要结构 -->
<div class="RouletteOut" id="rouletteOut">
<!-- 中心圆形 -->
<div class="RouletteIn"></div>
<!-- 扇形区域容器 -->
<div class="circleContainer">
<!-- 三个扇形区域 -->
<div class="sectorBox" onclick="handleClick(0)">
<span style="left: 20%; top: 30%;">Mine</span>
</div>
<div class="sectorBox" onclick="handleClick(1)">
<span style="bottom: 60%; left: 10%;">Featured</span>
</div>
<div class="sectorBox" onclick="handleClick(2)">
<span style="left: 20%; top: 30%;">Recent</span>
</div>
</div>
</div>
<script>
// 获取外层容器元素
const rouletteOut = document.getElementById('rouletteOut');
// 添加鼠标进入事件
rouletteOut.addEventListener('mouseenter', () => {
rouletteOut.classList.add('menuShow');
});
// 添加鼠标离开事件
rouletteOut.addEventListener('mouseleave', () => {
rouletteOut.classList.remove('menuShow');
});
// 扇形点击处理函数
function handleClick(index) {
console.log('点击了第', index + 1, '个扇形');
// 这里可以添加点击后的具体操作
}
</script>
</body>
</html>立体书签角标
一个精致的立体书签角标效果,适用于标记重要信息或状态。通过叠加阴影和伪元素创造出逼真的折纸效果。
效果预览

代码实现
html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>立体书签角标示例</title>
<style>
/* 重置图片默认间距 */
img {
vertical-align: bottom;
}
/* 主容器 - 用于放置内容和角标 */
.cornerMarkBox {
width: 400px;
height: 500px;
position: relative; /* 为角标定位提供参考 */
background: #1890ff;
overflow: visible; /* 允许角标超出容器 */
margin: 20px;
display: inline-block;
}
/* 角标容器 - 控制角标的位置和溢出隐藏 */
.MarkBox {
width: 106px;
height: 108px;
overflow: hidden; /* 隐藏旋转后多余的部分 */
position: absolute; /* 相对主容器定位 */
top: -6px;
left: 297px;
}
/* 角标内部样式 - 实现旋转和立体效果 */
.insideBox {
line-height: 18px;
text-align: center;
transform: rotate(45deg); /* 45度旋转实现角标效果 */
position: relative;
padding: 8px 0;
left: -8px;
top: 25px;
width: 150px; /* 宽度要足够以便旋转后覆盖角落 */
background: red;
color: white;
box-shadow: 0 5px 5px rgba(0, 0, 0, 0.1); /* 添加阴影提升立体感 */
letter-spacing: 1px;
}
/* 使用伪元素创建立体效果的两个小三角 */
.insideBox:before,
.insideBox:after {
content: "";
border-top: 4px solid #4e7c7d; /* 暗色边框营造立体感 */
border-left: 4px solid transparent;
border-right: 4px solid transparent;
position: absolute;
bottom: -4px;
}
/* 左侧小三角 */
.insideBox:before {
left: 0;
}
/* 右侧小三角 */
.insideBox:after {
right: 0;
}
</style>
</head>
<body>
<!-- 主要结构 -->
<div class="cornerMarkBox">
<!-- 内容区域 -->
<img style="width:auto;height:auto;max-width:100%;max-height: 100%"
src="https://preview.qiantucdn.com/58pic/44/05/54/47858PIC4pj2zTn5Dhzr6_PIC2018.png!w1024_new_0">
<!-- 角标区域 -->
<div class="MarkBox">
<div class="insideBox">水香木鱼</div>
</div>
</div>
</body>
</html>文字渐入动画效果
一个优雅的文字动画效果,通过逐字延迟显示创造出流畅的渐入体验。适用于标题、提示文字等需要吸引注意力的场景。
实现原理
- 使用 JavaScript 将文本拆分为单个字符
- 为每个字符添加延迟动画
- 利用 CSS custom properties 控制动画延迟
关键代码解析
javascript
// 文本拆分处理
text.innerHTML = text.textContent
.split('')
.map(char => `<span class="letter">
${char === ' ' ? ' ' : char}
</span>`)
.join('');
// 设置动画延迟
letters.forEach((letter, index) => {
letter.style.setProperty('--delay', `${index * 0.05}s`);
});动画优化建议
- 使用 cubic-bezier 创建更自然的动画曲线
- 控制合适的延迟时间间隔(建议 0.05s-0.08s)
- 考虑添加 will-change 优化性能
性能注意事项
- 避免在过长文本中使用
- 考虑使用 requestAnimationFrame 优化动画
- 添加 transform 硬件加速
效果预览

代码实现
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文字渐入动画效果</title>
<style>
/* 容器样式 */
.text-container {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
font-size: 24px;
}
/* 文字容器基础样式 */
.generating-tip {
position: relative;
display: inline-block;
}
/* 每个字母的基础样式 */
.letter {
display: inline-block;
opacity: 0; /* 初始设置为透明 */
}
/* 添加动画效果 */
.letter.animate {
/* 使用cubic-bezier创建弹跳效果 */
animation: moveIn 1s cubic-bezier(0.89, 0.32, 0.84, 1.3) forwards;
/* animation-delay 将由 JS 通过 --delay 变量设置 */
animation-delay: var(--delay);
}
/* 定义动画关键帧 */
@keyframes moveIn {
from {
opacity: 0;
transform: translateY(-100%);
}
to {
opacity: 1;
transform: translateY(0);
}
}
</style>
</head>
<body>
<div class="text-container">
<div class="generating-tip">Multiple views, please be patient.</div>
</div>
<script>
// 等待DOM加载完成
document.addEventListener('DOMContentLoaded', () => {
const text = document.querySelector('.generating-tip');
// 1. 将文本分割成单个字符并包装在span中
text.innerHTML = text.textContent
.split('')
.map(char => `<span class="letter">${char === ' ' ? ' ' : char}</span>`)
.join('');
// 2. 为每个字母设置延迟时间
const letters = document.querySelectorAll('.letter');
letters.forEach((letter, index) => {
// 设置每个字母的延迟时间,每个间隔50ms
letter.style.setProperty('--delay', `${index * 0.05}s`);
// 添加动画类
letter.classList.add('animate');
});
});
</script>
</body>
</html>中间透明圆角渐变色边框的容器
一个现代化的 UI 容器效果,结合了渐变边框、毛玻璃效果和圆角设计。适用于卡片、弹窗等需要突出视觉层次的界面元素。
实现要点
- 使用
backdrop-filter实现毛玻璃效果 - 通过
mask属性创建中空边框 - 利用 CSS 渐变实现边框颜色过渡
效果预览

代码实现
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>透明渐变边框容器</title>
<style>
/* 创建一个深色背景以便更好地展示效果 */
body {
background: #1a1a1a;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
}
/* 主容器样式 */
.box {
width: 500px;
height: 500px;
border-radius: 16px;
/* 添加毛玻璃效果 */
backdrop-filter: blur(4px);
padding: 0 min(1.32vw, 30px);
/* 设置容器背景为半透明渐变 */
background: linear-gradient(180deg,
rgba(0, 0, 0, 0.30) 0%,
rgba(0, 0, 0, 0.20) 100%
);
position: relative;
/* 添加一些内容样式 */
color: white;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
}
/* 渐变边框效果 */
.box::before {
/* 定义边框相关变量 */
--border-width: 2px;
--border-color: linear-gradient(
10deg,
rgb(166, 36, 227) 0%,
rgb(190, 160, 235) 45%,
rgb(190, 160, 235) 55%,
rgb(67, 0, 255) 100%
);
/* 绝对定位并居中 */
position: absolute;
content: '';
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/* 设置尺寸和基础样式 */
width: 100%;
height: 100%;
box-sizing: border-box;
display: block;
border-radius: inherit;
padding: var(--border-width);
/* 设置渐变背景 */
background: var(--border-color);
background-clip: padding-box;
/* 关键:使用mask实现中间透明效果 */
-webkit-mask-image: linear-gradient(red, red), linear-gradient(red, red);
-webkit-mask-clip: padding-box, content-box;
mask-composite: exclude;
/* 将伪元素置于内容下方 */
z-index: -10;
}
</style>
</head>
<body>
<div class="box">
渐变边框容器
</div>
</body>
</html>CSS圆形贴合裁剪效果
效果介绍 ✨
在现代网页设计中,我们经常需要实现一些独特的视觉效果。今天要介绍的是如何使用CSS实现两个元素之间的圆形贴合裁剪效果,这种效果常用于创建连接的标签、气泡对话框等设计元素。 
实现原理 💡
这个效果主要通过以下几个关键技术点实现:
- 使用
border-radius创建圆形元素 - 利用
radial-gradient实现圆形裁剪效果 - 通过定位和z-index控制元素层级关系
代码实现 🔨
html
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>圆形贴合裁剪效果</title>
<style>
body {
padding: 10px;
}
.inversePair {
border: 1px solid black;
display: inline-block;
position: relative;
height: 100px;
text-align: center;
line-height: 100px;
vertical-align: middle;
}
#a {
width: 100px;
border-radius: 50px;
background: grey;
z-index: 1;
}
#b {
width: 200px;
padding-left: 30px;
margin-left: -30px;
border-left: none;
background-image: radial-gradient(
circle closest-corner at -23px 50%,
transparent 0,
transparent 55px,
black 56px,
grey 57px
);
}
</style>
</head>
<body>
<div id="a" class="inversePair">A</div>
<div id="b" class="inversePair">B</div>
</body>
</html>关键点解析 🔍
圆形元素A:
- 使用
border-radius: 50px创建圆形 - 设置
z-index: 1确保显示在上层
- 使用
元素B的裁剪效果:
- 使用
radial-gradient创建径向渐变 -23px 50%定位渐变的中心点circle closest-corner确定渐变的形状- 使用透明色和实色的过渡创建裁剪效果
- 使用
浏览器兼容性 🌐
为确保更好的兼容性,建议添加各种浏览器前缀:
-webkit-radial-gradient-moz-radial-gradient-ms-radial-gradient-o-radial-gradient
使用场景 💼
- 标签连接效果
- 气泡对话框
- 导航菜单设计
- 时间轴节点
注意事项 ⚠️
- 确保两个元素的高度保持一致
- 注意调整间距和裁剪半径以获得最佳效果
- 在移动端需要注意响应式适配
跑马灯效果实现
跑马灯(Marquee)是一种常见的UI效果,能够实现内容的水平滚动展示,适用于新闻通知、合作伙伴展示等场景。下面介绍三种实现方案,各有优缺点。

实现方案对比
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| 废弃的marquee标签 | 实现简单 | 已被W3C废弃,兼容性差 | 仅作为了解,不推荐使用 |
| 绝对定位+动画延时 | 精确控制每个元素 | 实现复杂,需计算延时 | 固定数量的元素循环滚动 |
| 双份元素循环动画 | 实现简单,性能好 | 需额外DOM元素 | 大多数跑马灯场景的最佳选择 |
1. 废弃的 marquee 标签
这是最早的跑马灯实现方式,虽然使用简单,但已被W3C标准废弃,现代浏览器可能不再支持。
html
<marquee behavior="scroll" direction="left">
<div class="marquee-item"></div>
<div class="marquee-item"></div>
<div class="marquee-item"></div>
</marquee>2. 通过绝对定位+动画延时
这种方案通过精确计算每个元素的动画延时,实现无缝循环效果。
html
<div class="wrapper">
<div class="item" style="--count: 1"></div>
<div class="item" style="--count: 2"></div>
<div class="item" style="--count: 3"></div>
<!-- 更多元素... -->
</div>css
.wrapper {
--logo-width: 200px;
--logo-height: 100px;
--logo-count: 8;
--duration: 30s;
width: 90%;
max-width: 1200px;
margin-inline: auto;
position: relative;
height: var(--logo-height);
overflow: hidden;
/* 两侧渐隐效果 */
mask-image: linear-gradient(
to right,
rgba(0, 0, 0, 0),
rgba(0, 0, 0, 1) 20%,
rgba(0, 0, 0, 1) 80%,
rgba(0, 0, 0, 0)
);
}
@keyframes scrollLeft {
to {
left: calc(var(--logo-width) * -1);
}
}
.item {
width: var(--logo-width);
height: var(--logo-height);
background-color: #3498db;
border-radius: 6px;
position: absolute;
left: calc(var(--logo-width) * var(--logo-count));
animation-name: scrollLeft;
animation-duration: var(--duration);
animation-timing-function: linear;
animation-iteration-count: infinite;
/* 关键点:动态计算每个元素的延时 */
animation-delay: calc(var(--duration) / var(--logo-count) * (var(--logo-count) - var(--count)) * -1);
}实现原理说明:
- 所有元素都是绝对定位,初始位置在容器右侧
- 通过 CSS 变量计算每个元素的动画延时
- 元素从右向左移动,当移出视口后,因为动画是无限循环的,会重新从右侧进入
- 通过 mask-image 创建两侧渐隐效果,提升视觉体验
3. 双份元素进行动画循环(✨推荐)
这是现代网页中最常用的跑马灯实现方式,原理简单且效果良好。
html
<div class="marquee-container">
<!-- 第一组元素 -->
<div class="marquee">
<span>#CSS</span>
<span>#HTML</span>
<span>#JavaScript</span>
<span>#SVG</span>
<span>#React</span>
<span>#Vue</span>
</div>
<!-- 第二组完全相同的元素 -->
<div class="marquee">
<span>#CSS</span>
<span>#HTML</span>
<span>#JavaScript</span>
<span>#SVG</span>
<span>#React</span>
<span>#Vue</span>
</div>
</div>css
@keyframes marquee {
to {
transform: translateX(calc(-100% - var(--gap)));
}
}
.marquee-container {
--gap: 1rem;
position: relative;
display: flex;
overflow: hidden;
gap: var(--gap);
/* 两侧渐隐效果 */
mask: linear-gradient(90deg, transparent, #000 5% 95%, transparent);
/* 可选:增加内边距,提升视觉效果 */
padding-block: 1rem;
background: #f8f9fa;
border-radius: 8px;
}
.marquee {
flex-shrink: 0;
display: flex;
justify-content: space-around;
gap: var(--gap);
min-width: 100%;
/* 关键动画设置 */
animation: marquee 20s linear infinite;
}
/* 鼠标悬停时暂停动画 */
.marquee-container:hover .marquee {
animation-play-state: paused;
}
/* 元素样式 */
.marquee span {
padding: 0.5rem 1rem;
background: #e9ecef;
border-radius: 4px;
font-weight: bold;
color: #495057;
}实现原理说明:
- 创建两组完全相同的元素
- 将它们放在同一个容器中,水平排列
- 让整个容器向左移动一个组的宽度
- 由于有两组相同的元素,当第一组完全移出视口时,第二组刚好完全进入视口
- 动画无限循环,创造无缝滚动的效果
性能优化tips
- 使用 transform 而非 left/top 属性:transform 属性触发的是 GPU 加速,性能更好
- 使用 will-change: transform:提前告知浏览器元素将发生变化,优化渲染性能
- 设置合适的动画时长:太短的动画会显得急促,太长则缺乏视觉吸引力
- 考虑使用 requestAnimationFrame:对于复杂场景,可用JS控制动画,性能更优
响应式适配
对于移动端,可以调整速度和元素大小:
css
@media (max-width: 768px) {
.marquee-container {
--gap: 0.5rem;
}
.marquee {
animation-duration: 15s; /* 移动端屏幕小,适当加快速度 */
}
.marquee span {
padding: 0.25rem 0.5rem;
font-size: 0.875rem;
}
}完整实现代码
html
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>现代跑马灯效果</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
padding: 2rem;
max-width: 1200px;
margin: 0 auto;
background-color: #f5f5f5;
}
h2 {
color: #333;
margin-bottom: 1.5rem;
}
/* 跑马灯容器 */
.marquee-container {
--gap: 1rem;
position: relative;
display: flex;
overflow: hidden;
gap: var(--gap);
border-radius: 8px;
background: white;
box-shadow: 0 4px 6px rgba(0,0,0,0.05);
margin-bottom: 2rem;
/* 两侧渐隐效果 */
mask: linear-gradient(90deg, transparent, #000 5% 95%, transparent);
}
/* 跑马灯内容 */
.marquee {
flex-shrink: 0;
display: flex;
align-items: center;
gap: var(--gap);
min-width: 100%;
padding: 1rem 0;
/* 动画设置 */
animation: marquee 25s linear infinite;
will-change: transform;
}
/* 暂停效果 */
.marquee-container:hover .marquee {
animation-play-state: paused;
}
/* 动画关键帧 */
@keyframes marquee {
to {
transform: translateX(calc(-100% - var(--gap)));
}
}
/* 内容项样式 */
.marquee__item {
display: flex;
align-items: center;
justify-content: center;
height: 80px;
padding: 0 1.5rem;
background-color: #f8f9fa;
border-radius: 8px;
font-weight: 600;
color: #444;
box-shadow: 0 2px 4px rgba(0,0,0,0.04);
transition: transform 0.3s, box-shadow 0.3s;
}
.marquee__item:hover {
transform: translateY(-5px);
box-shadow: 0 6px 12px rgba(0,0,0,0.08);
}
/* 响应式调整 */
@media (max-width: 768px) {
.marquee-container {
--gap: 0.5rem;
}
.marquee {
animation-duration: 20s;
}
.marquee__item {
height: 60px;
padding: 0 1rem;
font-size: 0.875rem;
}
}
</style>
</head>
<body>
<h2>现代跑马灯效果</h2>
<div class="marquee-container">
<!-- 第一组元素 -->
<div class="marquee">
<div class="marquee__item">🎨 CSS</div>
<div class="marquee__item">🌐 HTML</div>
<div class="marquee__item">💻 JavaScript</div>
<div class="marquee__item">⚛️ React</div>
<div class="marquee__item">🖼️ SVG</div>
<div class="marquee__item">📱 响应式设计</div>
<div class="marquee__item">🔄 动画</div>
</div>
<!-- 第二组完全相同的元素 -->
<div class="marquee">
<div class="marquee__item">🎨 CSS</div>
<div class="marquee__item">🌐 HTML</div>
<div class="marquee__item">💻 JavaScript</div>
<div class="marquee__item">⚛️ React</div>
<div class="marquee__item">🖼️ SVG</div>
<div class="marquee__item">📱 响应式设计</div>
<div class="marquee__item">🔄 动画</div>
</div>
</div>
</body>
</html>