您现在的位置: 365建站网 > 365学习 > css3 动画与display:none冲突的解决方法

css3 动画与display:none冲突的解决方法

文章来源:365jz.com     点击数:320    更新时间:2021-07-24 17:06   参与评论

CSS不能在display:none和display:block之间进行动画,并且也不能在height:0和height:auto之间进行动画。这里我研究了一下在display:none和display:block之间进行动画的解决方案,记录下来供以后开发时参考,相信对其他人也有用。

我的理解是这样的:由于display:none会引起页面的重绘事件,所以它是一个异步的延时事件,所以浏览器其实会先解析animate的代码,然后再执行display:none。

这样就引发了一个问题:如果我们要设置类似淡入淡出的效果怎么办?就是让元素在消失/出现的同时产生动画怎么办?这里我研究了2个解决方案。

利用绝对定位和visiblity

不利用display:none,而是利用它的替代方式:

opacity: 0;visibility: hidden;

但是这样会占据空间。如果不想占据空间的话,只能使用绝对定位,把元素独立出去。这个时候会有一个层叠问题,所以需要搭配z-index控制层叠关系使它出现或者消失。

示例如下:

//自身css效果
.animate {
    position: absolute;
    top: 0;
    left: 0;

    transition: 1s;
    opacity: 0;
    visibility: hidden;
    z-index: 0;
}

//出现时的效果
.cur {
    opacity: 1;
    visibility: visible;
    z-index: 10;
}

利用timeout

jQuery里面也有淡入淡出的方法,它是怎么实现的呢?通过查资料可以知道,它是通过deferred对象通过延时display: none来实现的。好处是能够适用于出现时占据空间,消失时又不占据空间的情况。实例如下:

//css
.div {
    display: none;
}
.div-animate1 {
    display: block;
    visibility: hidden;
    opacity: 0;
    transform: translate3d(100px, 0, 0);
    transition: 1s;
}
.div-animate2 {
    visibility: visible;
    opacity: 1;
    transform: translate3d(0, 0, 0);
}

//js
function divAnimate1($div, divClass1, divClass2) {
    $div.addClass(divClass1);

    setTimeout(function(){
        $div.addClass(divClass2);
    });
}
function divAnimate2($div, divClass1, divClass2) {
    $div.removeClass(divClass2);

    setTimeout(function(){
        $div.removeClass(divClass1);
    }, 1000); //1s是动画时间。
}

其它

我还试过用transitionend事件,window.requestanimationframe来实现,但是都或多或少的有副作用。

另外总结一下:

  1. 如果消失前后都需要占据空间,则用visiblity。

  2. 如果消失前后都不需要占据空间,则用绝对定位和visiblity。

  3. 如果消失前需要占据空间但是消失后不需要占据空间,则用timeout和visiblity。


DISPLAY:NONE的元素如何触发过渡动画?

display:none的元素更改为display:block为何不可以和其他属性修改一样触发动画呢?

这是因为display属性刚开始是none,所以还没有创建,改为block之后需要等待js渲染队列更新

但是transition属性在一开始就有了,所以transform改变元素的时候并没有触发动画

解决方法:让元素获取dom.offsetHeight,触发js渲染队列更新,让元素先展示出来。

<!DOCTYPE HTML>
<html>
<head>
  <title>测试</title>
  <style type="text/css">
  html, body, div, span,
  h1, h2, h3, h4, h5, h6, p
  a, img, ol, ul, li
  {
      margin:0;padding:0;border:0;outline:0;
  }
  ul, li{
  list-style-type: none;
  }
  .father{
  border: 1px solid black;
  height: 300px;
  width: 1000px;
  }
  .one{
  background-color: red;
  height: 300px;
  width: 200px;
  display: none;
  transition: 1s ease;
  }
   </style>
</head>
<body>
<div class="father">
<div class="one"></div>
<button type="button" onclick="change()">测试</button>
</div>
<script>
function change(){
var one = document.getElementsByClassName('one')[0];
one.style.display='block';
// 区别在于有没有获取one.offsetHeight
console.log(one.offsetHeight);
one.style.transform='translateX(200px)';
}
</script>
</body>
</html>

用opacity实现淡入淡出的效果。噢!good!一切正常


