有这么一个常见需求:hover显示二维码,淡出一张图片,移出则图片消失。opacity很好做动画,问题是opacity为0时怎么让元素真的从页面消失
当使用CSS的opacity
过渡动画使元素逐渐消失时,元素并不会从DOM树中移除,因此它仍然存在页面上,尽管是完全透明的。如果目标是在动画结束后让元素完全从页面上消失,可以采用以下几种方法:
方法一:更改display
属性
在动画完成后,你可以使用JavaScript来改变元素的display
属性,将其设置为none
,这样元素就会从页面布局中移除,不再占用空间。
<div id="myElement">Hello World</div>
#myElement {
opacity: 1;
transition: opacity 2s ease-in-out;
}
document.getElementById('myElement').addEventListener('transitionend', function(event) {
if (event.propertyName === 'opacity' && this.style.opacity === '0') {
this.style.display = 'none';
}
});
方法二:使用CSS的关键帧动画(动画非过渡情况)
你可以使用CSS的@keyframes
规则来创建一个动画,当动画结束时,改变display
属性为none
。
@keyframes fadeOut {
from { opacity: 1; }
to { opacity: 0; display: none; }
}
#myElement {
animation: fadeOut 2s ease-in-out forwards;
}
但是,需要注意的是在to
关键字后面设置display: none;
可能不会在所有浏览器中工作,因为display
不是一个可动画的属性。对于这种情况,通常需要使用JavaScript来保证跨浏览器的兼容性。
方法三:结合使用visibility
和display
另一种方法是先使用visibility
属性来隐藏元素,然后在动画结束后使用display
属性来彻底移除元素
#myElement {
visibility: visible;
opacity: 1;
transition: opacity 2s ease-in-out, visibility 0s 2s;
}
document.getElementById('myElement').addEventListener('transitionend', function(event) {
if (event.propertyName === 'opacity') {
this.style.visibility = 'hidden';
setTimeout(function() {
this.style.display = 'none';
}.bind(this), 0);
}
});
在这个例子中,我们使用transition
属性同时对opacity
和visibility
进行过渡,但visibility
的过渡被延迟了,直到opacity
过渡完成后再将visibility
设置为hidden
,接着再使用setTimeout
确保在下一帧开始前将display
设置为none
。
请注意,以上代码中的JavaScript需要在元素的过渡动画触发之后运行,比如在鼠标离开元素或者任何其他交互事件后。
附件:方式一的演示代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.container {
}
.span {
color: blue;
position: relative;
}
.code {
width: 40px;
height: 40px;
background-color: red;
opacity: 0;
position: absolute;
right: -40px;
top: 0;
transition: opacity 1s ease;
}
.span:hover .code {
opacity: 1;
display: block;
}
</style>
</head>
<body>
<div class="container">
产品对接了二维码,<span class="span">显示<div class="code" id="myElement"></div></span>。
</div>
<script>
document.getElementById('myElement').addEventListener('transitionend', function (event) {
if (event.propertyName === 'opacity' && getComputedStyle(this).opacity === '0') {
this.style.display = 'none';
}
});
document.getElementById('myElement').addEventListener('transitionstart', function (event) {});
document.querySelector('.span').addEventListener('mouseenter', event => {
document.getElementById('myElement').style.display = 'block'
})
</script>
</body>
</html>