How to break row ("clear" element) in css flexbox - css

Is it possible to "clear" element in a "display: flex" container?
I want to achieve something like this:
20 elements in a row on a big screen
10 elements in a row on a smaller screen
5 elements in a row on a small screen
With floats, I could "clear" after each 5th element with proper media queries...

You can add flex-wrap: wrap; to the container and set the width of the elements inside.
Then you should have the control to decide on which elements the floating will stop.
Demo: http://codepen.io/imohkay/pen/gpard

You can try to add a width with percentages to the elements inside the container, along with the property flex-wrap: wrap. Then, with a media query, you manipulate the width of said elements given a breaking point. Here is an example:
.container {
display: flex;
flex-wrap: wrap;
}
.element {
width: calc(25% - 20px);
height: 100px;
margin: 10px;
background-color: red;
}
#media(max-width: 800px) {
.element {
width: calc(50% - 20px);
}
}
<div class="container">
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
<div class="element"></div>
</div>

As # BoltClock suggested you can "resize your flex container to accommodate the number of items on each line and let them wrap organically".
If you want to actually clear a line similar to using floats you can set a margin in the direction you want to clear.
element{
margin-right: calc( 100% - widthOfelement);
}
*{
box-sizing: border-box;
}
.parent{
display: flex;
width: 600px;
height: auto;
flex-wrap: wrap;
border: 1px grey dashed;
}
.child{
width: 100px;
height: 50px;
border: 1px orangered solid;
background-color: skyblue;
}
/*add "clear" after first child*/
.child:nth-child(1){
margin-right: calc(100% - 100px);
}
/*add "clear" after third child*/
.child:nth-child(3){
margin-right: calc(100% - 200px);
}
<div class="parent">
<div class="child">1</div>
<div class="child">2</div>
<div class="child">3</div>
<div class="child">4</div>
<div class="child">5</div>
<div class="child">6</div>
</div>

Related

Full-height flex item with height set to 0

I have the following code as working on development with flexbox.
#container {
display: flex;
justify-content: space-around;
width: 100%;
}
.content {
border: 1px solid black;
display: flex;
flex-direction: column;
height: 400px;
width: 400px;
}
#item1 {
background-color: red;
flex-grow: 1;
height: 0;
}
#item2 {
background-color: green;
flex-grow: 1;
height: 100px;
}
#item3 {
background-color: blue;
flex-grow: 1;
height: 900px;
}
<div id="container">
<div class="content">
<div id="item1"></div>
</div>
<div class="content">
<div id="item2"></div>
</div>
<div class="content">
<div id="item3"></div>
</div>
</div>
I know that setting flex-grow: 1 would take the remaining space of its parent. However, the property height seems to have no effect whatever its value is.
Reason being your flex-direction is set to column, which mean the flex-grow reacts from top to bottom, so the flex-grow responding to the height instead of width.
another question is, why flex-direction is column, but width is filled up, because it is a <div> displayed as block, the width is auto filled by display: block;
you are using flex-grow that’s why. have a look on this https://www.w3schools.com/cssref/css3_pr_flex-grow.asp
https://stackoverflow.com/a/64748435/1095913 (down here) is right, solution is: flex-grow: 0;
Here's another reference https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow

In css select first child *of each line* with wrapped flexboxes (first-column?)

I have a flexbox that is basically a "list of sub divs". The box' main feature is the automated wrapping. However I notice that, due to children's wrapping value, there is also an offset to the left of the box.
I wish to remove this. I've tried doing this by giving the container a negative padding: however that seems to be disallowed.
Then I tried to find a selector for the "first child on each line", but that also failed. Is there a way to do this in css?
Alternatively, an a grid display: grid be made to have variable width columns, and automatically calculate the number of columns based on the content (thus: wrapping).
Example below:
.cont {
display: flex;
flex-wrap: wrap;
width: 100%;
position: relative;
border: solid 1px red;
padding-left: -16px;
justify-content: 'center';
}
.cell {
min-width: 20%;
border: solid 1px black;
margin: 8px 16px 8px 0;
}
.wide2 {
min-width: calc(50% - 2px);
}
.wide {
width: calc(50% - 16px);
}
<div class="cont">
<div class="cell wide">
wide
</div>
<div class="cell">
test
</div>
<div class="cell">
test
</div>
<div class="cell">
test second line, should also have zero margin to left
</div>
</div>
<div class="cont">
<div class="cell wide">
wide
</div>
<div class="cell wide2">
this should line up,<br> iff margin right is no longer there
</div>
</div>
I believe this is currently not possible, and probably won't ever be.
You see, if you can have that selector, you'll be able to implement this:
.flexbox {
display: flex;
flex-wrap: wrap;
}
.flexbox .flex-item {
margin-left: 200px;
}
.flexbox .flex-item:first-of-flex-line {
margin-left: 0;
}
Notice that when margin-left: 0 of :first-of-flex-line cancels the margin-left: 20px rule, it can possibly make some items of the next line move up, almost like infinite loop. This would require iterative layouting, which seems unlikely to be implemented in browser as it is expensive rendering.

