当不同的媒体查询生效时,如何阻止动画响应导航菜单(由CSS3过渡提供动力)?

时间:2013-05-20 16:35:10

标签: css3 css-transitions

前言

我正在尝试使用导航菜单创建一个满足以下两个要求的响应式网站:

  1. 导航在普通浏览器窗口中完全可见,水平布局。
  2. 导航成为移动设备和小屏幕的可切换垂直菜单,在“打开”和“关闭”状态之间进行动画制作。
  3. 我希望移动设备上的性能良好 - 特别是在iOS上 - 这意味着动画应该使用GPU-accelerated translate3d transform CSS过渡。

    我的问题

    设置它是一块蛋糕,而且大多数情况下效果很好。我使用z-index: 1transform: translate3d(0,-100%,0)隐藏了标题后面的菜单,z-index: 2处于默认关闭状态,然后transform: translate3d(0,0,0)将菜单设置为打开状态。

    但我只是遇到一个问题:当我调整Chrome浏览器窗口的大小并启动​​移动媒体查询时,菜单会从打开状态设置为关闭状态。

    将浏览器窗口的大小调整为小于600px宽,以查看操作中的问题:

    我想我知道为什么会发生这种情况:当移动媒体查询启动时,浏览器会看到.nav当前未处于活动状态,因此会将其设置为默认关闭状态。我尝试使用display:nonedisplay:block来尝试不同的媒体查询状态,但这似乎完全破坏了动画。

    如何在调整浏览器窗口大小时阻止导航菜单的“关闭”动画被触发?

3 个答案:

答案 0 :(得分:9)

干得好,很干净。我可以偷了吗? : - )

无论如何,这是你的解决方案demo

我刚刚过渡到另一个班级:

.nav {
    /* stuff */
    z-index: 1;
    transform: translate3d(0,-100%,0);
    -webkit-transform: translate3d(0,-100%,0);
}
.nav.active {
    transform: translate3d(0,0,0);
    -webkit-transform: translate3d(0,0,0);
}
.nav.activated {
    transition: transform 400ms linear;
    -webkit-transition: -webkit-transform 400ms linear;
}

首先可以添加到元素“Toggle”:

function toggle(){
    $(".nav").addClass("activated").toggleClass("active");
}

P.S。如果您不希望在用户打开菜单后再进行转换,然后再次调整窗口大小,则可以使用Modernizr的mq method

$(window).on('resize',function(){
    if(Modernizr.mq('(min-width:600px)')) $(".nav").removeClass("activated");
});

答案 1 :(得分:2)

参考Giona提到的副作用:

  

P.S。如果您不想在用户打开菜单后再进行转换,然后再次调整窗口大小(...)

有一种更简洁的方法来解决这个问题,而不会触发每个resize事件。您可以在转换结束后删除要转换的类resposible(完整演示here):

$(function()
  {
    $(".nav").on("transitionend", function() {
        $(this).removeClass("activated");
    });
  }
)();

答案 2 :(得分:0)

通过结合GionaJanusz Kacalak(以及Justin Bull的评论)的答案,我们可以进一步优化代码,以使导航栏永远不会从打开状态变为关闭状态(不仅限于动画)。第一次,这就是Giona的代码)。

function toggle() {
  var navbar = $(".nav");
  if (navbar.hasClass("active")) {
    // Closing the nav bar.
    navbar.removeClass("active");
    // Listening for a transition.
    // Use `.one` here because we only want this to be called once.
    navbar.one(whichTransitionEvent(), function() {
      // Remove animation property after the nav bar is closed.
      navbar.removeClass("activated");
    });
  } else {
    // Opening the nav bar.
    navbar.addClass("activated").addClass("active");
  }
}

// Ref: https://davidwalsh.name/css-animation-callback
function whichTransitionEvent() {
  var t;
  var el = document.createElement('fakeelement');
  var transitions = {
    'transition': 'transitionend',
    'OTransition': 'oTransitionEnd',
    'MozTransition': 'transitionend',
    'WebkitTransition': 'webkitTransitionEnd'
  };

  for (t in transitions) {
    if (el.style[t] !== undefined) {
      return transitions[t];
    }
  }
}
body { margin: 0; }
.toggle { display: none; }
.nav { list-style-type: none; margin: 0; padding: 0; }
.nav li { float: left; margin: 0; padding: 20px; background: #fdd; }
.nav li:nth-child(2n) { background: #dfd; }

@media only screen and (max-width: 599px)
{
    .toggle {
        display: block;
        position: relative;
        z-index: 2;
        padding: 20px;
        background: #eee;
    }
    .nav li {
        display: block;
        float: none;
    }
    .nav {
        display: block;
        position: relative;
        z-index: 1;
        transform: translate3d(0,-100%,0);
		-webkit-transform: translate3d(0,-100%,0);
    }
    .nav.active {
        transform: translate3d(0,0,0);
		-webkit-transform: translate3d(0,0,0);
    }
    .nav.activated {
        transition: transform 400ms linear;
		-webkit-transition: -webkit-transform 400ms linear;
    }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<a href="#" class="toggle" onclick="javascript:toggle();return false;">Toggle menu</a>
<ul class="nav">
    <li>One</li>
    <li>Two</li>
    <li>Three</li>
    <li>Four</li>
    <li>Five</li>
</ul>