19

I'm using css3 scale transform to scale a div that contains other divs inside.

The problem I have is that some of the inner divs I need to keep as they were, basically as if they were not scaled, their size should not change, however I do need to scale the parent div with everything else inside.

How can you reverse the scaling in some of the divs?
I am trying to apply an inverse scaling.
If the overall div had applied a value of 1.5 , I'm trying to find what value I should now scale the other divs to revert them visually to how they looked before.

Dave
  • 8,163
  • 11
  • 67
  • 103
Javier Gonzalez
  • 369
  • 1
  • 2
  • 9

4 Answers4

33

If the parent div has been scaled by a factor of 1.5, then you need to scale the children by a factor of 1/1.5 = 0.(6) to keep their size constant.

example

In general, in order to cancel for a child element a scale transform that has been applied on the parent and has a scale factor of a, you need to apply another scale transform of factor 1/a on the child itself.

You either need to:

  • compute manually the scale factor before you do anything else and then use it as it is in your code (example linked above)
  • use a preprocessor to handle this for you (SASS example)
  • use JavaScript to compute the scale factor needed for the child and to set the scale transform on the child
Community
  • 1
  • 1
Ana
  • 35,599
  • 6
  • 80
  • 131
5

You could use a CSS variable to store your scale factor, and then use calc() to calculate the inverse scale for the child elements that have a certain class:

.wrapper {
  transform: scale(var(--scale));
  background: #ddd;
}

.wrapper > * {
  text-align: center;
}

.wrapper > .revertscale {
  transform: scale(calc(1/var(--scale)));
}
<div class="wrapper" style="--scale: 0.8">
  <h2>scaled title</h2>
  <p>scaled description</p>
</div>

<div class="wrapper" style="--scale: 0.8">
  <h2 class="revertscale">not scaled title</h2>
  <p class="revertscale">not scaled description</p>
</div>

⋅ ⋅ ⋅

In case you don't want any of the child elements to scale, another way of doing it would be to style your wrapper as a pseudo element :

.wrapper {
  position: relative;
}

.wrapper > * {
  text-align: center;
}

.wrapper::before {
  content: "";
  z-index: -1;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  transform: scale(var(--scale));
  background: #ddd;
}
<div class="wrapper" style="--scale: 1">
  <h2>title</h2>
  <p>description</p>
</div>

<div class="wrapper" style="--scale: 1.2">
  <h2>title</h2>
  <p>description</p>
</div>

<div class="wrapper" style="--scale: 0.8">
  <h2>title</h2>
  <p>description</p>
</div>
Takit Isy
  • 9,688
  • 3
  • 23
  • 47
  • For information, I've posted here because someone linked this topic on this other one: https://stackoverflow.com/questions/53811765/scale-a-div-without-changing-the-size-and-position-of-its-child-elements/53811936#53811936 – Takit Isy Dec 17 '18 at 09:50
1

The inverse of any scale operation is 1 / <scale> so by scaling the container by 1.5 you would need to scale the children by 1 / 1.5 = 0.6

Unfortunately, according to the specification you cannot just use CSS like:

transform: scale(1/1.5);

since scale is defined as scale(<number>[, <number>])

where <number> is

either an or zero or more decimal digits followed by a dot (.) followed by one or more decimal digits

So you'll have to do the calculation yourself or could use a dynamic stylesheet language like LESS which supports these sort of operations.

Demo (webkit only)

andyb
  • 43,435
  • 12
  • 121
  • 150
0

If you, as suggested, use the inverted the scale factor, then note that the child does not necessarily keep its original size during the scale transformation -- this matters of course only if you let the scale transforms have a duration (e.g. by using transition: transform;).

Goran W
  • 187
  • 1
  • 12