Stacking 3 elements both sides on window resize with CSS using inline, flex, float or whatever

I know there are many questions about this, the most of them says this is not possible because they ask about 1 method only, this question is about any method, I simply can't believe this is not possible with CSS.
I have 3 elements, 2 of them are stacked on the left and the other one is taller and his width fills the remaining space, when the screen goes smaller they stack, so the right element moves between first and last element:
I tried different methods like display:inline-block, float:left (and right), display:flex (and some flex properties) and even tables! I can not achieve it.
These are my 3 best attempts:
.test_inline div{display:inline-block;}
.test_inline .right{flex-grow:1; width: calc(100% - 130px);min-width:100px;}
.test_flex{display:flex;flex-wrap: wrap}
.test_flex .right{flex-grow:1; width: calc(100% - 130px);min-width:100px;}
.test_float .left{float:left;}
.test_float .right{display: flow-root;}
/* */
.main{ margin: 50px; }
div div{ border: 1px solid #333; }
.left{ width: 100px; }
.right{ height: 50px; }
<div class='main test_inline'>
<div class='left'>1 Top left</div>
<div class='right'>2 Right</div>
<div class='left'>3 Bottom Left</div>
</div>
<div class='main test_flex'>
<div class='left'>1 Top left</div>
<div class='right'>2 Right</div>
<div class='left'>3 Bottom Left</div>
</div>
<div class='main test_float'>
<div class='left'>1 Top left</div>
<div class='right'>2 Right</div>
<div class='left'>3 Bottom Left</div>
</div>
Thank you for your help!
I simply can't believe this is not possible with CSS.
It is possible. In fact, it's fairly simple with CSS Grid.
No need for floats, inline block, absolute positioning or even flex.
jsFiddle demo
.test_grid {
display: grid;
grid-template-columns: 150px 1fr;
grid-template-rows: 50px 50px;
grid-gap: 5px;
}
.right {
grid-row: span 2;
}
#media ( max-width: 600px) {
.test_grid {
grid-template-columns: 1fr;
grid-template-rows: 50px 50px 50px 50px;
}
}
/* */
.main {
margin: 50px;
}
div div {
border: 1px solid #333;
}
<div class='main test_grid'>
<div class='left'>1 Top left</div>
<div class='right'>2 Right</div>
<div class='left'>3 Bottom Left</div>
</div>
There's a few ways you can go about it #stamin. Ultimately I think you would need to know which side of the markup you want to determine the height of your UI though.
This positions the right element absolutely and uses flexbox for the left two. You could always do it the other way.
<div class="wrapper">
<div class="item one">Top Left</div>
<div class="item two">Right</div>
<div class="item three">Bottom Left</div>
</div>
CSS
.wrapper {
border: 1px solid green;
display: flex;
flex-wrap: wrap;
position: relative;
}
.item {
border: 1px solid red;
flex: 0 0 100%;
height: 100px;
}
.one,
.three {
text-align: left;
}
.two {
text-align: right;
}
#media (min-width: 768px) {
.wrapper {
padding-right: 50%;
}
.one,
.three {
float: left;
}
.two {
align-self: stretch;
position: absolute;
right: 0;
width: 50%;
height: 100%;
}
}
And here is a working example https://stackblitz.com/edit/css-reorder

CSS Flex dynamic grid with multiple sizes

