This question already has answers here:
Targeting flex items on the last or specific row
(10 answers)
Closed 4 years ago.
I have a simple grid here using css flex.
I need the 3 columns that are a percentage of the parent container width.
I also need a right margin on each block.
I nearly have it working here but I need the blocks in the second line to go from left to right, here the second block on the second row is on the right.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
justify-content: space-between;
//justify-content: flex-start;
}
.block__item {
//align-self: flex-start;
background: grey;
height: 20px;
//margin-right: 8px;
margin-bottom: 2px;
width: calc(33.3% - 2px);
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
You were on the right track originally with using justify-content: flex-start. It was justify-content: space-between that was giving you the gap on the second row, so I removed that and everything lined up. I adjusted the margins and padding too to match the spacing.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px 3px 5px 5px;
max-width: 900px;
justify-content: flex-start;
}
.block__item {
background: grey;
height: 20px;
margin-bottom: 2px;
width: calc(33.3% - 2px);
margin-right:2px;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
Another way to think about it is to use a wrapping element (.block__item) that provides the spacing between elements with internal padding. These wrapping elements are physically next to each other but provide the visual distinction between their contents (.block__content).
The benefit of this is that you don't need to include the spacing in your calculations for width or flex-basis. If you want to change the spacing, simply update padding.
*Note that you need to change the box-model of your elements to border-box to take advantage of this.
* {
box-sizing: border-box;
}
.block {
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
max-width: 900px;
border: 1px solid lightgrey;
padding: 2px;
}
.block__item {
flex: 0 1 calc(100% / 3);
padding: 2px;
}
.block__content {
height: 20px;
background-color: grey;
color: white;
font-size: 10px;
font-weight: 700;
line-height: 20px;
text-align: center;
}
#media (max-width: 400px) {
.block__item {
flex-basis: 50%;
}
}
<div class="block">
<div class="block__item">
<div class="block__content">1</div>
</div>
<div class="block__item">
<div class="block__content">2</div>
</div>
<div class="block__item">
<div class="block__content">3</div>
</div>
<div class="block__item">
<div class="block__content">4</div>
</div>
<div class="block__item">
<div class="block__content">5</div>
</div>
</div>
You could reduce the margins a bit so they fit better and keep aligning flex items to the left with justify-content: flex-start; or you could also use CSS Grid instead and define the gap you need as well as the total columns you need (3 in this case), with grid you can even avoid percentage calculations and just tell each item to use a fraction of the available space.
The biggest benefit of CSS Grid I think would be that you avoid wasting space that might be left out with percentages, and also you don't need to change anything else on the items if you want to add or remove columns.
.block {
border: 1px solid lightgrey;
display: flex;
flex-wrap: wrap;
padding: 5px;
max-width: 900px;
justify-content: flex-start;
}
.block__item {
background: grey;
height: 20px;
margin-right: 2px;
margin-bottom: 2px;
width: calc(33.3% - 2px);
}
.block-grid{
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: minmax(20px, auto);
grid-gap: 2px;
border: 1px solid grey;
padding: 5px;
}
.block-grid__item{
background-color: red;
}
<div class="block">
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
<div class="block__item"></div>
</div>
<div class="block-grid">
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
<div class="block-grid__item"></div>
</div>
Related
I want to created a wrapper component in React, which take a children items, and the wrapper should only show three items per row (inputs, checkboxes, whatever).
And also for bigger screens the cells should not stretch, and items have to be grouped tightly. But when the screen shrinks, items have to wrap and change number of columns.
That's how it should be for bigger screens:
I thought css grid perfectly fits, but I can't find the proper way to do so.
Since you don't have any code shared, this is difficult to answer because we have no reference/starting point of where you are at.
Here is a blitz I put together for you showing a few ways to achieve what I think you need.
EDIT: Here is a snippet of the three options I included.
Option 1: Limit the number of children per parent. Then you can add a flexbox to the parent to control wrapping. Repeat this for how ever many you need.
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div> //repeat
Option 2: Flex Basis
<div class="parent2">
<div class="child2">
<div class="grandchild"></div>
</div>
<div class="child2">
<div class="grandchild"></div>
</div>
</div> // Put your data inside the grandchild component and add a flex basis to the child component
Option 3: Flex and Position
<div class="parent3">
<div class="child3">
<h2>1 </h2>
</div>
<div class="child3">
<h2>2</h2>
</div>
<div class="child3">
<h2>3</h2>
</div>
<div class="spacing"></div>
<div class="child3">
<h2>4 </h2>
</div>
<div class="child3">
<h2>5</h2>
</div>
<div class="child3">
<h2>6</h2>
</div>
</div>
Here are all the styles I used
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: 10px;
}
.child {
background: blue;
margin: 10px 0 0 10px;
height: 100px;
width: 100px;
}
/* ....................................... */
.parent2 {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: 10px;
}
.child2 {
flex-basis: 30%;
background: lightblue;
margin: 10px 0 0 10px;
height: 100px;
width: 100px;
}
.grandchild {
border: 3px solid red;
height: 50px;
width: 50px;
}
/* ....................................... */
.parent3 {
width: 100%;
min-height: 100px;
height: auto;
display: flex;
justify-content: flex-start;
flex-wrap: wrap;
}
.child3 {
width: 100px;
height: 100px;
background-color: lightgreen;
margin: 10px;
position: relative;
}
.spacing {
width: 100%;
height: 5%;
}
This question already has an answer here:
How to exclude the first item in a flexbox wrap?
(1 answer)
Closed 2 years ago.
Using Flex how can i create a layout , that has main parent div (container , display:flex) set.
The div1 to be in horizontal
div 2 and div 3 to be vertical as seen in the image.
I am new to flex and still learning
You can Achieve this even without flex, But if you need to do all the 3 div with flex then you can use this.
Here we put all the div in one contaner called main. And then we use flex property to make it a row. and then use flex-wrap to break apart. and then we give 100% to the first div as you wanted that in full width
HTML
<div id="main">
<div style="background-color:coral;" id="one">RED</div>
<div style="background-color:lightblue;">BLUE</div>
<div style="background-color:lightgreen;">Green div with more content.</div>
</div>
CSS
#main {
width: 100%;
height: 300px;
border: 1px solid black;
display: flex;
flex-wrap:wrap;
}
div{
width:200px;
}
#one{
flex:100%;
}
You can do something like this:
#MainDiv {
border: 1px solid black;
display: flex;
flex-direction: column;
height: 500px;
width: 700px;
}
.Column {
border: 1px solid red;
height: 30px;
margin: 10px;
}
.Rows {
display: flex;
flex-direction: row;
height: 450px;
width: 650px;
border: 1px solid teal;
margin: 10px;
}
.row {
height: 400px;
width: 300px;
border: 1px solid red;
margin: 10px;
}
<div id="MainDiv">
<div class="Column">Horizontal </div>
<div class="Rows">
<div class="row">Vertical Left</div>
<div class="row">Vertical Right</div>
</div>
</div>
You can use flex: 1 without specifying size in pixel for each box
.row {
display: flex;
flex-direction: row;
width: 100%;
}
.col {
border: 1px solid red;
flex: 1;
}
<div class="row">
<div class="col">One</div>
</div>
<div class="row">
<div class="col">Two</div>
<div class="col">Three</div>
</div>
This question already has answers here:
CSS3 box-sizing property
(5 answers)
Closed 4 years ago.
I know this question has been asked several times and the solution is flex-wrap: wrap but for some reason this doesnt work in my code.
Could anyone briefly help me why my divs aren't wrapping?
I basically need always 2 divs next to eachother in a row and then to wrap.
JSFIDDLE: enter link description here
.wrapper {
display: flex;
display: -ms-flexbox;
display: -webkit-flex;
display: -moz-box;
flex-wrap: wrap;
}
.box {
flex: 50%;
text-align: center;
padding-bottom: 10px;
color: #8988DB;
flex-wrap: wrap;
border: 1px solid black;
}
<div class="wrapper">
<div class="box"><br>Valerian Root</div>
<div class="box"><br>Lavender</div>
<div class="box"><br>Lemon Balm</div>
<div class="box"><br>Chamomile</div>
<div class="box"><br>Passion Flower</div>
<div class="box"><br>Hops</div>
<div class="box"><br>Rooibos</div>
<div class="box"><br>Cinnamon</div>
</div>
Thanks so much!
Alpha
As a note, in the CSS rule for the flex container, place the regular display: flex property after all the prefix-versions.
For it to work also in IE11, use width: 50% instead of flex: 50%, combined with box-sizing: border-box, where borders/padding gets included in the set width.
.wrapper {
display: -ms-flexbox;
display: -webkit-flex;
display: -moz-box;
display: flex;
flex-wrap: wrap;
}
.box {
box-sizing: border-box;
width: 50%;
padding: 0 30px 10px;
text-align: center;
color: #8988DB;
border: 1px solid black;
}
<div class="wrapper">
<div class="box"><br>Valerian Root</div>
<div class="box"><br>Lavender</div>
<div class="box"><br>Lemon Balm</div>
<div class="box"><br>Chamomile</div>
<div class="box"><br>Passion Flower</div>
<div class="box"><br>Hops</div>
<div class="box"><br>Rooibos</div>
<div class="box"><br>Cinnamon</div>
</div>
Step into CSS Grid, it's ideal for this use case. Your use case is so simple, you only need three lines of CSS to pull it off.
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr; // creates two responsive columns
grid-gap: 10px; // puts 10px between each node in the grid
}
Looks like all you need is a proper CSS reset, specifically, the box-sizing property so that borders are not included in the width calculations.
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wrapper {
display: flex;
flex-wrap: wrap;
}
.box {
flex: 50%;
text-align: center;
padding-bottom: 10px;
color: #8988DB;
border: 1px solid black;
}
<div class="wrapper">
<div class="box"><br>Valerian Root</div>
<div class="box"><br>Lavender</div>
<div class="box"><br>Lemon Balm</div>
<div class="box"><br>Chamomile</div>
<div class="box"><br>Passion Flower</div>
<div class="box"><br>Hops</div>
<div class="box"><br>Rooibos</div>
<div class="box"><br>Cinnamon</div>
</div>
I'm trying to make my css with flexbox, so I followed some articles and tried to set my elements like this example:
the elements 1 & 2 are in another container
I'm trying to set the two elements (1 and 3) to be next each other as the second example (The first is what I have now and the other is what I'm trying to achieve.)
but I can't find a good way with the Flexbox since I set the container to flex-direction: column;
<div class="container">
<div class="sub-ctn">
<h5 class="1"><span>♦ </span>{{ text }}</h5>
<span class="2">{{ value }}</span>
<div class="3">
<h5>{{ text }}
</div>
</div>
</div>
CSS:
.container {
margin-right: 2.5%;
direction: rtl;
}
.sub-ctn {
display: flex;
flex-flow: row;
margin-top: 1%;
flex-direction: column;
}
.1 {
width: 100%;
direction: rtl;
text-align: right;
}
.2 {
float: right;
/* text-align: right; */
}
.3 {
margin-left: 1%;
display: flex;
flex-direction: column;
}
let me know if another information is needed
Don't use float and flex together. Flex alone will be much easier and better.
.cont{
display: flex;
width: 80%;
border: 1px solid black;
padding: 10px;
}
.left-cont{
height: 100%;
flex-grow: 1;
}
.right-cont{
flex-grow: 1;
display: flex;
flex-direction: column;
}
.item{
text-align: center;
border: 1px solid black;
margin: 3px;
}
<div class="cont">
<div class="left-cont">
<div class="item">3</div>
</div>
<div class="right-cont">
<div class="item">1</div>
<div class="item">2</div>
</div>
</div>
I've been working on learning flexbox for layout and have been unable to figure out why text is not wrapping inside the flex-item. The text is breaking out of the container like this:
html,
body {
height: 100%;
}
.main {
max-width: 10em;
margin: 1em auto;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
min-height: 12em;
border: 1px solid red;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-item {
padding: 5px;
border: 1px solid black;
}
<div class="main">
<div class="flex-row">
<div class="flex-column">
<div class="flex-item">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="flex-item">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
</div>
</div>
</div>
</div>
There are no spaces between your text.
The default value of the word-break property is normal, meaning that a continuous line of text has no line breaks.
For these reasons, your text is not wrapping and overflowing the container.
Add word-break: break-all to .flex-item.
html,
body {
height: 100%;
}
.main {
max-width: 10em;
margin: 1em auto;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
min-height: 12em;
border: 1px solid red;
}
.flex-column {
display: flex;
flex-direction: column;
}
.flex-item {
padding: 5px;
border: 1px solid black;
word-break: break-all; /* new */
}
<div class="main">
<div class="flex-row">
<div class="flex-column">
<div class="flex-item">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="flex-item">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
</div>
</div>
</div>
</div>
From MDN:
word-break
The word-break CSS property specifies whether or not the browser
should insert line breaks wherever the text would otherwise overflow
its content box.
In contrast to overflow-wrap, word-break will create a break at
the exact place where text would otherwise overflow its container
(even if putting an entire word on its own line would negate the need
for a break).
Values
normal
Use the default line break rule.
break-all
To prevent overflow, word breaks should be inserted between any two
characters (excluding Chinese/Japanese/Korean text).
keep-all
Word breaks should not be used for Chinese/Japanese/Korean (CJK) text.
Non-CJK text behavior is the same as for normal.
There's actually another reason – flexbox-specific – why the flex items are overflowing the container. Here's the explanation:
Why doesn't flex item shrink past content size?
To contain the items (without the need for the text to wrap), you could apply min-width: 0, overflow: hidden or overflow: auto to .flex-column.
html,
body {
height: 100%;
}
.main {
max-width: 10em;
margin: 1em auto;
}
.flex-row {
display: flex;
align-items: center;
justify-content: center;
min-height: 12em;
border: 1px solid red;
}
.flex-column {
display: flex;
flex-direction: column;
overflow: hidden; /* new */
/* overflow: auto; */
/* min-width: 0; */
}
.flex-item {
padding: 5px;
border: 1px solid black;
}
<div class="main">
<div class="flex-row">
<div class="flex-column">
<div class="flex-item">
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
</div>
<div class="flex-item">
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
</div>
</div>
</div>
</div>