Centering a grid with flexbox changes grid structure - css

I am making a horizontal grid that contains 4 divs, I want the grid to be horizontally centered, so I wrap my grid container with another div so that it will act as a flexbox parent and try to center it (check the code below), while the grid has been centered the horizontal grid has now become a vertical grid
HTML:
<h2>My Simple Grid</h2>
<div class="grid-holder">
<div class="grid-container grid-container--fill">
<div class="grid-element">
1
</div>
<div class="grid-element">
2
</div>
<div class="grid-element">
3
</div>
<div class="grid-element">
4
</div>
</div>
</div>
CSS:
.grid-container {
display: grid;
}
.grid-container--fill {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
.grid-element {
background-color: darkGreen;
padding: 20px;
color: #fff;
border: 1px solid #fff;
}
.grid-holder{
display: flex;
flex-direction: column;
align-items: center;
}
body {
padding: 2em;
}
Current Result:
current result
Expected Outcome:
Grid elements 1,2,3,4 should remain horizontal while the grid-holder div remains centered, sorry for the bad drawing
my drawing of expected result
I also want to know why did I need to use flex-direction: column ? Am I making any silly mistake, or forgot the basics ? Thanks in advance.

After you added align-items: center; to your flex container grid-holder, And with grid-template-columns set to auto-fill for the class grid-container--fill many columns are implicitly created with each item to fill the whole row with as many columns as it can, then the elements will be centred but only one element will be shown in a row, To fix that change the auto-fill by 4 to precise the number of columns that should be displayed in each row as follow:
.grid-container {
display: grid;
}
.grid-container--fill {
grid-template-columns: repeat(4, minmax(100px, 1fr));
}
.grid-element {
background-color: darkGreen;
padding: 20px;
color: #fff;
border: 1px solid #fff;
}
.grid-holder{
display: flex;
flex-direction: column;
align-items: center;
}
body {
padding: 2em;
}
<h2>My Simple Grid</h2>
<div class="grid-holder">
<div class="grid-container grid-container--fill">
<div class="grid-element">
1
</div>
<div class="grid-element">
2
</div>
<div class="grid-element">
3
</div>
<div class="grid-element">
4
</div>
</div>
</div>

Related

How to get children with dynamic content centered AND the same width with flex?

Okay, so, I know this is a long shot, but you never know, so I'll ask anyway.
I have a flex container that display 4 items which contents are dynamically generated (picked in a database). Which means I don't know what's inside of them. I just know it's some text with a certain maximum length. So I basically have something like this :
#container {
display: flex;
justify-content: center;
}
.item {
margin: 0 5px;
background-color: yellow;
}
<div id="container">
<div class="item">Content</div>
<div class="item">Long item content</div>
<div class="item">Short</div>
<div class="item">Other content</div>
</div>
What I'd like would be for all the items to be the same size, which would be the size of the biggest of them (here the second one) to have something like this :
#container {
position: absolute;
display: flex;
justify-content: center;
width: 85%;
left: 50%;
transform: translateX(-50%);
}
.item {
margin: 0 5px;
background-color: yellow;
flex: 1 1 0;
text-align: center;
}
<div id="container">
<div class="item">Content</div>
<div class="item">Long item content</div>
<div class="item">Short</div>
<div class="item">Other content</div>
</div>
but of course, without fiddling the container's width and position. I'd like the container to be 100% width, and the children to adapt their size to get this rendering.
Does anyone knows a way to do this?
I work with Angular, by the way.
Thanks a lot.
Have you considered using display: grid instead?
#container {
display: grid;
grid-template-columns: repeat(4, 1fr);
grid-column-gap: 4px;
grid-row-gap: 4px;
}
.item {
padding: 4px;
background-color: #aaaa00;
text-align: center;
}
<div id="container">
<div class="item">Content</div>
<div class="item">Long item content</div>
<div class="item">Short</div>
<div class="item">Other content</div>
<div class="item">fifth element</div>
</div>
Added fifth element to show that grid layout is honored by further elements.

Filling cells starting from the bottom in CSS Grid

I have a CSSĀ grid with 3 rows. There may be less than 3 items to fill it, and I want to start filling it from the bottom.
I've created a jsFiddle for you to play with, but it currently fails to do what I want.
html, body, div {
height: 100%;
}
div {
display: grid;
grid-template-columns: 1;
grid-template-rows: repeat(3, 1fr);
/* MISSING RULE */
}
<div>
<p>Last item</p>
<p>Second last item</p>
<p>Top item</p>
</div>
Actual output:
Last item
Second last item
Top item
Desired output:
Top item
Second last item
Last item
I'd like to apply one rule to the <div> that contains the grid, rather than separate rules to the items in the grid, if that is possible.
There is no column-reverse function in CSS Grid, like there is in flexbox.
Therefore, getting grid areas to populate a container starting from the bottom isn't possible with a single rule in the container.
Here's how it would work in flexbox:
div {
display: flex;
flex-direction: column-reverse;
height: 100vh;
}
p {
flex: 1;
}
/* demo styles */
p {
margin: 0;
background-color: lightgreen;
}
p + p {
margin-bottom: 10px;
}
body {
margin: 0;
}
<div>
<p>Last item</p>
<p>Second last item</p>
<p>Top item</p>
</div>
If you want to use CSS Grid layout it will be like this. I modify your HTML. You have to write CSS property for grid child item where to start and where to end. grid-row-start: and grid-row-end:. Here is a CodePen.
.grid-item{
border: 2px solid red;
border-radius: 5px;
height: 200px;
padding: 10px;
width: 300px;
margin-left: auto;
margin-right: auto;
display: grid;
grid-template-columns: 1fr;
grid-template-rows: repeat(3, 1fr);
}
.grid-item p{
margin: 0;
}
.grid-item .first-item{
grid-row-start: 1;
}
.grid-item .last-item{
grid-row-start: 3;
}
<div class="grid-item">
<p class="last-item">Last item</p>
<p class="second-item">Second last item</p>
<p class="first-item">Top item</p>
</div>
If you want to use flexbox it will be using two line code.
<div>
<p>Last item</p>
<p>Second last item</p>
<p>Top item</p>
</div>
CSS for this
div{
display: flex;
flex-direction: column-reverse;
}
The flex-direction CSS property sets how flex items are placed in the flex container defining the main axis and the direction (normal or reversed).