I have a problem with flex.
I have a wrapper where a minimum of 1 and maximum of 9 squares can be shown. Squares can have multiple sizes, based on the number of squares in grid.
I've got all required cases working except for one, as seen in this picture:
My styles are:
.grid {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: space-between;
width: 300px;
height: 300px;
position: relative;
}
Plus. the images have sized based on the overall number of them and their position in a list.
So the problem is in situation when I have 1 big square (takes position of 4 small squares) and 5 small squares around him from right and bottom.
The big one is first as he should be.
Next to him (top right corner) is second one, that's also correct.
The third one is in bottom left corner, and it should be in the second line and on the far right. Because of this one, all the others are in wrong position, so the last one is overflowing.
I've tried a lot of value combinations for justify-content, align-content, align-items and align-self but nothing have worked.
I'll go back to ton of classes and position absolute solution, if there is no flex solution for this. But I don't like it. It's too much styles and it doesn't look good.
Any advice would be greatly appreciated.
I think float is a better option for you, check out this snippet:
.grid {
width: 300px;
}
.box {
background: orange;
width: 90px;
height: 90px;
margin: 5px;
float: left;
}
.wide {
width: 190px;
}
.tall {
height: 190px;
}
.empty {
background: transparent
}
/* you can ignore everything after this comment - it's all for illustration */
body {
background: #334;
color: white;
font-family: sans-serif;
}
.example {
display: inline-block;
margin: 5px;
border: 1px solid #445;
padding: 10px;
width: 300px;
}
h3 {
margin: 0 0 5px 0;
}
<div class="example">
<h3>Example 1</h3>
<div class="grid">
<div class="box wide tall"></div>
<div class="box tall empty"></div>
<div class="box wide empty"></div>
<div class="box"></div>
</div>
</div>
<div class="example">
<h3>Example 2</h3>
<div class="grid">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
<div class="example">
<h3>Example 4</h3>
<div class="grid">
<div class="box wide tall"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
Flex is still trying to make complete rows of elements, so your big square and your little square are part of one row; there's no support for stacking beyond that.
Float on the other hand tries to stuff elements wherever it can fit them.
EDIT
I've updated this answer with examples on how to reproduce most of the images above (I've purposefully left out the 2 by 2 example - didn't want to cloud the answer with classes for boxes of 1.5 height/width).
Use of an empty class to remove color from blocks, as well as classes tall and wide to fill in spots of all sizes should help you customize your layout however you see fit. One note - here empty sets the background color to transparent. Your empty class may do more or less than this. You may not even need an empty class if all it is is a div without content.
There is no way to handle this layout with flex in a single container.
You need to do a little trick to achieve it.
The easier one would be to take the third item out of the flex layout, positioning it absolute:
.grid {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: space-between;
width: 300px;
height: 300px;
position: relative;
}
.item {
background-color: lightblue;
width: 100px;
height: 100px;
margin: 0px;
border: transparent solid 5px;
box-sizing: border-box;
background-clip: content-box;
}
.item:first-child {
width: 200px;
height: 200px;
}
.item:nth-child(2) {
background-color: blue;
position: absolute;
top: 100px;
right: 0px;
}
<div class="grid">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Another posibility, may be more in the flex idea, but also tricky
Set the big element with a margin-bottom negative, that makes it occupy only 1 row (being the height of a row the size of the small boxes).
Now be have a layout with 3 rows. The problem will be that the 3rd box will be under the first, big box. To solve this, we are setting a pseudo element (I have styled the snippet to make it visible, in production just set it to height 0 and it will disappear) with the same properties of width and margin of the first element.
.grid {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
align-content: space-between;
width: 300px;
height: 300px;
position: relative;
}
.grid:after {
content: "";
order: 3;
background-color: red;
width: 190px;
height: 10px;
margin: 5px;
}
.item {
background-color: lightblue;
width: 90px;
height: 90px;
margin: 5px;
}
.item:first-child {
width: 190px;
height: 190px;
margin-bottom: -100px;
order: 1;
opacity: 0.5;
}
.item:nth-child(2) {
order: 2;
}
.item:nth-child(n+3) {
order: 4;
}
<div class="grid">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>

Flexbox: 3 divs, 2 columns

I'm new to flexbox, so please bear with me. My html:
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
With flexbox, I am trying to achieve the following layout:
.
What's the simplest way I can achieve this without setting a height for the container? .one is expected to change in height.
You can achieve this by setting flex-direction to column.
As requested, the width of the second div is static. I am using calc for the other 2 divs.
.container {
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 100px;
}
.one,
.three {
flex: 0 0 50%;
background: cyan;
width: calc(100% - 100px);
}
.two {
flex: 0 0 100%;
order: 1;
background: moccasin;
width: 100px;
}
.three {
background: tomato;
}
<div class="container">
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
</div>
EDIT .... Late answer , iI leave it since approach looks a little different from other even that it i think it very similar .. but not much choice about the way flex is working :)
you may need to set an height to parent container and childs on first column. order will organize the flow of containers.
codepen to check behavior and how it breaks while windows is reduced or content increased
.one {
background: #A1EB88;
}
.two {
background: #E7AAF6
}
.three {
background: #F7F467
}
.container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
height: 50vh;/* height is needed to force wrapping */
}
.one,
.three {
order: -1;/* bring them in front of other(s) */
height: 50%;/* share the height (if three of them, then put it down to 33.33% to share evenly height avalaible) */
}
.two {
flex: 1;/* equals height:100%; it will fill entire height */
width: 200px;/* here your fixed width */
}
<h1>test it also in full page mode </h1>
<div class="container">
<div class="one">one</div>
<div class="two">two</div>
<div class="three">three</div>
</div>

Resources