Flexboxgrid and gap overflow issue - css

Im using flexboxgrid library to create easy responsive layout, I have a parent div styled like so
display: flex;
flex-wrap: wrap;
gap: 2rem;
children have flexboxgrid styling
col-xs-12 col-md-6 col-lg-4
and it works otherwise well, except when I put that 'gap: 2rem' on parent, then div's start overflowing and push last item to another row.
To illustrate problem:
How can I fix it ?
EDIT: Link to CodePen, with gap there is 2 rows, without gap 1 row.
How to keep gap, stay on 1 row ?
https://codepen.io/ShinigamiZ/pen/YzezgwE

If you want to spread them out over the whole width, don't set a flex-basis for the elements. Rather set flex-grow: 1. This means, that the elements will grow to be as big as possible.
If you want to wrap them to a new line, you need to alter your calculation for flex-basis to also incorporate the gap.
.parent {
display: flex;
flex-wrap: wrap;
gap: 2rem;
background-color: yellow;
}
.sib {
background-color: gray;
flex-grow: 1;
}
<div class='parent'>
<div class='sib'>
123
</div>
<div class='sib'>
123
</div>
<div class='sib'>
123
</div>
</div>

Column classes (col-xs-12 col-md-6 col-lg-4) means it's percentage width and that's where the issue is because the gap is not included in percentage calculation.
My take on this is to allow the columns shrink and grow but only by the amount of gap you define. With your example that would be something like:
.col-md-6 {
flex: 1 0 calc(50% - 2rem);
max-width: 50%;
}
The only issue is a slight inconsistency with columns width if there's a empty space left or if it's the only column and not fullwidth as the elements have their own original percentage width and not one reduced by gap.
https://codepen.io/Erehr/pen/jOxYadW

Related

How to achieve specific css flexbox layout with multiple columns of different row items [duplicate]

This question already has answers here:
Make a div span two rows in a grid
(2 answers)
Closed 2 years ago.
I'm trying to achieve the flex layout as per the image below. In my code examples, I've not been successful, yet so I can't provide any useful code snippets.
Box 1 would be fixed width and 100% height
Box 2 and 3 would be 50% height and 100% width
Box 4 would be fixed width and 100% height
It would be wrapped in a container DIV (not shown).
Is this correct usage for Flex, or should a grid be used for something like this? I've found an example that manages to get either box 1 or box 4 in position (such as here: Mozilla Flex Example, but not with both.
For layouts with such requirements CSS Grid is a much better choice than Flexbox.
CSS Grid Layout excels at dividing a page into major regions or defining the relationship in terms of size, position, and layer, between parts of a control built from HTML primitives.
Here's a working codepen. You can modify the fixed columns width by changing the grid-template-columns definitions.
Yes, you can do this with flexbox - you will need a container div for box 2 and box 3. You can use something like this:
#layout {
display: flex;
resize: both;
overflow: scroll;
}
#box1, #box4 {
width: 100px;
}
#box2-3 {
flex-grow: 1;
display: flex;
flex-direction: column;
}
#box2, #box3 {
flex-grow: 1;
}
#box1, #box2, #box3, #box4 {
border: 1px solid red;
}
<div id="layout">
<div id="box1">Box 1</div>
<div id="box2-3">
<div id="box2">Box 2</div>
<div id="box3">Box 3</div>
</div>
<div id="box4">Box 4</div>
</div>

CSS flex-wrap: Put gap between items unless wrapped?

I come often across with this scenario, where i have i.e. 2 flex-children, with property flex-direction row. so they are first shown side by side with a gap between them (margin-right).
And by resize, as soon as there is not enough space left for both, flex-wrap moves the second child under the first one, so i don't need the margin-right from 1. item anymore.
Can i dynamically set the margins depends on the "wrap" status?
Fiddle: https://jsfiddle.net/ejmhxztd/
Fiddle Note: You should resize the window (reduce width) and see the wrapped case. If you continue reducing the width, you will see that the text of the first child will also split into 2 lines, since the margin-right is there and takes space.
.parent {
display:flex;
flex-direction:row;
flex-wrap:wrap
}
.child1 {
margin-right:300px
}
<div class="parent">
<span class="child1">Child1 Text</span>
<span class="child2">Child2 Text</span>
</div>
I know this is an old issue, but you can use "column-gap" and "row-gap" to define gaps only in some direction.
For example:
.class{
display: flex;
align-items: center;
column-gap: 10px;
flex-wrap: wrap-reverse;
flex-direction: row;
}
In this case, the gap will only affect in columns.
You can try to use CSS-grid for this:
.parent {
display:grid;
grid-column-gap:300px;
grid-template-columns:repeat(auto-fit,minmax(100px,max-content));
}
.parent > * {
border:1px solid;
}
<div class="parent">
<span class="child1">Child1 Text</span>
<span class="child2">Child2 Text</span>
</div>

Why flexbox won't grow to its text?

