css - transition用法 - transition width




显示屏上的过渡:属性 (19)

我目前正在设计一种CSS'mega dropdown'菜单 - 基本上是一个普通的CSS下拉式菜单,但是它包含不同类型的内容。

目前, 看起来CSS3转换不适用于'display'属性 ,也就是说你不能做任何从display: nonedisplay: block (或任何组合)的转换。

任何人都可以为上面的例子中的第二层菜单设想一种方式,当有人悬停在顶层菜单项之一上时“淡入”?

我知道你可以在visibility:属性上使用转换,但我想不出有效利用它的方法。

我也尝试过使用高度,但只是失败了。

我也意识到使用JavaScript来实现这一点很简单,但我想挑战自己只使用CSS,而且我认为我的想法有点短了。

所有和任何建议最受欢迎。



I started an open source skeleton project called Toggle Display Animate

https://marcnewton.github.io/Toggle-Display-Animate/

This skeleton helper will allow you to easily mimic jQuery show/hide but with in/out CSS3 transition animations.

It uses class toggles so you can use any css methods you want on elements besides display:none|block|table|inline etc as well as other alternate uses that can be thought up.

Its main design purpose is for element toggle states, it supports a revert state where hiding the object allows you to run your keyframe in reverse or play an alternate animation for hiding the element.

Most of the markup for the concept I am working on is CSS, there is very little javascript actually used.

There is a demo here: http://marcnewton.co.uk/projects/toggle-display-animate/


There is a alternate solution with css animation for drop-down hidden:

.dropdown{   
  position: relative;
  width: 100%;
 -webkit-animation-name: animatetop;
 -webkit-animation-duration: 0.4s;
 animation-name: animatetop;
 animation-duration: 0.4s
}
/* Add Animation */
@-webkit-keyframes animatetop {
 from {top:-300px; opacity:0} 
 to {top:0; opacity:1}
}

@keyframes animatetop {
 from {top:-300px; opacity:0}
 to {top:0; opacity:1}
}

You can get this to work the natural way you expected - using display - but you have to throttle the browser to get it to work, using either JS or as others have suggested a fancy trick with one tag inside another. I don't care for the inner tag as it further complicates CSS and dimensions, so here's the JS solution:

https://jsfiddle.net/b9chris/hweyecu4/1/

Starting with a box like:

<div class="box hidden">Lorem</div>

A hidden box. You can have it transition on click with:

function toggleTransition() {
  var el = $("div.box1");

  if (el.length) {
    el[0].className = "box";
    el.stop().css({maxWidth: 10000}).animate({maxWidth: 10001}, 2000, function() {    
        el[0].className = "box hidden";
    });
  } else {
    el = $("div.box");
    el[0].className = "box";
    el.stop().css({maxWidth: 10001}).animate({maxWidth: 10000}, 50, function() {    
        el[0].className = "box box1";
    });
  }

  return el;
}

someTag.click(toggleTransition);

The CSS is what you'd guess:

.hidden {
  display: none;
}
.box {
    width: 100px;
    height: 100px;
    background-color: blue;
    color: yellow;
    font-size: 18px;
    left: 20px;
    top: 20px;
    position: absolute;
    -webkit-transform-origin: 0 50%;
    transform-origin: 0 50%;
    -webkit-transform: scale(.2);
    transform: scale(.2);
  -webkit-transition: transform 2s;
  transition: transform 2s;
}
.box1{
    -webkit-transform: scale(1);
    transform: scale(1);
}

The key is throttling the display property. By removing the hidden class then waiting 50ms, then starting the transition via the added class, we get it to appear and then expand like we wanted, instead of it just blipping onto the screen without any animation. Similar occurs going the other way, except we wait till the animation is over before applying hidden.

Note: I'm abusing .animate(maxWidth) here to avoid setTimeout race conditions. setTimeout is quick to introduce hidden bugs when you or someone else picks up code unaware of it. .animate() can easily be killed with .stop() . I'm just using it to put a 50ms or 2000ms delay on the standard fx queue where it's easy to find/resolve by other coders building on top of this.


不需要JavaScript,也不需要极其巨大的最大高度。 相反,请在文本元素上设置最大高度,并使用诸如rem或em之类的字体相对单位。 这样,您可以将最大高度设置为大于您的容器,同时避免延迟或菜单关闭时的“弹出”:

HTML

<nav>
  <input type="checkbox" />
  <ul>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
    <li>Link 1</li>
  </ul>
</nav>

CSS

nav input + ul li { // notice I set max-height on li, not ul
   max-height: 0;
}

nav input:checked + ul li {
   max-height: 3rem; // a little bigger to allow for text-wrapping - but not outrageous
}

