如何使HTML父元素的边界框适应CSS转换后的子元素?

7

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

顺便说一句,这似乎是一个浏览器bug,因为它违反了默认盒模型行为,即父元素的大小会自动调整以适应子元素。

#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>

3个回答

11

这个问题必须使用 JavaScript 来解决,但它并不是浏览器的 bug。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>


谢谢。我不想缩放父级元素。你知道有哪些流行的JS库可以解决这个问题吗? - abbr
很遗憾,我不知道有一个库可以完全做到这一点,但如果您可以接受子元素只有3倍的宽度和高度而不是被缩放,那么您始终可以通过获取JS innerWidthinnerHeight来获得其默认的宽度和高度,然后使用JS将元素的CSS widthheight设置为恰好是那些尺寸的3倍。 - Maximillian Laumeister
我所工作的应用程序大量使用CSS变换,不仅仅是缩放,因此这个选项对我来说不可行。如果仅靠CSS无法解决,我会考虑使用JS解决方案。 - abbr

1

如果不使用转换,由于Maximillian 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,这个解决方案应该是有效的,而且不需要每次添加内容都进行更改。

比例尺不仅适用于字体,这正是我所需要的。就像在浏览器中,放大镜不仅仅放大文本。 - abbr

0

其他答案已经解释了为什么需要使用JS。以下是一种隐藏变换后留下的“额外”空间的方法。

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

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接