Css3 Scale Transform on Parent Div But Keeping Constant Size in Some of the Associated Divs

How to use CSS transform: scale(); to fit child div to parent div responsively in react?

Using @Gershom's snippet, but keeping aspect ratio

let scaledWrapper = document.getElementsByClassName('scaled-wrapper')[0];
let applyScaling = scaledWrapper => { // Get the scaled content, and reset its scaling for an instant let scaledContent = scaledWrapper.getElementsByClassName('scaled-content')[0]; scaledContent.style.transform = 'scale(1, 1)'; let { width: cw, height: ch } = scaledContent.getBoundingClientRect(); let { width: ww, height: wh } = scaledWrapper.getBoundingClientRect(); // let scaleAmtX = ww / cw;// let scaleAmtY = wh / ch; let scaleAmtX = Math.min(ww / cw, wh / ch); let scaleAmtY = scaleAmtX; scaledContent.style.transform = `scale(${scaleAmtX}, ${scaleAmtY})`; };
applyScaling(scaledWrapper);
// ---- The rest of the code is just for the demonstration ui ----let change = () => { let w = parseInt(wInp.value); let h = parseInt(hInp.value); if (!isNaN(w)) scaledWrapper.style.width = `${w}px`; if (!isNaN(h)) scaledWrapper.style.height = `${h}px`; scaledWrapper.getElementsByClassName('scaled-content')[0].innerHTML = textInp.value; applyScaling(scaledWrapper);};
let wInp = document.createElement('input');wInp.setAttribute('placeholder', 'input parent width in px');wInp.addEventListener('input', change);wInp.value = '100';document.body.appendChild(wInp);
let hInp = document.createElement('input');hInp.setAttribute('placeholder', 'input parent height in px');hInp.addEventListener('input', change);hInp.value = '100';document.body.appendChild(hInp);
let textInp = document.createElement('input');textInp.setAttribute('placeholder', 'input text content');textInp.addEventListener('input', change);textInp.value = 'abc';document.body.appendChild(textInp);
.wrapper-wrapper {  box-sizing: border-box;  border: solid 2px blue;  position: relative;}.scaled-wrapper {  position: relative;  width: 100px; height: 100px;  outline: 1px solid red;  z-index: 1;}.scaled-content {  box-sizing: border-box;  display: inline-block;  transform-origin: 0 0;  background-color: #ffd0d0;  z-index: -1;}
<div class="wrapper-wrapper">  <div class="scaled-wrapper">    <div class="scaled-content">abc</div>  </div></div>

Transform scale keeps the original space around the scaled element

A brutal way would be to virtually reduce space needed by element.

Your example shows a known width & height, so it makes it easy. else you would need a javascript method.

.box_1 {
width: 300px;
height: 300px;
transform: scale(0.5);
transform-origin: left top;
margin-bottom:-150px;
margin-right:-150px;
}

https://jsfiddle.net/0bc4sxk3/1/

Scaling up would mean positive margins.

Transform only happens at screen, elements still use initial room and place needed in the flow of the document.

Scale a div without changing the size and position of its child elements

You can't prevent the child elements to be scaled if you apply the transform on your wrapper.



But you can use a CSS variable to store your scale factor, and then use calc to calculate (better than doing it manually) and apply the inverse scale for the child elements:

.wrapper {  padding: 0 20px;  transform: scale(var(--scale));  background: #ddd;}
.wrapper > * { transform: scale(calc(1/var(--scale)));}
<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>

Div inline-block display and proper position after using transform: scale

Here is a quick fix for you

JSFiddle

Just add a div (for example .wrap) around .elements and change its width and height depending on scale like this.

el.parent('.wrap').css({
width: (350 * scale) + "px",
height: (500 * scale) + "px"
});
.wrap {
width: 350px;
height: 500px;
display: inline-block;
position: relative;
}

.elements {
width: 340px;
height: 490px;
background-repeat: no-repeat;
margin: 5px;
-moz-transform-origin: 0 0;
transform-origin: 0 0;
}

Scale/zoom a DOM element and the space it occupies using CSS3 transform scale()

The HTML (Thanks Rory)

<!DOCTYPE html>
<html>
<head>
<meta name="description" content="Sandbox for Stack Overflow question http://stackoverflow.com/q/10627306/578288" />
<meta charset=utf-8 />
<title>Sandbox for SO question about scaling an element both visually and dimensionally</title>
</head>
<body>

<div id="wrapper">
<div class="surrounding-content">
before
</div>

<div id="content-to-scale">
<div>something inside</div>
<div><img src="http://placekitten.com/g/150/100"></div>
<div>another something</div>
</div>

<div class="surrounding-content">
after
</div>
</div>

</body>
</html>

The CSS (Still started from Rory's base)

body {
font-size: 13px;
background-color: #fff;
}
#wrapper {
width: 50%;
margin-left: auto;
margin-right: auto;
border: 0.07692307692307693em solid #888;
padding: 1.1538461538461537em;
}
.surrounding-content {
border: 0.07692307692307693em solid #eee;
}
#content-to-scale {
border: 0.07692307692307693em solid #bbb;
width: 10em;
}
#content-to-scale {
font-size: 1.1em;
}
#content-to-scale img {
width: auto;
height: auto;
min-width: 100%;
max-width: 100%;
}

The Explanation:

I'm using font size and ems to "scale" the dimensions of the child elements.

Ems are dimension units that are relative to the current context's font-size.

So if I say I have a font-size of 13px and a border of 1 (the desired border-width in pixels) divded
by 13 (the current context's font-size also in pixels) = 0.07692307692307693em the browser ought to render a 1px border

To emulate a 15px padding I use the same formula, (desired pixels)/(current context's font-size in pixels) = desired ems.
15 / 13 = 1.1538461538461537em

To tame the scaling of the image I use an old favorite of mine: the natural ratio preserving scale, let me explain:

Images have a natural height and width and a ratio between them. Most browser's will preserve this ratio if both width and height are set to auto.
You can then control the desired width with min-width and max-width, in this case making it always scale to the full width of the parent element, even when it will scale beyond it's natural width.

(You can also use max-width and max-height 100% to prevent the image from busting out of the borders of the parent element, but never scaling beyond their natural dimensions)

You can now control the scaling by tweaking the font-size on #content-to-scale. 1.1em roughly equals scale(1.1)

This does have some drawbacks: nested font-sizing in ems are applied recusively. Meaning if you have:

<style type="text/css">
div{
font-size: 16px;
}
span{
font-size: 0.5em;
}
</style>
<div>
<span>
<span>
Text
</span>
</span>
</div>

You will end up with "Text" rendering at 4px instead of the 8px you might expect.



Related Topics



Leave a reply



Submit