Keep wrapped flex items on left while others centred

I'm trying to display a list of flex items with fixed width in the center of flexbox with wrap by using margin: auto. When wrap happens, the wrapped item also centers in its own container:
Is there a way to keep the wrapped item on the left while everything else is centred?
.parent {
display: flex;
flex-wrap: wrap;
height: 100px;
}
.children {
flex: 1;
border: 1px solid black;
max-width: 300px;
min-width: 300px;
margin: auto;
height: 100px;
margin-top: 1rem;
}
<div class="parent">
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
</div>
You're saying you want the items centered, but when there is only one item that wraps, you want it left-aligned.
The problem is that there is really no left-alignment in the flex container. Everything is centered, based on available space in the row. So the single item in the last row has no concept of what's going on above, and nothing to align with.
Here's what happens if you left-align the last item (on wider screens):
.parent {
display: flex;
flex-wrap: wrap;
}
.children {
border: 1px solid black;
max-width: 300px;
min-width: 300px;
margin: auto;
height: 100px;
margin-top: 1rem;
}
.children:last-child {
margin-left: 0;
}
<div class="parent">
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
</div>
What you need is a nested grid structure.
A top-level grid to establish the centering.
A nested grid for the wrapping.
In the demo below, you'll find a three-column grid. The left and right columns are empty (spacer) items, created with CSS pseudo-elements, and set to equal widths. This centers the middle item.
The middle item is also a grid container. Using the repeat() and auto-fill functions, the items can wrap, with individual items aligning left.
body {
display: grid;
grid-template-columns: auto 1fr auto;
}
body::before,
body::after {
content: ''; /* in grid (and flex) layouts, pseudo-elements on the container
are treated as items */
}
.parent {
display: grid;
grid-template-columns: repeat(auto-fill, 300px);
grid-auto-rows: 100px;
grid-gap: 10px;
justify-content: center; /* centers the columns (not the items, like in flex) */
}
.children {
border: 1px solid black;
}
<div class="parent">
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
<div class="children"></div>
</div>
jsFiddle demo

Can't get flex box items to wrap in 2 columns set-up [duplicate]

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>

Flex two rows to align at the bottom without centering according to space

I need to make two rows align to the bottom, without using the rest of the space to vertically align the first row.
When I only have one row it works great, but when I add another row, the first row will align vertically to make it use the rest of the space.
Basically I want the two rows to be at the bottom, because then they will align with the ones in the other containers, and make it look uniform.
The title can vary in length, so the boxes inside the content, must always flow to the bottom so they always will align.
See the picture here:
Example on jsFiddle: http://jsfiddle.net/zv56fak7/2/
Here it shows two rows in one line, and these should be on seperate lines, and both be aligned to the bottom without any spacing between them.
I tried to make the 'my-flex-item-content-box' inside separate rows, but it didn't work.
So I want it as shown at the picture, but just that all the oranges rows should be aligned to the bottom.
Sample code:
.my-flex-container {
display: flex;
flex-wrap: wrap;
}
.my-flex-item-wrapper {
width: 33%;
padding: 5px;
display: flex;
}
.my-flex-item {
border: 1px solid gray;
flex: 1;
display: flex;
flex-direction: column;
}
.my-flex-item-header {
font-size: 2.5em;
background-color: #f5f5f5;
border-bottom: 1px solid gray;
}
.my-flex-item-content {
align-items: baseline;
align-items: flex-end;
background-color: rebeccapurple;
display: flex;
flex-wrap: wrap;
flex-grow: inherit;
}
.my-flex-row {
display: flex;
flex: 1;
}
.my-flex-item-content-box {
width: 33.33%;
min-height: 100px;
color: white;
background-color: purple;
background-color: orange;
}
<div class="my-flex-item-wrapper">
<div class="my-flex-item">
<div class="my-flex-item-header">
Queen and Adam Lambert 4th July Ultimate On Stage Experience
</div>
<div class="my-flex-item-content">
<div class="my-flex-row">
<div class="my-flex-item-content-box">
Content box
</div>
<div class="my-flex-item-content-box">
Content box
</div>
<div class="my-flex-item-content-box">
Content box
</div>
</div>
<div class="my-flex-row">
<div class="my-flex-item-content-box">
Content box
</div>
<div class="my-flex-item-content-box">
Content box
</div>
<div class="my-flex-item-content-box">
Content box
</div>
</div>
</div>
</div>
</div>
I figured it out.
Setting '.my-flex-row' with 'with:100%;' and 'flex-basis: auto;', it gives me a row with only 3 items inside as desired.
Setting '.my-flex-item-content' with 'align-content: flex-end;' there is no spacing.
Rows without any spacing between is working nicely
You should remove the flex-grow property from .my-flex-item-content and add margin-top:auto;. http://jsfiddle.net/zv56fak7/13/
.my-flex-item-content {
margin-top:auto;
align-items: baseline;
align-items: flex-end;
background-color: rebeccapurple;
display: flex;
flex-wrap: wrap;
}
Also mind the padding and box-sizing if that is an issue
.my-flex-item-wrapper {
width: 33%;
padding: 5px;
display: flex;
box-sizing:border-box;
}

Resources