在这里看到一个例子: http://codepen.io/mindfullsilence/pen/DtzjE : http://codepen.io/mindfullsilence/pen/DtzjE


今天我遇到了一个问题position: fixed模式,我正在重复使用。 我无法保持它的display: none ,然后动画,因为它刚刚出现,并且z-index (负值等)也做了奇怪的事情。

我也在使用height: 0height: 100% ,但它只在模态出现时才起作用。 这与使用left: -100%相同left: -100%或其他。

然后它让我感到有一个简单的答案。 Et瞧:

首先,你的隐藏模式。 注意height0 ,并检查转换中的height声明......它有一个500ms比我的opacity过渡更长 。 记住,这会影响淡出过渡:将模态返回到默认状态。

#modal-overlay {
    background: #999;
    background: rgba(33,33,33,.2);
    display: block;
    overflow: hidden;
    height: 0;
    width: 100%;
    position: fixed;
    top: 0;
    left: 0;
    opacity: 0;
    z-index: 1;
    -webkit-transition: height 0s 500ms, opacity 300ms ease-in-out;
       -moz-transition: height 0s 500ms, opacity 300ms ease-in-out;
            -ms-transition: height 0s 500ms, opacity 300ms ease-in-out;
         -o-transition: height 0s 500ms, opacity 300ms ease-in-out;
        transition: height 0s 500ms, opacity 300ms ease-in-out;
}

其次,你的可见模态。 假设你正在为body设置一种.modal-active 。 现在height100% ,我的转变也发生了变化。 我希望立刻改变heightopacity需要300ms

.modal-active #modal-overlay {
    height: 100%;
    opacity: 1;
    z-index: 90000;
    -webkit-transition: height 0s, opacity 300ms ease-in-out;
       -moz-transition: height 0s, opacity 300ms ease-in-out;
        -ms-transition: height 0s, opacity 300ms ease-in-out;
         -o-transition: height 0s, opacity 300ms ease-in-out;
            transition: height 0s, opacity 300ms ease-in-out;
}

就是这样,它就像一个魅力。


你可以用转换事件来做到这一点,所以你为转换创建了2个css类,其中一个持有动画,保持显示无状态。 并在动画结束后切换它们? 在我的情况下,我可以再次显示div,如果我按btn,并删除这两个类。

尝试下面的剪辑...

$(document).ready(function() {
  //assign transition event
  $("table").on("animationend webkitAnimationEnd", ".visibility_switch_off", function(event) {
    //we check if this is the same animation we want  
    if (event.originalEvent.animationName == "col_hide_anim") {
      //after the animation we assign this new class that basically hides the elements.    
      $(this).addClass("animation-helper-display-none");
    }

  });

  $("button").click(function(event) {

    $("table tr .hide-col").toggleClass(function() {
      //we switch the animation class in a toggle fashion...
      //and we know in that after the animation end, there is will the animation-helper-display-none extra class, that we nee to remove, when we want to show the elements again, depending on the toggle state, so we create a relation between them.
      if ($(this).is(".animation-helper-display-none")) {
        //im toggleing and there is already the above classe, then what we want it to show the elements , so we remove both classes...        
        return "visibility_switch_off animation-helper-display-none";
      } else {
        //here we just want to hide the elements, so we just add the animation class, the other will be added later be the animationend event...        
        return "visibility_switch_off";
      }

    });

  });

});
table th {
  background-color: grey;
}

table td {
  background-color: white;
  padding:5px;
}

.animation-helper-display-none {
  display: none;
}

table tr .visibility_switch_off {
  animation-fill-mode: forwards;
  animation-name: col_hide_anim;
  animation-duration: 1s;
}

@-webkit-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-moz-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@-o-keyframes col_hide_anim {
  0% {opacity: 1;}
  100% {opacity: 0;}
}

