admin管理员组

文章数量:1264860

Is there a way, preferably without using JS, to make the container in following code snippet to wrap the scaled, and more generically, transformed child element, i.e. solid red outer border fully contains dashed blue border?

BTW, this appears to be a browser bug as it violates the default box model behavior that parent's size is auto adjusted to fit children.

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

Is there a way, preferably without using JS, to make the container in following code snippet to wrap the scaled, and more generically, transformed child element, i.e. solid red outer border fully contains dashed blue border?

BTW, this appears to be a browser bug as it violates the default box model behavior that parent's size is auto adjusted to fit children.

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

Share Improve this question edited Feb 13, 2018 at 17:41 abbr asked Dec 26, 2015 at 20:08 abbrabbr 5,5716 gold badges31 silver badges51 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 12

There is no way to do this without using JavaScript, but it is also not a browser bug. CSS transforms happen in the graphics pipeline, after the page flow is calculated and every non-transformed element's position and size are determined.

This means that CSS transforms do not cause the size of any other element to be recalculated, and that is why the container is not being resized to contain the transformed child element. This is actually a feature of transform meant to improve performance by avoiding layout recalculation entirely.

The only way you can do this cleanly is to apply the transform to the parent element, which it seems like you're trying to get away from. If you want it to be dynamic, and you want to stay away from JS, there is unfortunately no other way.

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

The same visibly given result without transform for the reasons given by Maximillian Laumeister's Answer would possibly be:

#container {
  border: 1px solid red;
}

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

But this does not seem to solve the problem for some reason so lets play around with the transform feature add a little javascript to fix the height:

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

As I pointed out in the code you can do this manually by changing the height in the css but if you are willing to work with JavaScript this solution should be valid and shouldn't need changing every time you add something.

Other answers have already explained why this requires JS. Here's a method to hide the 'extra' space left over after a transform.

  • Lets say you want 50% scaling
  • You'd set transform: scale(.5); transform-origin: 0 0 on your item.
  • If you know the original size of the item being resized you can calculate its new dimensions by multiplying the width and height by the scaling factor.
  • Set those new dimensions on a parent div so that everything else on the page can flow around it.

If you don't know the size of the element you can use ResizeObserver to find it (it will be the unscaled size), then multiply the scaling factor by the width/height and set those new values on a parent wrapper div.

本文标签: javascriptHow to fit HTML parent element39s bounding box to a CSS transformed childStack Overflow