如何进行CSS转换会影响其他元素的流动

时间:2016-08-27 18:34:23

标签: javascript css css3 css-transitions css-transforms

我正在使用带有transform属性的CSS过渡来在添加和删除元素时缩小元素。

然而,一个问题是这个属性不影响其他元素的流动,所以看起来被删除的元素会缩小,然后其余的元素会突然跳跃。

如果我要为高度属性设置动画而不是使用变换,那就没问题,但是在实际使用中我使用的是可变高度的元素,所以我不知道我可以在其间设置动画的高度。

修改:有人建议动画height属性(上述内容不起作用)或max-height属性。 max-height属性在某种程度上可以正常工作,但是您无法完美地对齐时序,因为转换将继续调整max-height属性超过元素的实际高度,直到转换时间结束。

这些方法的另一个问题是它不使用您可以使用transform属性实现的平滑动画。对象的变换将顺利进行,但是随着浏览器以不同方式呈现这些过渡,以下元素的移动将会断断续续。

这是一个JSFiddle我的意思(尝试添加然后删除元素,并在删除元素时查看跳转):

var button = document.querySelector("button");
var box = document.createElement("div");

box.className = "box";
box.appendChild(document.createTextNode("Click to delete"));

button.addEventListener("click", function(e) {
  var new_box = box.cloneNode(true);

  new_box.addEventListener("click", function(e) {
    this.className = "box deleting";
    window.setTimeout(function(e) {
      new_box.remove();
    }, 1000);
  });

  this.parentNode.appendChild(new_box);
});
button {
  font-size: 20pt;
}
.box {
  font-size: 20pt;
  margin: 10px;
  width: 200px;
  padding: 10px;
  background: pink;
  transform: scale(1, 1);
  transform-origin: top left;
}
.deleting {
  transform: scale(1, 0);
  transition: all 1000ms ease;
}
<button>
  Add Box
</button>

4 个答案:

答案 0 :(得分:2)

  

对于布局由CSS框模型控制的元素,   transform属性不会影响周围内容的流动   转化的元素。

参考:Transform Rendering

您必须使用max-height属性(check this answer)才能获得所需的效果。

&#13;
&#13;
var button = document.querySelector("button");
var box = document.createElement("div");

box.className = "box";
box.appendChild(document.createTextNode("Click to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to deleteClick to delete"));

button.addEventListener("click", function(e) {
  var new_box = box.cloneNode(true);
  new_box.style.height = ( Math.random() * (200 - 30) + 30 ) + 'px';

  new_box.addEventListener("click", function(e) {
    this.className = "box deleting";
    window.setTimeout(function(e) {
      new_box.remove();
    }, 1000);
  });

  this.parentNode.appendChild(new_box);
});
&#13;
button {
  font-size: 20pt;
}
.box {
  overflow:hidden;
  font-size: 12pt;
  margin-bottom: 10px;
  width: 600px;
  max-height:1000px;
  padding: 10px;
  background: pink;
  transform: scaleY(1);
  transform-origin: top left;
}
.deleting {
  transform: scaleY(0);
  max-height:0;
  padding:0 10px;
  margin-bottom:0;
  transition: padding 1000ms ease,max-height 1000ms ease, transform 500ms ease 500ms, margin-bottom 1000ms ease;
}
&#13;
<button>
  Add Box
</button>
&#13;
&#13;
&#13;

答案 1 :(得分:1)

没有办法做对(仅使用 css) ¬¬

我的做法是部分使用 JS(或 C#/Blazor 在我的情况下)

我使用了 max-height,但我用 var() 设置了它,并且我根据我拥有的内容计算了值本身(我为此使用了 JS/c#),然后使用该值设置带有 css 变量的 inline style

<ul 
    class="submenu @SubMenuActiveClass" 
    style="--max-height:@((int)(40.3f * Model.Children.Count))px">

    <!--... childrens with 40.3px height each -->

</ul>
.submenu {
    max-height: 0;
    transition: max-height 0.3s ease-out;
    overflow: hidden;

    &.active {
        max-height: var(--max-height);
    }
}

示例使用 Blazor 和 SCSS,但很容易理解

答案 2 :(得分:0)

你可以在收缩盒周围创建一个包装器。现在你只是缩放红色框,这意味着它仍然使用相同的空间,但它以缩放的方式呈现。当你最终删除它时,它不再使用该空间,它下面的元素将向上跳跃。

如果在每个红色框周围创建一个包装器,则可以控制它所占用的空间。 只需更改该包装器的高度,也可以进行转换。

/* css for a wrapper */
overflow: hidden;
transition: height .2s; /* your time */

所以,不要仅使用过渡来缩放红色框,而是将它们放在包裹元素中,并更改该元素的高度。

答案 3 :(得分:0)

为获得最佳效果,您需要修改影响周围环境的拳击属性。这包括宽度/高度,填充,边距和边框宽度。在下面的示例中,我将相关属性设置为0以获得所需效果。这包括影响元素垂直间距的所有属性:heightpadding-[top/bottom]margin-[top/bottom]border-[top/bottom]-width都已转换为0。

我还在框中添加了box-sizing: border-box;overflow: hidden; - 您应该看到未设置时会发生什么。我会让你自己了解这些。

var button = document.querySelector("button");
var box = document.createElement("div");

box.className = "box";
box.appendChild(document.createTextNode("Click to delete"));

button.addEventListener("click", function(e) {
  var new_box = box.cloneNode(true);

  new_box.addEventListener("click", function(e) {
    new_box.style.height = this.offsetHeight + 'px';
    window.requestAnimationFrame(function () {
      new_box.style.height = 0;
      new_box.className = "box deleting";
      window.setTimeout(function(e) {
        new_box.remove();
      }, 1000);
    });
  });

  this.parentNode.appendChild(new_box);
});
button {
  font-size: 20pt;
}
.box {
  box-sizing: border-box;
  overflow: hidden;
  font-size: 20pt;
  margin: 10px;
  width: 200px;
  padding: 10px;
  border: 5px solid red;
  background: pink;
  transform: scale(1, 1);
  transform-origin: top left;
}
.deleting {
  height: 0;
  padding-top: 0;
  padding-bottom: 0;
  margin-top: 0;
  margin-bottom: 0;
  border-top-width: 0;
  border-bottom-width: 0;
  transform: scale(1, 0);
  transition: all 1000ms ease;
}
<button>
  Add Box
</button>