@keyframes col_hide_anim {
  0%   {opacity: 1;}
  100% {opacity: 0;}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
  <theader>
    <tr>
      <th>Name</th>
      <th class='hide-col'>Age</th>
      <th>Country</th>
    </tr>
  </theader>
  <tbody>
    <tr>
      <td>Name</td>
      <td class='hide-col'>Age</td>
      <td>Country</td>
    </tr>
  </tbody>
</table>

<button>Switch - Hide Age column with fadeout animation and display none after</button>


在吉列尔莫接受的答案写成后,2012年4月3日的CSS过渡规范改变了可视化过渡的行为, 现在可以在不使用过渡延迟的情况下以更短的方式解决这个问题

.myclass > div { 
                   transition:visibility 1s, opacity 1s; 
                   visibility:hidden;  opacity:0
               }
.myclass:hover > div 
               {   visibility:visible; opacity:1 }

为两个转换指定的运行时间通常应该是相同的(尽管稍长的可视时间不是问题)。 有关正在运行的版本,请参阅我的博客http://www.taccgl.org/blog/css-transition-visibility.html#visibility-opacity

关于“显示器上的转换:属性”以及对于来自Rui Marques和josh的评论的回答,可接受的答案是这样的:此解决方案适用于与使用显示或可见性属性无关的情况 (因为它很可能在这个问题中就是这种情况)。 它不会完全删除元素作为display:none,只是使其不可见,但仍保留在文档流中并影响以下元素的位置。 完全删除类似于display的元素的转换:none可以使用height(如其他答案和注释所示),max-height或margin-top / bottom来完成,但也可以参阅如何转换height:0; 到高度:auto; 使用CSS? 和我的博客http://www.taccgl.org/blog/css_transition_display.html

作为对GeorgeMillo的评论的回应:需要两个属性和两个转换:不透明属性用于创建淡入淡出动画和可见性属性,以避免元素仍然对鼠标事件作出反应。 对于视觉效果的不透明度和延迟隐藏的可见度需要转换,直到淡出完成。


您可以将元素“屏幕外”存储到您需要的位置,而不是使用显示器,然后将其位置设置到您想要的位置并同时进行转换。 这引起了很多其他设计问题,所以ymmv。 您可能不想使用显示器,因为您希望屏幕阅读器可以访问内容,而屏幕阅读器大部分都试图遵守可见性规则 - 即,如果它不应该是可见的,它不会显示为代理的内容。


您可以简单地使用CSS 可见性 :hidden / visible而不是display :none / block

div {
    visibility:hidden;
    -webkit-transition: opacity 1s ease-out;
    -moz-transition: opacity 1s ease-out;
    -o-transition: opacity 1s ease-out;
    transition: opacity 1s ease-out;
    opacity: 0; 
}

parent:hover > div {
    opacity: 1;
    visibility: visible;
}

您需要通过其他方式隐藏该元素才能使其发挥作用。

我通过绝对定位两个<div>并将隐藏的一个设置为opacity: 0来实现效果opacity: 0

如果您甚至将display属性从none切换为block ,则不会发生其他元素的转换。

要解决此问题,请始终允许元素display: block ,但通过调整以下任何方法来隐藏该元素:

  1. height设置为0
  2. opacity设置为0
  3. 将元素放置在另一个overflow: hidden元素的框架之外overflow: hidden

可能有更多的解决方案,但是如果您将元素切换为display: none无法执行转换。 例如,你可能试图尝试这样的事情:

div {
    display: none;
    transition: opacity 1s ease-out;
    opacity: 0; 
}
div.active {
    opacity: 1;
    display: block;
}

但那不行。 根据我的经验,我发现这无所作为。

正因为如此,你总是需要保持元素display: block - 但你可以通过做这样的事情来解决它:

div {
    transition: opacity 1s ease-out;
    opacity: 0; 
    height: 0;
    overflow: hidden;
}
div.active {
    opacity: 1;
    height: auto;
}

我怀疑任何刚刚启动CSS转换的人都会发现,如果您同时修改display属性(block / none),他们将无法正常工作。 尚未提及的一种解决方法是,您可以继续使用display:block / none来隐藏/显示元素,但将其不透明度设置为0,以便即使在display:block中仍然不可见。 然后将其淡入,添加另一个CSS类,如“on”,将不透明度设置为1并为不透明度定义过渡。 正如您可能已经想象的那样,您必须使用JavaScript将“on”类添加到元素,但至少您仍然在使用CSS来进行实际的转换。

PS如果您发现自己处于需要同时显示:block和添加“on”类的情况,则同时使用setTimeout推迟后者。 否则,浏览器只会同时看到两件事情,并禁用转换。


我整洁的JavaScript技巧是将整个场景分成两个不同的功能

为了准备事情,声明了一个全局变量并定义了一个事件处理程序:

  var tTimeout;
  element.addEventListener("transitionend", afterTransition, true);//firefox
  element.addEventListener("webkitTransitionEnd", afterTransition, true);//chrome

然后,当隐藏元素时,我使用这样的东西:

function hide(){
  element.style.opacity = 0;
}

function afterTransition(){
  element.style.display = 'none';
}

为了再现这个元素,我正在做这样的事情:

function show(){
  element.style.display = 'block';
  tTimeout = setTimeout(timeoutShow, 100);
}

function timeoutShow(){
  element.style.opacity = 1;
}

它的工作,迄今为止!


我知道这是一个非常古老的问题,但对于正在查看此线程的人员,您现在可以向块属性添加自定义动画。

@keyframes showNav {
  from {opacity: 0;}
  to {opacity: 1;}
}
.subnav-is-opened .main-nav__secondary-nav {
  display: block;
  animation: showNav 250ms ease-in-out both;
}

Demo

在这个演示中,子菜单从display:none更改为display:block并且仍然设置为淡入淡出。


我觉得回答这个问题的答案很差,但这个解决方案具有出色的兼容性,我还没有看到它:

.hidden-element {
  position: absolute;
  z-index: -1;
  pointer-events: none;
  visibility: hidden;
  opacity: 0;
  transition: visibility 0s, opacity .5s ease-out;
}

.hidden-element.visible {
  position: static;
  z-index: auto;
  pointer-events: auto;
  visibility: visible;
  opacity: 1;
}

说明 :它使用visibility: hidden技巧(与一步中的“显示和动画”兼容),但使用组合position: absolute; z-index: -1; pointer-events: none; position: absolute; z-index: -1; pointer-events: none; 以确保隐藏的容器不占用空间并且不回答用户交互


我认为SalmanPK有最接近的答案,它使用以下CSS动画淡入或淡出项目。 但是,显示属性不能平滑地进行动画制作,只有不透明度。

@-webkit-keyframes fadeIn {
    from { opacity: 0; }
      to { opacity: 1; }
}

@-webkit-keyframes fadeOut {
    from { opacity: 1; }
      to { opacity: 0; }
}

如果要将从显示模块移动的元素设置为无显示,我不能看到它现在只能使用CSS,您必须获取高度并使用CSS动画降低高度。 如下例所示,这可以通过CSS实现,但要知道需要为元素设置动画效果的确切高度值将非常困难。

jsFiddle 例子

CSS

@-webkit-keyframes pushDown {
  0% {
    height: 10em;
  }
  25% {
    height: 7.5em;
  }
  50% {
    height: 5em;
  }
  75% {
    height: 2.5em;
  }
  100% {
    height: 0em;
  }
}

.push-down {
    -webkit-animation: pushDown 2s forwards linear;
}

JavaScript的

var element = document.getElementById("element");

// push item down
element.className = element.className + " push-down";

更改overflow:hidden overflow:visible 。 它效果更好。 我使用这样的:

#menu ul li ul {
    background-color:#fe1c1c;
    width:85px;
    height:0px;
    opacity:0;
    box-shadow:1px 3px 10px #000000;
    border-radius:3px;
    z-index:1;
    -webkit-transition:all 0.5s ease;
    -moz-transition:all 0.6s ease;
}