I need .child-1-2 to grow to its text, but the text overflows. When I change flex-basis of .child-1-1 from 50px to auto, it seems to work. Why is that happening?
.parent-1 {
display: flex;
}
.child-1 {
display: flex;
flex: 0 0 auto;
background: #4c72af;
}
.child-1-1 {
display: flex;
flex: 0 0 50px;
}
.child-1-2 {
display: flex;
flex: 1 0 auto;
}
.child-2 {
display: flex;
flex: 1 0 auto;
background: #f7ed7e;
}
<div class="parent-1">
<div class="child-1">
<div class="child-1-1">C1</div>
<div class="child-1-2">Some text</div>
</div>
<div class="child-2">
<div class="child-2-1">Another text</div>
</div>
</div>
In order to understand the reason why the described behavior takes place, we should know how flex-basis and flex-grow actually work and how width of flex items is calculated.
Flex-grow
From flex-grow is weird. Or is it?
If we apply display: flex; to the parent element and don't change
anything else, the child elements will be stacked horizontally, no
matter what. If there isn't enough space, they will shrink in size. If
on the other hand there is more than enough space, they won't grow,
because Flexbox wants us to define how much they should grow. So
rather than telling the browser how wide an element should be,
flex-grow determines how the remaining space is distributed amongst
the flex items and how big the share is each item receives.
Flex-basis
Width of a flex item is determined in the following order:
content
width
flex-basis (limited by max|min-width)
From The Difference Between Width and Flex Basis
If no flex-basis is specified, then the flex-basis falls back to the
item’s width property.
If no width is specified, then the flex-basis falls back to the
computed width of the item’s contents.

Flexbox grow and shrink property columns vs determined width columns for responsive grid system

Lately I've been learning flexbox and how to make my own grid system. When making grid system using floats, we determine number of columns per layout and each column's width in percentages. But when using flexbox, all the layout tutorials I saw are simply using flex-direction: row; and flex: 1
for columns, to make all of them equal size, equal gutter, centered and in one row. But when I checked flexboxgrid source code on github, they are using same principle as bootstrap 3. They have columns for different screen sizes, 12 columns and flex-grow, shrink are disabled. Instead, each column is determined in width percentages, like col-xs-1 max-width: 8.33%.
Now I'm wondering what's the difference between these two techniques and which one is more preferable. I mean determining width for each column requires a lot of counting, while using flex grow property just fulfills the whole viewport in main axis with equally sized columns and gutters.
tl;dr
They are not techniques to achieve the same result, they do different things.
Flexbox grid uses flex-basis to determine width in flex container's main axis. It does not use flex: 1; on flex items because that is equivalent to flex: 1 1 0;. Which means flex-basis would have a value of 0, and the flex items sizes would be proportional to the specified grow and shrink factor, both having a value of 1.
Example
col-xs-1 with a flex-basis of 0 specified from flex: 1; would grow as if it was col-xs-12 if it is the only child, if there is another col-xs-1 like this as a sibling, then it would grow as if it was col-xs-6 and so forth.
It is expected for every col-xs-1 to fill 1/12, (8.33333333%), of the container, which would not be the case using flex: 1;.
* {
box-sizing: border-box;
}
article {
margin-bottom: 1rem;
}
[class^="col-"],
[class*="col-"] {
flex: 0 0 auto; /* flex-grow: 0; flex-shrink: 0; flex-basis: auto; */
}
.row {
display: flex;
margin-right: -.5rem;
margin-left: -.5rem;
}
.col-xs-1 {
padding-right: .5rem;
padding-left: .5rem;
flex-basis: 8.33333333%;
}
.box-row {
min-height: 1em;
background: #007FFF;
}
article:last-of-type .col-xs-1 {
flex: 1; /* Same as flex: 1 1 0; */
}
<article class="row">
<section class="col-xs-1">
<div class="box-row"></div>
</section>
<section class="col-xs-1">
<div class="box-row"></div>
</section>
</article>
<article class="row">
<section class="col-xs-1">
<div class="box-row"></div>
</section>
<section class="col-xs-1">
<div class="box-row"></div>
</section>
</article>

Flexbox row: doesn't grow according to content? [duplicate]

This question already has answers here:
What are the differences between flex-basis and width?
(6 answers)
Closed 4 years ago.
I have the following structure, and I'd like to understand why my row does not grow with its inner content.
.row {
border:solid red;
display: flex;
flex-direction: row;
}
.cell {
border: solid green;
flex: 0 0 400px;
}
<div class="row">
<div class="cell">
cell 1
</div>
<div class="cell">
cell 2
</div>
<div class="cell">
cell 3
</div>
</div>
JsFiddle
I don't want the cells to grow or shrink, they should always be 400px width. The parent should grow and overflow the window, and an horizontal scrollbar is expected.
In the above example, the red border should be around the green border. The green border has the expected dimensions, not the red one.
I don't want to set a static width to my row for maintainability reasons related to my usecase.
I'm open for non-flexbox solutions (see inline-block attempt), but would appreciate more a flexbox one (because I need align-items: center behavior on the row)
If you want your container to always match the width of it's children, you'll need to look into display: inline-flex.
display: flex behaves more like a container with a width of 100%
Here's a fiddle that should work:
http://jsfiddle.net/hnrs64fm/

Resources