涉及展示属性时其他属性的硬转换

时间:2017-02-27 08:57:45

标签: javascript css css3 transition

我希望在容器内的两个不同大小的元素之间淡入淡出。第一个元素应该淡出,然后容器调整大小,最后另一个元素淡入。

以下是相关代码段:



var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");

function switchLayers() {
  layer1.addEventListener("transitionend", function() {
    layer2.classList.add("fadein");
  });
  layer1.classList.add("fadeout");
}

#container {
  position: relative;
  background-color: yellow;
  padding: 10px;
  overflow: hidden;
}

.layer {
  position: relative;
  width: 400px;
}

#layer1 {
  height: 100px;
  float: left;
  background-color: blue;
}

#layer2 {
  height: 150px;
  background-color: red;
  display: none;
  opacity: 0;
}

#layer1.fadeout {
  opacity: 0;
  transition: opacity 1s ease-out;
}

#layer2.fadein {
  display: block;
  opacity: 1;
  transition: opacity 1s ease-out;
}

<button onclick="switchLayers()">Switch layers</button>
<div id="container">
  <div id="layer1" class="layer"></div>
  <div id="layer2" class="layer"></div>
</div>
&#13;
&#13;
&#13;

当第二层的display属性设置为block时,它按预期工作,即不透明度在一秒内从0变为1。虽然如果它设置为none,转换突然变得离散。

我已尝试在all值中设置transition以转换所有属性,并尝试在转换中包含display属性,如下所示:

transition: display 0s, opacity 1s ease-out;

虽然没有成功。请注意,因为容器应调整为当前显示的图层的大小,所以不能使用visibility属性(因为它隐藏了元素但仍允许它占用空间)。

如何使这项工作?

2 个答案:

答案 0 :(得分:1)

尝试使用visibility属性而不是display

有关visibilitydisplay中状态更改的详细信息,请参阅article

要转换父height,您必须手动更改height的{​​{1}}属性。使用#container&amp; display: block永远不会转换父母。

参考代码:

display: none
var layer1 = document.getElementById("layer1");
var layer2 = document.getElementById("layer2");

function switchLayers() {
  layer1.addEventListener("transitionend", function() {
    layer2.classList.add("fadein");
    document.getElementById("container").style.height = "170px";
  });
  layer1.classList.add("fadeout");
}
#container {
  position: relative;
  background-color: yellow;
  padding: 10px;
  height: 100px;
  overflow: hidden;
  transition: all 0.5s;
}

.layer {
  position: relative;
  width: 400px;
}

#layer1 {
  height: 100px;
  float: left;
  background-color: blue;
}

#layer2 {
  height: 150px;
  background-color: red;
  visibility: none;
  opacity: 0;
}

#layer1.fadeout {
  visibility: none;
  opacity: 0;
  transition: all 1s ease-out;
}

#layer2.fadein {
  visibility: visible;
  opacity: 1;
  transition: all 1s ease-out;
}

答案 1 :(得分:1)

没有直截了当的方式。转换不适用于display,也不适用于自动height。所以,visibility是一个不错的选择。

  

请注意,因为容器应调整为大小   当前显示的图层,不能使用可见性属性(如   它隐藏了元素,但仍然让它占据了空间。)

然后,你需要破解它。您可以使用min-height。向您的min-height提供虚假 container,然后在转换结束后应用height layer2。此外,由于display上的layer2将阻止转换,因此您需要将displayopacity的类分开,并在其间使用零超时来隔离其应用程序。

这是一个粗略的想法:

&#13;
&#13;
var layer1 = document.getElementById("layer1"),
    layer2 = document.getElementById("layer2"),
    container = document.getElementById("container"),
    h = window.getComputedStyle(layer2).getPropertyValue("height");

container.addEventListener("transitionend", function(e) {
  if (e.target.id === 'layer1') {
    // apply layer2 height to container min-height
    container.style.minHeight = h; 
  }
  if (e.target.id === 'container') { 
    // First show the layer2
    layer2.classList.add("show"); 
    // Then a dummy pause to fadein
    setTimeout(function(){
      layer2.classList.add("fadein");
    }, 0);
  }
}, false);

function switchLayers() {
  layer1.classList.add("fadeout");
}
&#13;
#container {
  position: relative;
  background-color: yellow;
  padding: 10px; overflow: hidden;
  min-height: 1px; /* faux min-height */
  transition: min-height 1s linear;
}

.layer { position: relative; width: 400px; }

#layer1 {
  height: 100px; float: left;
  background-color: blue;
  transition: all 1s linear;
}

#layer2 {
  height: 150px; background-color: red;
  display: none; opacity: 0;
  transition: opacity 1s linear;
}

#layer1.fadeout { opacity: 0; }
#layer2.show { display: block; } /* Separate out display */
#layer2.fadein { opacity: 1; } /* Separate out opacity */
&#13;
<button onclick="switchLayers()">Switch layers</button>
<div id="container">
  <div id="layer1" class="layer"></div>
  <div id="layer2" class="layer"></div>
</div>
&#13;
&#13;
&#13;