<!DOCTYPE html>
<html>
<meta charset="uft-8">
<head>
<style>
.div1{
     background: red;
}
.div2 {
     width:100px;
     height:100px;
     background:blue;
     transition:opacity 2s;
     -moz-transition:opacity 2s; /* Firefox 4 */
     -webkit-transition:opacity 2s; /* Safari and Chrome */
     -o-transition:opacity 2s; /* Opera */
     opacity: 0;
}
.div1:hover .div2 {
     opacity:1;
}
</style>
</head>
<body>
     <div class="div1">
     <p>请移动到红色div上</p>
     <div class="div2"></div>
</div>
</body>
</html>


或者用animation,在keyframe中写也一样。这里就不写出代码了
但是难免我们会遇到这样的需求,也一定会遇到: 我们都知道opacity:0的时候,其实他还是占页面空间的,他会遮挡到他下面的层(不是视觉上)。而且绑定在他上面的一些onclick事件之类的,也同样会发生。 这时候我们想在opacity:0的时候,把他隐藏掉,用display: none。 好,那我们稍微在css中加几句,变成

.div1{
     background: red;
}
.div2 {
     width:100px;
     height:100px;
     background:blue;
     transition:opacity 2s;
     -moz-transition:opacity 2s; /* Firefox 4 */
     -webkit-transition:opacity 2s; /* Safari and Chrome */
     -o-transition:opacity 2s; /* Opera */
     opacity: 0;
     display: none;
}
.div1:hover .div2 {
     opacity:1;
     display:block
}

打开浏览器看一下效果先。 我擦。。。。淡入淡出的效果全没了怎么回事。。。这简直是破坏性的作用,这也是之前做动画过程中遇到的大坑

聪明的码农们当然有办法来解决这种情况。 大家都知道visibility的效果其实跟 display 在一定程度上相似, 当然是一定程度上。 那为什么说只是一定程度上相似呢,因为它仍然是占空间的,那么这时候看官一定会说,这么用跟opacity压根没区别呀

但聪明的码农们一定又想到,这时候,他是不会遮挡到下面的层的,也就是说 他跟opacity这样的存在不同,onclick等事件是不会发生的。

我们来说下visibility, 常用到的是visible和 hidden 两个值。但也可以是数值, 等于0时相当于hidden,而只要大于0时,visibility就为visible。那我们利用这点。

.div1{
     background: red;
}
.div2 {
     width:100px;
     height:100px;
     background:blue;
     transition:all 2s;
     -moz-transition:all 2s; /* Firefox 4 */
     -webkit-transition:all 2s; /* Safari and Chrome */
     -o-transition:all 2s; /* Opera */
     visibility: hidden
}
.div1:hover .div2 {
     visibility: visible
}


浏览一下,会发现,这时候是会有延时隐藏的效果的。很好,又发现新东西了


那渐变的效果怎么办。。。。


聪明的码农们又想起了opacity 。。。结合起来用会怎么用呢

.div1{
     background: red;
}
.div2 {
     width:100px;
     height:100px;
     background:blue;
     transition:all 2s;
     -moz-transition:all 2s; /* Firefox 4 */
     -webkit-transition:all 2s; /* Safari and Chrome */
     -o-transition:all 2s; /* Opera */
     visibility: hidden;
     opacity: 0
}
.div1:hover .div2 {
     visibility: visible;
     opacity: 1
}


浏览下先。。。。!!!!一切正常了


其实,visibility会在opacity生效后再应用。比如隐藏时,先opacity变为0,再应用了visibility:hidden 这时候就隐藏起来了,相关的事件也不会发生。 看来display:none这时候被抛弃了啊


当然,有人会说visibility:hidden始终是占着页面空间的,display能够减少页面的repaint,还是要用display:none怎么做呢


聪明的码农又想到了: 先把display变成block 然后延迟transition动画的执行


当然啦 这就需要用到JS了


以上就是CSS3 动画与display:none冲突的解决方法!



如对本文有疑问,请提交到交流论坛,广大热心网友会为你解答!! 点击进入论坛


发表评论 (320人查看0条评论)
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
用户名: 验证码: 点击我更换图片
最新评论
------分隔线----------------------------