在网页设计中,让图片以淡入淡出方式出现或切换,是提升用户体验的常见手段。纯CSS就能完成这类效果,不需要依赖任何脚本。其本质是通过改变图片的透明度,并让浏览器在一段时间内平滑过渡这个数值,从而产生渐隐渐显的视觉感受。

一、使用opacity与transition实现悬停淡入
最基础的淡入淡出效果,是利用opacity属性控制元素透明度,再用transition指定过渡时间和缓动函数。当鼠标悬停到容器上时,图片从透明变为不透明,移开后又慢慢消失。
这种写法适合做图片悬停说明、相册预览等轻交互。它的优点是实现简单、性能较好,因为只涉及合成层透明度变化;缺点是不能自动播放,必须依赖用户行为触发。下面的代码展示了一个默认透明、悬停后淡入的图片块。
/* 容器相对定位,方便内部图片绝对填充 */
.img-box {
position: relative;
width: 300px;
height: 200px;
}
/* 图片初始透明,并设置0.6秒淡入淡出 */
.img-box img {
width: 100%;
height: 100%;
opacity: 0;
transition: opacity 0.6s ease-in-out;
}
/* 鼠标移入时完全显示 */
.img-box:hover img {
opacity: 1;
}
1.1 初始状态的重要性
很多初学者忘记给图片设置初始opacity:0,结果页面加载时图片直接显示,悬停反而没有变化。一定要明确写出起始值和结束值,过渡才能生效。
另外,如果图片加载较慢,可以在容器上先设背景色,避免布局抖动。结合loading="lazy"属性还能优化性能,但这属于HTML层面配合,不影响CSS过渡逻辑。
1.2 缓动函数选择
ease-in-out是最自然的加速减速曲线,也可以用cubic-bezier()自定义。例如cubic-bezier(0.4,0,0.2,1)是材质设计推荐的标准曲线,视觉上更舒服。
不建议用linear做淡入淡出,因为匀速会让人感觉突兀。过渡时间一般控制在0.3秒到0.8秒之间,过短像闪烁,过长又显得拖沓。
二、使用animation实现自动淡入淡出轮播
如果希望图片自己循环淡入淡出,比如首页广告位,可以用@keyframes定义动画,再用animation属性绑定到元素上。这种方式完全不需要JS定时器。
思路是让多张图片重叠摆放,分别给它们不同的动画延迟,使每张图在各自时间段内显示再隐藏,从而模拟轮播。下面以两张图交替为例。
<div class="fade-slider"> <img class="slide s1" src="https://ipipp.com/a.jpg" alt="图1"> <img class="slide s2" src="https://ipipp.com/b.jpg" alt="图2"> </div>
.fade-slider {
position: relative;
width: 400px;
height: 250px;
}
.slide {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
/* 每张图动画时长6秒,无限循环 */
animation: fade 6s infinite;
}
/* 第二张延迟3秒,错开显示 */
.s2 {
animation-delay: 3s;
}
@keyframes fade {
0% { opacity: 0; }
20% { opacity: 1; }
50% { opacity: 1; }
70% { opacity: 0; }
100% { opacity: 0; }
}
2.1 多图时间分配计算
假设有N张图,单张可见时间加过渡时间总和为T,那么动画总时长应设为N乘以T,每张图延迟为自身序号乘T。上面例子中两张图,各占3秒可见与过渡,总时长6秒,第二张延后3秒,刚好衔接。
如果图片数量变多,手写延迟容易出错,此时虽然纯CSS可行,但维护成本高。这也是为什么复杂轮播最终常引入JS或框架组件。
2.2 性能与兼容性注意
动画只改opacity,浏览器通常只在合成线程处理,不触发重排,因此流畅度不错。老版本IE不支持animation,需要加-ms-前缀或放弃支持。
为避免动画开始时页面闪一下,可给图片加backface-visibility:hidden。移动端还可配合will-change:opacity提前提升图层,但别滥用,否则内存占用上升。
三、两种方案对比与选用建议
transition方案胜在简单直观,适合响应用户操作的局部效果;animation方案适合无人值守的自动展示,但代码量随图片数线性增长。
从可访问性看,淡入淡出不应作为传递关键信息的唯一方式,因为部分读屏软件会忽略透明度变化。下面用表格归纳差异。
| 对比项 | transition方式 | animation方式 |
|---|---|---|
| 触发条件 | 需悬停或类切换 | 页面加载后自动 |
| 代码复杂度 | 低 | 中,多图时高 |
| 是否需JS | 否 | 否 |
| 典型用途 | 悬停预览、提示 | 背景轮播、广告 |
3.1 混合使用技巧
实际项目里两者可结合:用animation做自动轮播,用transition做鼠标悬停暂停时的微调。例如悬停时通过animation-play-state:paused停掉动画,再叠加transition控制遮罩。
但要注意样式优先级,animation运行时会覆盖普通opacity声明,暂停后transition才能接手,写的时候多用浏览器审查工具观察计算值。
3.2 常见误区澄清
有人以为用visibility也能淡入淡出,其实visibility不支持平滑过渡,它只有可见与隐藏两态,和opacity混用虽能解决焦点问题,但渐变仍靠opacity完成。
还有人把display:none拿来过渡,这是无效的,因为display变化不进入过渡队列。隐藏元素请优先用opacity加绝对定位移出视口,而不是display。
四、完整示例:带说明文字的淡入卡片
最后给出一个综合例子,图片默认半透明,悬停清晰并显示描述,同时用animation让边框光晕呼吸,展示CSS组合能力。
<div class="card"> <img src="https://ipipp.com/c.jpg" alt="示例"> <p class="desc">悬停查看详情</p> </div>
.card {
position: relative;
width: 260px;
border: 1px solid #ccc;
border-radius: 8px;
overflow: hidden;
}
.card img {
width: 100%;
display: block;
opacity: 0.6;
transition: opacity 0.4s ease;
}
.card:hover img {
opacity: 1;
}
.desc {
position: absolute;
bottom: 0;
margin: 0;
padding: 8px;
width: 100%;
background: rgba(0,0,0,0.5);
color: #fff;
transform: translateY(100%);
transition: transform 0.4s ease;
}
.card:hover .desc {
transform: translateY(0);
}
以上代码里,图片和文字说明分别用opacity与transform过渡,两者互不干扰又共同构成淡入效果。这种拆解思维,能让你在更复杂界面中灵活安排每一种视觉变化。
掌握这些CSS技巧后,多数图片渐显需求都能纯样式解决,既减轻脚本负担,也方便设计师直接调整参数。遇到极端兼容场景再考虑JS补充即可。
CSSopacitytransition修改时间:2026-08-06 00:45:47