Like the title says, when flex-wrap:wrap is enabled on a parent div, the child grid containers double in height. I’d like it to not do that, but more importantly, why is this happening?
I assumed the height of the grid would simply adjust if/when more grid-items are added to cause it to wrap…but I’m clearly missing something.
I’d like it to look like it does when flex-wrap:nowrap
is enabled, but also I want it to wrap….
.container {
width: 88%;
margin: 2rem auto;
max-width: 1400px;
}
.cno-event-search-filters__container {
display: flex;
flex-direction: column;
align-items: stretch;
}
.cno-event-search-filters__filter-container {
border: 2px solid black;
display: grid;
grid-template-columns: repeat(auto-fit, max(240px));
gap: 1rem;
}
<div class="container">
<div class="cno-event-search-filters">
<div class="cno-event-search-filters__container">
<h4 class="cno-event-search-filters__title">Event Types</h4>
<div class="cno-event-search-filters__filter-container">
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Culture">
<label for="Culture">Culture</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Entertainment">
<label for="Entertainment">Entertainment</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Sports">
<label for="Sports">Sports</label>
</div>
</div>
</div>
<div class="cno-event-search-filters__container">
<h4 class="cno-event-search-filters__title">Locations</h4>
<div class="cno-event-search-filters__filter-container">
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Ampitheatre">
<label for="Ampitheatre">Ampitheatre</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Capitol Lawn">
<label for="Capitol Lawn">Capitol Lawn</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Capitol Museum">
<label for="Capitol Museum">Capitol Museum</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Chapel">
<label for="Chapel">Chapel</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Choctaw Village">
<label for="Choctaw Village">Choctaw Village</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Playground">
<label for="Playground">Playground</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Red Warrior Park">
<label for="Red Warrior Park">Red Warrior Park</label>
</div>
<div class="cno-event-search-filters__filter">
<input type="checkbox" id="Stickball Field">
<label for="Stickball Field">Stickball Field</label>
</div>
</div>
</div>
</div>
</div>
2
Answers
I guess is a glitch of browser trying to automatically calculate sizes, give it some help deifining that your container is full width with a
width: 100%
in&__filter-container
Here is the codepen: https://codepen.io/Crist-bal-D-az-lvarez/pen/oNaydwO
This quirk is a bit tricky so I will try to use simple words to explain what’s happening.
First, when defining
flex-wrap
you control the nature of the layout like detailed in the Specification:Even if in your case, you have one line when you add
flex-wrap: wrap
your layout is still considered as "multi-line" and the algorithm is a bit different from the "single-line" one.The difference is related to how of the size of each line is calculated which also affect the size of the items. Here it’s about the width since we have a column direction.
When you have a "single-line" layout (
flex-wrap: nowrap
), calculating the width of the line is easy. From the SpecificationYour container is a block element so its full width (the definite cross size). That width is used as the size of the line and the element inside will stretch to fit that size. A logical behavior BUT we can change it we remove that stretch part.
Note how you only have one column of
240px
inside your grid because your element no more stretch inside the whole line and the CSS grid algorithm will create only one column following its algorithmYour grid container has no definite size, no max size and no min size so we fall into the last "otherwise" and we end with one repetition. (note that
auto-fit
andauto-fill
have the same algorithm here)Now, when you have a "multi-line" layout, the algorithm of defining the number of lines and the line sizes is more complex and different form the "single-line" layout even if at the end you have only one line. This is the trickiest part and what you need to know is that the size of the items is used to identify the size of the lines.
In other words, we need to first identify the element size to find the size of the lines and your grid container has no definite size, no max size and no min size so we fall into the same previous case where we end with one column. Then the flexbox algorithm will identify one line. Then the stretch alignment will strike to make your grid container full width and the
auto-fit
algorithm will strike another time to create more column BUT the height of your grid container won’t change and here is the quirk.Before finding the number of lines and defining their size we first calculate the width/height of the grid container. After finding the number of lines and their sizes, the width will get updated (due to the stretch alignment) but the height won’t change. The number of columns will change because we have space for them.
If you do a comparison, you will find that the height is equal to the size of the container without
grid-template-columns
. Addflex-wrap: wrap
and use the Dev tool to disable thegrid-template-columns
and the height won’t change. That height is also the same when we disable thestretch
alignmentHere is a simplified version of your case. Resize the main container and notice how the height of the inner one won’t change.
To fix this and allow the height to change you need to have either a "defined size, a max size or min size" like in the algorithm.
a
min-width: 100%
orwidth: 100%
can do the job