xims
xims

Reputation: 1608

css flex - maximise items size while keeping them filling different size container

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">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
  <div class="it">&nbsp;</div>
</div>

Upvotes: 1

Views: 404

Answers (1)

G-Cyrillus
G-Cyrillus

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">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
    <div class="it">&nbsp;</div>
  </div>
</div>

... if i understood the question :)

Upvotes: 1

Related Questions