Home > Net >  Easy way to maximize size of square flexbox elements?
Easy way to maximize size of square flexbox elements?

Time:12-22

I have a flexbox <div> that contains n equally-sized subelements (also <div>s). These subelements are square (aspect-ratio:1;), but the exact height and width is unknown---they should be as large as possible. Here are the constraints:

  • n will not vary.
  • Height and width of the containing <div> might vary over time, in response to the user's actions. (I might be able to make the height constant.)
  • I do not care how many rows of items there are (nor how many items there are per row). I expect that this will change if the size of the containing element changes.
  • The subelements must all be 100% inside of the containing element, with no scroll bars or hidden items.
  • The containing element does not need to be a flexbox, if this is better achieved in a different way.
  • Every subelement needs to stay of equal size, even if that size changes.

So how can I maximize the size of the subelements? Is there an easy way to do it? Answers in pure HTML/CSS will be preferred.

Here's a rough image of what I'm trying to accomplish:enter image description here

Thank you.

CodePudding user response:

I think you are looking for something like this. The 10rem sets the minimum width for each grid column, you can adjust this bigger or smaller as desired.

grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));

More hints in this excellent article.

#d {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
  gap: 1em;
}
#d>div {
  background-color: lime;
  border-radius: 10px;
  aspect-ratio: 1/1;
  padding: 1em;
}
<div id="d">
  <div>a</div>
  <div>b</div>
  <div>c</div>
  <div>d</div>
  <div>e</div>
  <div>f</div>
  <div>g</div>
 </div>

CodePudding user response:

Edit: missed the aspect-ratio thing. It works now. :-) Removed flex-grow, added aspect-ratio and provided some dimensions.

Change the width and height of the .flex-container CSS rule to see the result.

Attribution - CSS Tricks

.flex-container {
  width: 100%;
  height: 200px;
  /* We first create a flex layout context */
  display: flex;
  
  /* Then we define the flow direction 
     and if we allow the items to wrap 
   * Remember this is the same as:
   * flex-direction: row;
   * flex-wrap: wrap;
   */
  flex-flow: row wrap;
  
  /* Then we define how is distributed the remaining space */
  justify-content: space-around;
  
  padding: 0;
  margin: 0;
  list-style: none;
}

.flex-item {
  aspect-ratio: 1/1;
  width: 200px;
  height: 150px;
  margin: 5px;
  border: 1px solid black;
  background: tomato;
  padding: 5px;
  margin-top: 10px;
  line-height: 150px;
  color: white;
  font-weight: bold;
  font-size: 3em;
  text-align: center;
}
<ul >
  <li >1</li>
  <li >2</li>
  <li >3</li>
  <li >4</li>
  <li >5</li>
  <li >6</li>
</ul>

CodePudding user response:

I'm actually too tired right now to explain my answer,but I wanted you to have some code to toy with already. Tomorrow a full explanantion ( 5am here).

The CSS is commented and fairly self explanatory. Let me know if this is what you've been looking for.

However to force a number of sub elements (n) you will need to know the width of the parent element, the spacing between the sub elements (gap).

SQRT(n) will give you the number of rows and columns required within the parent. By dividing the parent width by SQRT(n), adjusted with (n-1) * gap you can derive the width for each sub element. Finally, aspect-ratio will force them to a square.

*    { box-sizing: border-box }

body {
    margin: unset;
    padding: 1rem;
}

:root {
    /* Defined here for easy access in range slider JS */
    --vw:  20;  /* initial container size in VW, changed by user */
}

.container {
    display: flex; flex-flow: row wrap;

    --n  : 100; /* number of sub items */
    --gap: 5px; /* gap between sub elements */

    /* Calculate SQRT(n) in CSS */
    --sqr1: calc((var(--n)      ( var(--n) / var(--n)   )) / 2);
    --sqr2: calc((var(--sqr1)   ( var(--n) / var(--sqr1))) / 2);
    --sqr3: calc((var(--sqr2)   ( var(--n) / var(--sqr2))) / 2);
    --sqr4: calc((var(--sqr3)   ( var(--n) / var(--sqr3))) / 2);
    --sqr5: calc((var(--sqr4)   ( var(--n) / var(--sqr4))) / 2);
    --sqr6: calc((var(--sqr5)   ( var(--n) / var(--sqr5))) / 2);
    --sqr7: calc((var(--sqr6)   ( var(--n) / var(--sqr6))) / 2);
    --sqr8: calc((var(--sqr7)   ( var(--n) / var(--sqr7))) / 2);
    --sqr9: calc((var(--sqr8)   ( var(--n) / var(--sqr8))) / 2);
    --sqrt: calc((var(--sqr9)   ( var(--n) / var(--sqr9))) / 2);

    /* --sqrt results in number of rows and columns */
    /* e.g. n = 100 => SQRT(n) = 10 => 10 rows, 10 columns */
    
    /* width = available parent width / SQRT(n) */
    /* result is space available for one square in a row */
    --width: calc(var(--vw) / var(--sqrt) * 1vw);

    /* Calculate total gaps => (n-1) * gap-size */
    --total-gap: calc((var(--sqrt) - 1) * var(--gap));

    gap: var(--gap);
    
    /* create a parental square */
    /* Parent size plus reserve for total-gap  */
    width : calc(var(--vw) * 1vw   var(--total-gap));
    height: calc(var(--vw) * 1vw   var(--total-gap));

    color: CornSilk;
}

.container > * {
    overflow: hidden;
    flex-grow: 1;     /* here, but irrelevant as size is set below */

    width    : var(--width); /* force to maintain calculated width */
    max-width: var(--width); /* in each row of the flexbox parent  */

    aspect-ratio: 1/1; /* keep it a square */

    /* Eye-candy */    
    display: grid; place-items: center; /* easy centering content */
    background-color: CornflowerBlue;
    border-radius: calc(var(--width) / 4);
}

input[type="range"] { width: 100% }
label, input        { display: block; font-size: 1em }
<label>size [1 - 85vw]<span id="info-size"></span>
    <input type="range" min="1" max="85" step="0.1" value="20"
           oninput="document.documentElement.style.setProperty('--vw', this.value);
                    document.getElementById('info-size').innerHTML = ' </span> '   this.value   'vw';">
</label>
<br><br><br>
<div >
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
    <div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div><div>text</div>
</div>

  • Related