如何适应HTML父元素's的边界框转换为CSS转换的子对象

How to fit HTML parent element's bounding box to a CSS transformed child?

本文关键字:转换 边界 CSS 对象 HTML 何适应 元素      更新时间:2023-09-26

有没有一种方法,最好不使用JS,使以下代码片段中的容器包装缩放的、更通用的、转换的子元素,即实心红色外部边界完全包含蓝色虚线边界?

顺便说一句,这似乎是一个浏览器错误,因为它违反了默认的框模型行为,即父对象的大小会自动调整以适合子对象。

#container {
  border: 1px solid red;
}
#scaled {
  border: 1px dashed blue;
  transform: scale(3, 3);
  transform-origin: 0 0;
}
<div id="container">
  container
  <div id="scaled">
    scaled 3x
  </div>
</div>

如果不使用JavaScript,就无法做到这一点,但它也不是浏览器错误。CSS转换发生在图形管道中,在计算页面流并确定每个未转换元素的位置和大小之后。

这意味着CSS转换不会导致任何其他元素的大小被重新计算,这就是为什么容器的大小不会被调整为包含转换后的子元素。这实际上是transform的一个功能,旨在通过完全避免布局重新计算来提高性能。

唯一可以干净地做到这一点的方法是将转换应用于父元素,这似乎是您试图摆脱的。如果您希望它是动态的,并且希望远离JS,那么不幸的是没有其他方法。

#container {
  border: 1px solid red;
  transform: scale(3, 3);
  transform-origin: 0 0;
}
#scaled {
  border: 1px dashed blue;
  
}
<div id="container">
  container
  <div id="scaled">
    scaled 3x
  </div>
</div>

由于Maximilian Laumeister的答案给出的原因,在没有变换的情况下,同样明显给出的结果可能是:

#container {
  border: 1px solid red;
}
#scaled {
  border: 3px dashed blue;
  font-size:3em;
}
<div id="container">
  container
  <div id="scaled">
    scaled 3x
  </div>
</div>

但出于某种原因,这似乎并不能解决问题,所以让我们利用转换功能添加一点javascript来修复高度:

//JavaScript
var scale = 3;
var scaled = document.getElementById("scaled");
var container = document.getElementById("container");
container.style.height = //set the height of the container to
  container.clientHeight + //the old container height including the unscaled div
  (scale-1)*scaled.clientHeight + //add to that 2 more of the unscaled div
  (scale+scale/2|0) + //a kind of magic buffer to acount for border |0 converts to int
  "px";// make it css readable in pixls
/*CSS*/
#container {
  border: 1px solid red;
  /*height: 86px; tweakable magic number if not using JavaScript*/
}
#scaled {
  border: 1px dashed blue;
  transform: scale(3,3);
  transform-origin: 0 0;
  width: 33%
}
<div id="container">
 container
  <div id="scaled">
    scaled 3x
  </div>
</div>
<script>
  //insert JavaScript here
</script>

正如我在代码中指出的,您可以通过更改css中的高度来手动完成此操作,但如果您愿意使用JavaScript,则此解决方案应该是有效的,不需要每次添加内容都进行更改。

其他答案已经解释了为什么这需要JS。这里有一个方法来隐藏变换后剩余的"额外"空间。

  • 假设您希望缩放50%
  • 你应该在你的物品上设置transform: scale(.5); transform-origin: 0 0
  • 如果您知道正在调整大小的项目的原始大小,则可以通过将宽度和高度乘以比例因子来计算其新尺寸
  • 在父div上设置这些新维度,以便页面上的所有其他内容都可以围绕它流动

如果您不知道元素的大小,您可以使用ResizeObserver来查找它(它将是未缩放的大小),然后将缩放因子乘以宽度/高度,并在父包装div上设置这些新值。