如何使CSS转换影响其他元素的流

mzsu5hc0  于 2023-02-14  发布在  其他
关注(0)|答案(5)|浏览(201)

我使用带有transform属性的CSS过渡来在添加和删除元素时缩小元素。
然而,这样做的一个问题是,这个属性不影响其他元素的流动,因此看起来好像被删除的元素缩小了,然后其余的元素突然跳转。
如果我用height属性来做动画而不是使用一个transform,这将是很好的,但是在实际使用中,我使用的是可变高度的元素,所以我不知道我可以在什么高度之间做动画。

**编辑:**人们建议动画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>
ssgvzors

ssgvzors1#

对于布局由CSS框模型控制的元素,transform属性不影响转换后的元素周围的内容流。
REF:变换渲染
必须使用max-height属性(check this answer)才能获得所需的效果。

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);
});
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;
}
<button>
  Add Box
</button>
bqjvbblv

bqjvbblv2#

有没有办法做正确的(与css单独)
我做这件事的方法是部分使用JS(或者在我的例子中使用C #/Blazor)
我使用了max-height,但是我用var()设置了它,并且我根据我拥有的内容计算值本身(我使用JS/c #),然后使用该值通过css变量设置inlinestyle

<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中,但它非常容易理解

acruukt9

acruukt93#

你可以在缩小的盒子周围创建一个 Package 器。现在你只是缩放红色盒子,这意味着它仍然使用相同的空间,但它是以缩放的方式呈现的。当你最终删除它时,它不再使用那个空间,它下面的元素会向上跳。
如果你在每个红框周围创建一个 Package ,你就可以控制它所占的空间。只需要改变 Package 的高度,再加上一个过渡。

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

所以,不要只使用过渡来缩放红色框,还要将它们放在 Package 元素中,并更改该元素的高度。

xlpyo6sf

xlpyo6sf4#

为了获得最佳效果,您需要修改影响其周围的装箱属性。这包括宽度/高度、填充、边距和边框宽度。在下面的示例中,我将相关属性设置为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>
x3naxklr

x3naxklr5#

解决方法是将边距设置为负值。

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 {
  box-sizing: border-box;
  font-size: 20pt;
  margin: 10px;
  width: 200px;
  padding: 10px;
  background: pink;
  transform: scale(1, 1);
  transform-origin: top left;
  height: 2em;
}
.deleting {
  transform: scale(1, 0);
  margin-bottom: calc(-2em - 10px);
  transition: all 1000ms ease;
}
<button>
  Add Box
</button>

相关问题