I have an inner div that has been scaled by an arbitrary amount. I would like the size of the container div to be that of the inner div, but instead it is sized as if the inner contents were not scaled. How can I get it to shrinkwrap correctly?
#content {
background-color: blue;
height: 200px;
width: 200px;
}
#scaler {
transform: scale(0.5);
transform-origin: 0 0;
}
#outer {
background-color: red;
display: inline-block;
}
<div id="outer">
<div id="scaler">
<div id="content">
</div>
</div>
</div>
Too nice a challenge to pass.
Pretty sure not achievable via CSS alone, I expected it to be easier with JS.
Ended up as a bit of both:
class zoomFactor {
constructor(el) {
this.el = this.query(el, document);
this.update();
this.query('input').addEventListener('input', () => this.update());
window.addEventListener('resize', () => this.update())
}
query(s, el = this.el) {
return el.querySelector(s);
}
value() {
return this.query('input') ?
this.query('input').value :
parseFloat(this.el.dataset('scale')) || 1;
}
update() {
let val = this.value(),
z1 = this.query('z-1'),
z2 = this.query('z-2'),
z3 = this.query('z-3');
z1.style = z2.style = z3.style = '';
z2.style.width = z1.clientWidth * val + 'px';
z1.style.width = z2.style.width;
z3.style.transform = 'scale(' + val + ')';
z3.style.width = z2.clientWidth / val + 'px';
z1.style.height = z3.clientHeight * val + 'px';
}
}
new zoomFactor('zoom-factor');
.range {
display: flex;
justify-content: center;
}
.range input {
width: 70%;
}
zoom-factor {
position: relative;
display: block;
}
z-1,
z-2,
z-3 {
display: block;
color: white;
}
z-1 {
width: 50%;
float: left;
overflow: hidden;
position: relative;
margin: 1em 1em .35em;
}
z-2 {
position: absolute;
width: 100%;
background-color: red;
}
z-3 {
transform-origin: left top;
background-color: blue;
}
z-3 p {
text-align: justify;
}
p,
h3 {
padding-right: 1em;
padding-left: 1em;
}
h3 {
margin-top: 0;
padding-top: 1em;
}
z-3>*:last-child {
padding-bottom: 1em;
}
<zoom-factor>
<div class="range">
<input type="range" value=".8" min="0.05" max="1.95" step="0.01">
</div>
<z-1>
<z-2>
<z-3>
<h3>Transformed content</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Elit ut aliquam purus sit amet. Non pulvinar neque laoreet suspendisse interdum consectetur libero. Sed euismod nisi porta
lorem mollis aliquam ut. Mattis nunc sed blandit libero volutpat. Bibendum at varius vel pharetra vel. Nibh situs amet commodo nulla facilisi nullam vehicula ipsum. Metus aliquam eleifend mi in nulla posuere sollicitudin. Dolor morbi non arcu
risus. Venenatis urna cursus eget nunc.</p>
<p>In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Urna molestie at elementum eu facilisis sed odio. Arcu risus quis varius quam quisque. Lorem ipsum dolor sit amet. Fringilla est ullamcorper eget nulla facilisi etiam dignissim
diam quis. Arcu bibendum at varius vel pharetra vel turpis. Consectetur a erat nam at lectus urna. Faucibus pulvinar elementum integer enim neque volutpat ac tincidunt. Diam quam nulla porttitor massa id neque aliquam vestibulum. Nam libero
justo laoreet sit amet cursus sit amet dictum. Imperdiet sed euismod nisi porta lorem. Varius vel pharetra vel turpis nunc eget lorem dolor. Vitae auctor eu augue ut lectus arcu bibendum at varius. Aliquet enim tortor at auctor urna nunc id
cursus metus. Non curabitur gravida arcu ac tortor.</p>
</z-3>
</z-2>
</z-1>
<h3>Normal content</h3>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Elit ut aliquam purus sit amet. Non pulvinar neque laoreet suspendisse interdum consectetur libero. Sed euismod nisi porta lorem
mollis aliquam ut. Mattis nunc sed blandit libero volutpat. Bibendum at varius vel pharetra vel. Nibh sit amet commodo nulla facilisi nullam vehicula ipsum. Metus aliquam eleifend mi in nulla posuere sollicitudin. Dolor morbi non arcu risus. Venenatis
urna cursus eget nunc.</p>
<p>In tellus integer feugiat scelerisque varius morbi enim nunc faucibus. Urna molestie at elementum eu facilisis sed odio. Arcu risus quis varius quam quisque. Lorem ipsum dolor sit amet. Fringilla est ullamcorper eget nulla facilisi etiam dignissim diam
quis. Arcu bibendum at varius vel pharetra vel turpis. Consectetur a erat nam at lectus urna. Faucibus pulvinar elementum integer enim neque volutpat ac tincidunt. Diam quam nulla porttitor massa id neque aliquam vestibulum. Nam libero justo laoreet
sit amet cursus sit amet dictum. Imperdiet sed euismod nisi porta lorem. Varius vel pharetra vel turpis nunc eget lorem dolor. Vitae auctor eu augue ut lectus arcu bibendum at varius. Aliquet enim tortor at auctor urna nunc id cursus metus. Non curabitur
gravida arcu ac tortor.</p>
<p>In metus vulputate eu scelerisque felis. Quam quisque id diam vel quam elementum pulvinar etiam. Porttitor leo a diam sollicitudin tempor id eu nisl. Feugiat in fermentum posuere urna nec tincidunt praesent semper feugiat. Mattis rhoncus urna neque
viverra. Euismod elementum nisi quis eleifend quam adipiscing. Enim diam vulputate ut pharetra sit amet. Adipiscing tristique risus nec feugiat in fermentum posuere urna nec. Risus sed vulputate odio ut. Augue interdum velit euismod in pellentesque.
Consequat interdum varius sit amet mattis vulputate enim nulla aliquet. At quis risus sed vulputate odio ut enim. In egestas erat imperdiet sed euismod nisi porta.</p>
<p>In arcu cursus euismod quis viverra nibh. Adipiscing commodo elit at imperdiet. Consectetur adipiscing elit duis tristique sollicitudin. Dui ut ornare lectus sit amet est placerat in. Felis eget nunc lobortis mattis. Pellentesque dignissim enim sit
amet. Senectus et netus et malesuada. A lacus vestibulum sed arcu non odio. Congue quisque egestas diam in arcu cursus euismod quis viverra. Nisi scelerisque eu ultrices vitae auctor eu augue. Sapien faucibus et molestie ac feugiat sed. Ullamcorper
a lacus vestibulum sed arcu.</p>
<p>Varius vel pharetra vel turpis nunc eget lorem. Odio ut enim blandit volutpat maecenas volutpat. Tellus in hac habitasse platea dictumst vestibulum rhoncus est. Sed sed risus pretium quam. Vel pharetra vel turpis nunc eget lorem dolor. Sit amet porttitor
eget dolor morbi. Mattis nunc sed blandit libero volutpat sed. Sit amet nulla facilisi morbi tempus iaculis urna id volutpat. Maecenas ultricies mi eget mauris pharetra et ultrices neque. Congue nisi vitae suscipit tellus. Accumsan tortor posuere
ac ut consequat semper viverra. In fermentum posuere urna nec tincidunt praesent semper feugiat nibh. Sed velit dignissim sodales ut. Tempus urna et pharetra pharetra massa massa ultricies. Ornare aenean euismod elementum nisi quis eleifend quam.
Aliquet nibh praesent tristique magna sit amet purus gravida. Euismod lacinia at quis risus sed vulputate. Ultrices mi tempus imperdiet nulla.</p>
</zoom-factor>
Most likely you won't want the input[type="range"]
and want to control the scale from outside. You can simply pass <zoom-factor>
a data-scale
attribute and init it:
const zFactor = new zoomFactor('zoom-factor');
You don't really need to store it in a const
, but it's useful for changing the scale:
zFactor.el.dataset('scale') = 0.5;
zFactor.update();
I'll probably wrap it up as a plugin, but I want to test it cross-browser and provide a few more options (i.e. allow changing the transform origin to center or right, create an auto-init method, etc...), to make it more flexible.