#menu ul li:hover ul  {
    overflow:visible;
    opacity:1;
    height:140px;
}

visible是更好的,因为overflow:hidden行为完全像一个display:none


根据W3C 2013年11月19日工作草案, display不是一个可动画的属性 。 幸运的是, visibility是可以动画的。 您可以通过不透明度转换( JSFiddle )来链接它的转换:

  • HTML:

    <a href="http://example.com" id="foo">Foo</a>
    <button id="hide-button">Hide</button>
    <button id="show-button">Show</button>
    
  • CSS:

    #foo {
        transition-property: visibility, opacity;
        transition-duration: 0s, 1s;
    }
    
    #foo.hidden {
        opacity: 0;
        visibility: hidden;
        transition-property: opacity, visibility;
        transition-duration: 1s, 0s;
        transition-delay: 0s, 1s;
    }
    
  • 用于测试的JavaScript:

    var foo = document.getElementById('foo');
    
    document.getElementById('hide-button').onclick = function () {
        foo.className = 'hidden';
    };
    
    document.getElementById('show-button').onclick = function () {
        foo.className = '';
    };
    

请注意,如果您只是将链接设置为透明,而未设置visibility: hidden ,则可以保持可点击。


这个问题最简单的通用解决方案是:随意在CSS中指定display:none ,但是您将使用JavaScript将其更改为block (或其他任何内容),然后您还必须为您的元素添加一个类这个问题实际上是通过setTimeout()进行的 。 就这样。

即:

<style>
#el {
    display: none;
    opacity: 0;
}
#el.auto-fade-in {
    opacity: 1;
    transition: all 1s ease-out; /* future, future, please come sooner! */
    -webkit-transition: all 1s ease-out;
    -moz-transition: all 1s ease-out;
    -o-transition: all 1s ease-out;
}
</style>

<div id=el>Well, well, well</div>

<script>
var el = document.getElementById('el');
el.style.display = 'block';
setTimeout(function () { el.className = 'auto-fade-in' }, 0);
</script>

在最新的理智浏览器中进行测试。 显然不应该在IE9或更早版本中工作。





css-transitions