Reputation: 1608
I'm trying to create a component that will show a flowing grid of same-sized items (number of whom can vary) in a different sized container. I'd like the items to be as large as possible (while keeping their ratio) and fill the container as much as possible while keeping nicely contained inside.
I've created a snippet with a hard coded scale values but my question is - can this (the scaling) be done automatically? Or at least what approach can you suggest to make the calculation to do it?
So far the only thing I could think of is trying different scales and measuring the final area but it doesn't seem very elegant.
Thanks
function set_state(cls, scl) {
document.getElementById("cont").className = cls;
[].slice.call(document.getElementsByClassName("it"))
.map((e) => {
e.style.width = 50 * scl + 'px';
e.style.height = 70 * scl + 'px';
});
}
#cont {
display: flex;
flex-wrap: wrap;
align-content: center;
align-items: center;
justify-content: center;
background-color: #00ff00;
}
.it {
width: 50px;
height: 70px;
margin: 10px;
background-color: #b33;
}
.shape1 {
width: 300px;
height: 200px;
}
.shape2 {
width: 200px;
height: 400px;
}
.shape3 {
width: 300px;
height: 500px;
}
.shape4 {
width: 290px;
height: 280px;
}
.shape5 {
width: 210px;
height: 380px;
}
No Scale
<button onClick='set_state("shape1", 1)'>shape 1</button>
<button onClick='set_state("shape2", 1)'>shape 2</button>
<button onClick='set_state("shape3", 1)'>shape 3</button>
<button onClick='set_state("shape4", 1)'>shape 4</button>
<button onClick='set_state("shape5", 1)'>shape 5</button>
<br/><br/>
Scale
<button onClick='set_state("shape1", .8)'>shape 1</button>
<button onClick='set_state("shape2", .92)'>shape 2</button>
<button onClick='set_state("shape3", 1.45)'>shape 3</button>
<button onClick='set_state("shape4", 1)'>shape 4</button>
<button onClick='set_state("shape5", 1)'>shape 5</button>
<br/><br/><br/><br/>
<div id="cont" class="shape5">
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
</div>
Upvotes: 1
Views: 404
Reputation: 105843
Here is a css demo with flex : x x x;
and max-width
and min-width
+ a wrapping container which can be resized like a textarea.
Similar to what you set via javascript.
Values to set is the flex-basis
, max/min-width
and the vertical padding
of the pseudo element.
The ratio is set via the pseudo element.
#cont {
display: flex;
flex-wrap: wrap;
margin: 1em;
padding: 15px;
justify-content:center;
}
.it {
background: tomato;
margin:1em;
flex:1 0 15%;
max-width:15%;
min-width:100px;
}
.it:before {
content:'';
display:block;;
padding-top:100%;
}
/* demo purpose */
.resize {
resize: both;
border: solid;
overflow: scroll;
text-align:center;
}
<div class="resize">
<h1> to run in full page mode to test behavior</h1>
<div id="cont">
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
<div class="it"> </div>
</div>
</div>
... if i understood the question :)
Upvotes: 1