How to Set a Flex-Container to Be the Width of Its Flex-Items

How to make flex container width adapt to the width (and numbers) of flex items?

You could use a single grid (instead nested flexbox) and set the input on the first row among and before the cards.

here is an example of the idea or a codepen with a side element https://codepen.io/gc-nomade/pen/NWpVeOY :

* {
box-sizing: border-box;
}

.mainContainer {
min-height: 200px;
padding: 1rem;
}

#search {
width: 100%;
height: 2rem;
background-color: var(--Mwhite);
border: 0.05rem solid var(--Mdefault);
border-radius: 0.5rem;
color: var(--Mdefault);
padding: 0 0 0 0.5rem;
outline: 0.05rem solid transparent;
transition: outline 0.5s;
grid-column: 1 / -1;
}

.secondaryContainer {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(12.5rem, max-content));
justify-content: center;
row-gap: 1rem;
column-gap: 0.5rem;
}

.card {
background-color: var(--Mwhite);
border: 0.05rem solid var(--Mdefault);
width: 12.5rem;
height: fit-content;
min-height: 16.25rem;
display: flex;
flex-flow: column nowrap;
align-items: center;
justify-content: space-between;
box-shadow: var(--Mdefault) 0 0 0;
transition: box-shadow 0.5s, border 0.5s;
border-radius: 0.8rem;
}

input#search,
.card {
border: 1px solid black;
;
}
<div class="mainContainer">

<div class="secondaryContainer">
<input type="search" placeholder="search" id="search" />
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
<div class="card">card</div>
</div>
</div>

Make flex container take width of content, not width 100%

Instead of display: flex on the container, use display: inline-flex.

This switches the container from block-level (which takes the full width of its parent) to inline-level (which takes the width of its content).

This sizing behavior is similar to display: block vs. display: inline-block.

For a related problem and solution see:

  • Make flex items take content width, not width of parent container

Make Flex container width 'shrink wrap' to content, up to a certain width?

If you have access to the sizes of the photos before hand or can get them, you can create an array of the widths and then loop over the list in order and find which row will be the largest less than max.
Once found you can set the width style value to this new width.

<html>
<head>
<style>
.photos {
margin: 0px auto 0px auto;
box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.16);
max-width:500px;
display: flex;
flex-wrap: wrap;
justify-content: center;
border: 1px solid black;
}

.photo {
height: 50px;
border: 1px solid red;
}
</style>
</head>
<body>
<div id="photos" class="photos">
<div class="photo" style="width: 155px"></div>
<div class="photo" style="width: 254px"></div>
<div class="photo" style="width: 233px"></div>
<div class="photo" style="width: 387px"></div>
</div>
</body>
<script>
var photos = [155, 254, 233, 387];
var actualWidth = 0;
var maxWidth = 500;
var currentWidth = 0;
var columnCount = 0;
var actualColumnCount = 0;

// get div that will need its width adjusted
var container = document.getElementById('photos');
// loop through each of the photos widths
photos.forEach((pWidth) => {
// is our combined width more than the max width
if (pWidth + currentWidth > maxWidth) {
// is the currentWidth more than the actualWidth
console.log(currentWidth);
actualWidth = checkActual(currentWidth, actualWidth);
// with border css you are adding 2*width to the width of the box model. so we need to accoutn for this
actualColumnCount = checkActual(columnCount, actualColumnCount);
// reset the currentWidth as we are now starting a new row
currentWidth = pWidth;
// same as above
columnCount = 1;
} else {
// add currentWidth to loopvalue width
currentWidth += pWidth;
// increment columnCount
columnCount += 1;
}
});
console.log(currentWidth);
// one last check incase last element would make the highest row count
actualWidth = checkActual(currentWidth, actualWidth);
actualColumnCount = checkActual(columnCount, actualColumnCount);
// set the width the largest width for a row and add the offset to account for the border
container.style.width = actualWidth + 2 * actualColumnCount;

// since both sets of compared values are numbers, we can use this generic function for our test
function checkActual(current, actual) {
return current > actual ? current : actual;
}
</script>

Flexbox - Set flex item size based total number of items

How about this:

#container {
display: flex;
border: 4px solid black;
padding: 3px;
width: 600px;
}

.box {
flex: 1 1 0px;
border: 2px solid grey;
padding: 2px;
}
<div id="container">
<div class="box">We choose to go to the Moon...We choose to go to the Moon in this decade and do the other things, not because they are easy, but because they are hard.</div>
<div class="box">Hello World</div>
<div class="box"></div>
<div class="box">Never Gonna Give You Up, Never Gonna Let You Down</div>
</div>

How to calculate the actual width of child elements of a flexbox container?

You are facing the shrink effect. In all the cases the total width 100vw + 25% is bigger than 100% so both items will shrink equally.

Since your container is also full width, the overflow will always be equal to 25% or 25vw. Both element have the default shrink value 1 so we have a sum equal to 125vw.

The first element width will be equal to: 25vw - (25vw * 25vw/125vw) = 20vw
and the width of the second item will be: 100vw - (25vw * 100vw/125vw) = 80vw

You can logically see that the total is 100vw (20vw + 80vw) and when the screen width is equal to 600px, 20vw is equal 120px.

To avoid this, disable the shrink effect on the first item by setting flex-shrink:0

* {
margin: 0;
padding: 0;
}

.container {
height: 300px; /* your code here */
display: flex;
}

.left {
background-color: #f44336;
width: 25%;
min-width: 100px;
flex-shrink:0;
}

.right {
background-color: #2973af;
width: 100vw;
}
<div class="container">
<div class="left"></div>
<div class="right"></div>
</div>


Related Topics



Leave a reply



Submit