Layout gap/margin center two last elements with flex-wrap - css

I have issues with a layout where I want to center the last two elements on a row. First I tried with grid and couldn't find any proper solution so I found a way to solve it with "flex-wrap" and it looks pretty good.
The issue I'm facing now is with the gap/margin. I can't find any good solution while I'm setting the width to 33,33%.
Is there any other good way to solve this? I'm kind of stuck and have been looking at this for hours now :) (see layout attached image)
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
flex-direction: column;
}
#media only screen and (min-width: 640px) {
#container {
display: flex;
flex-wrap: wrap;
justify-content: center;
flex-direction: row
}
}
.item {
width: 100%;
background: teal;
color: white;
border-radius: 10px;
text-align: center;
}
#media only screen and (min-width: 640px) {
.item {
width: 33.33%;
}
}
<div id="container">
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
</div>;

You can use the gap parameter, see the example below.
Update:
Solution 1
Stretched Last element
#container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 20px;
}
.item {
width: 100%;
background: teal;
color: white;
border-radius: 10px;
text-align: center;
}
/* Start Media Query*/
#media only screen and (min-width: 640px) {
#container {
display: flex;
justify-content: center;
flex-direction: row;
}
.item {
flex: 1 1 30%;
}
} /* End Media Query*/
<div id="container">
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
</div>
Solution 2
Not stretched last element
#container {
display: flex;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 20px;
}
.item {
width: 100%;
background: teal;
color: white;
border-radius: 10px;
text-align: center;
}
/* Start Media Query*/
#media only screen and (min-width: 640px) {
#container {
display: flex;
justify-content: center;
flex-direction: row;
}
.item {
flex: 0 0 calc(33.33% - 15px);
}
} /* End Media Query*/
<div id="container">
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
<div class="item">
<p>Item</p>
</div>
</div>

Related

Jutifying content in flex after wrap

I'm having a situation where I'm having a page title on the left side and rating number and stars on the right side. I'm trying to align all items centered once flexbox wraps. Once "Longer Page Title" reaches rating and stars and flexbox wraps, they should all be center aligned.
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
.title,
.ratings-and-stars {
border: 3px solid red;
}
.ratings-and-stars {
text-align: right;
}
<div class="flex-container">
<div class="title">Longer Page Title</div>
<div class="ratings-and-stars">
<div class="ratings">10</div>
<div class="stars">**********</div>
</div>
</div>
EDIT: I need to horizontally center content on mobile once flexbox wraps
The closest to your description i can think about is to play with margin & text-align and flex-grow for the title.
Below is an average demo.
However , you will need a mediaquerie set at a fixed breakpoint to decide when to wrap. See second snippet for a possible option
.flex-container {
display: flex;
flex-wrap: wrap;
}
.title {
flex: 1;
}
.title,
.ratings-and-stars {
border: 3px solid red;
margin: auto;
text-align:center;
text-align-last:left;
}
.ratings-and-stars {
text-align: right;
}
<div class="flex-container">
<div class="title">Longer Page Title ////////////////////long_string_for_demo\\\\\\\\\\\\\\\\\\\\\\\\ .</div>
<div class="ratings-and-stars">
<div class="ratings">10</div>
<div class="stars">**********</div>
</div>
</div>
Compromise with a mediaquerie (here set at 600px, use your own breakpoint)
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
text-align: center;
}
.title,
.ratings-and-stars {
border: 3px solid red;
}
.ratings-and-stars {
text-align: right;
}
#media (max-width:600px) {
.title {
min-width: 100%;
}
.flex-container {
justify-content: center;
}
}
<div class="flex-container">
<div class="title">Longer Page Title</div>
<div class="ratings-and-stars">
<div class="ratings">10</div>
<div class="stars">**********</div>
</div>
</div>
white-space is also a possibility for an average result:
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content:center;
}
.title {
white-space:prewrap;
margin:auto auto auto 0;
}
.title,
.ratings-and-stars {
border: 3px solid red;
text-align:center;
}
.ratings-and-stars {
text-align: right;
}
<div class="flex-container">
<div class="title">Longer Page Title //////////////////// long_string_for_demo \\\\\\\\\\\\\\\\\\\\\\\\ .</div>
<div class="ratings-and-stars">
<div class="ratings">10</div>
<div class="stars">**********</div>
</div>
</div>
You are missing align-items: center more info
.flex-container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center
}
.title,
.ratings-and-stars {
border: 3px solid red;
}
.ratings-and-stars {
text-align: right;
}
<div class="flex-container">
<div class="title">Longer Page Title</div>
<div class="ratings-and-stars">
<div class="ratings">10</div>
<div class="stars">**********</div>
</div>
</div>

Display flex alignment incorrect in Chrome, Safari and Edge, but correct in Firefox

I have a div using the display flex method that contains other divs also using display flex to get the proper alignment that I want. I usually develop my web pages using Firefox and then later test them with other browsers to see if they work/display correctly there too.
I want to have a super-container that arranges its items in a normal flow. These items contains two images. These images are placed next to each other, and only their widths are fixed. The heights may differ per item. Below these two images I place a bit of text. All items are aligned such, that the first line of the texts are aligned with each other. The images should be placed in the horizontal middle of the item.
The following image shows how I want it to be displayed:
Firefox correct display. In Chrome and Edge (and Safari on iOS), the image looks like this: Incorrect display.
I have the following HTML and CSS:
.CompleteContainer
{
align-items: baseline;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
width: 300px;
}
.ItemContainer
{
align-items: center;
background-color: aqua;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
margin: 0 0 5px 10px;
width: 130px;
}
.ItemTopContainer
{
display: flex;
justify-content: space-between;
width: 100%;
}
.ItemTopLeftContainer
{
align-items: flex-end;
background-color: #ff8888;
display: flex;
justify-content: flex-end;
width: calc(50% - 2px);
}
.ItemTopLeft
{
background-color: #ff0000;
height: 50px;
width: 50px;
}
.ItemTopRightContainer
{
align-items: flex-end;
background-color: #88ff88;
display: flex;
justify-content: flex-start;
width: calc(50% - 2px);
}
.ItemTopRight
{
background-color: #00aa00;
height: 25px;
width: 50px;
}
.ItemBottomContainer
{
text-align: center;
}
<div class="CompleteContainer">
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Foo bar
</div>
</div>
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Foo bar, lorum ipsum
</div>
</div>
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Lorum ipsum
</div>
</div>
</div>
What am I doing wrong or what am I missing to get the display in Chrome and Edge the same as in Firefox? To be clear: in Firefox the above code snippet gives the results I want, in Chrome and Edge (and Safari on iOS) they are wrong.
UPDATE: I am not yet allowed to comment on the answers directly, but I will do it this way. Both the answers did point me in the correct direction, though they did not produce the correct results I wanted. I have updated the code in this question to reflect the changes in CSS to create the layout I want.
I have adjusted your code below and included documentation in the source. Taken out the floats. Please note floats do not work inside a flexbox.
.CompleteContainer
{
align-items: baseline;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
width: 300px;
}
.ItemContainer
{
align-items: center;
background-color: aqua;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
margin: 0 0 5px 10px;
width: 130px;
}
.ItemTopContainer
{
width: 100%;
display: flex; /* Added */
}
.ItemTopLeftContainer
{
align-items: flex-end;
display: flex;
height: 100%;
/* justify-content: right; "right" does not exist. */
width: calc(50% - 2px);
}
.ItemTopLeft
{
background-color: red;
height: 50px;
width: 50px;
}
.ItemTopRightContainer
{
align-self: flex-end; /* Replacing align-items */
/* Not necessary
display: flex;
height: 100%;
justify-content: left;
*/
width: calc(50% - 2px);
}
.ItemTopRight
{
background-color: green;
height: 25px;
width: 50px;
}
.ItemBottomContainer
{
text-align: center;
}
<div class="CompleteContainer">
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Foo bar
</div>
</div>
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Foo bar, lorum ipsum
</div>
</div>
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Lorum ipsum
</div>
</div>
</div>
.CompleteContainer
{
align-items: baseline;
display: flex;
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
width: 300px;
}
.ItemContainer
{
align-items: center;
background-color: aqua;
display: flex;
flex-direction: column;
flex-wrap: nowrap;
margin: 0 0 5px 10px;
width: 130px;
}
.ItemTopContainer
{
width: 100%;
display: flex;
align-items: center;
}
.ItemTopLeftContainer
{
align-items: flex-end;
display: flex;
float: left;
height: 100%;
justify-content: right;
width: calc(50% - 2px);
}
.ItemTopLeft
{
background-color: red;
height: 50px;
width: 50px;
}
.ItemTopRightContainer
{
align-items: flex-end;
display: flex;
float: right;
height: 100%;
justify-content: left;
width: calc(50% - 2px);
}
.ItemTopRight
{
background-color: green;
height: 25px;
width: 50px;
}
.ItemBottomContainer
{
text-align: center;
}
<div class="CompleteContainer">
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Foo bar
</div>
</div>
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Foo bar, lorum ipsum
</div>
</div>
<div class="ItemContainer">
<div class="ItemTopContainer">
<div class="ItemTopLeftContainer">
<div class="ItemTopLeft">
</div>
</div>
<div class="ItemTopRightContainer">
<div class="ItemTopRight">
</div>
</div>
</div>
<div class="ItemBottomContainer">
Lorum ipsum
</div>
</div>
</div>

Flex Flexbox, Push right, Align Left and different widths

left side Easy, is done.
but what about right section RESPONSIVE PUSHED right but align left, small box included.. see the image:
Any flexbox easy idea?
Try this:
.container {
display: flex;
justify-content: space-between;
}
.container > div {
display: flex;
flex-direction: column;
}
.right {
align-items: flex-start;
}
.left {
align-items: flex-end;
}
.box {
height: 40px;
width: 100px;
border: 1px solid blue;
margin-bottom: 5px;
}
.wide {
width: 200px;
}
<div class="container">
<div class="left">
<div class="box wide"></div>
<div class="box"></div>
</div>
<div class="right">
<div class="box wide"></div>
<div class="box"></div>
</div>
</div>

flexbox vertical align child top, center another

I've got the following markup:
.row {
display: flex;
align-items: stretch;
margin: -16px;
background: #ddd;
}
.row .col {
display: flex;
flex-direction: column;
justify-content: center;
flex: 1;
margin: 16px;
background: #fff;
}
.header, .content, .footer {
padding: 16px;
background: red;
}
<div class="row">
<div class="col">
<div class="header">Header #1</div>
<div class="content">Lorem Ipsum<br />Dolor<br />Sit Amet</div>
<div class="footer">Footer</div>
</div>
<div class="col">
<div class="header">Header #2</div>
<div class="content">Lorem Ipsum<br />Dolor</div>
</div>
</div>
Unfortunatly the second header isn't align vertically to the top. Is there a way to archive this with flexbox? I need the ".header" to be aligned the the top and the ".content" to be centered within the rest of the box.
Greetings!
No, not really, not without another wrapper which is a flex-container.
As flexbox is, to a certain extent based on manipulting margins, there is no method (AFAIK, although I'd be interested to find out if there is) to justify-content: center and then align-self a child element to somewhere else other than center.
I'd go with something like this: Add a wrapper to the "content" div, give it flex:1 to fill the remaining space below the header, then make that wrapper display:flex with justify-content:center.
This seems to be the most logical method
.col {
height: 150px;
width: 80%;
margin: 1em auto;
border: 1px solid grey;
display: flex;
flex-direction: column;
}
.header {
background: lightblue;
}
.content {
background: orange;
}
.flexy {
flex: 1;
display: flex;
flex-direction: column;
justify-content: center;
background: plum;
}
<div class="col">
<div class="header">Header #2</div>
<div class="flexy">
<div class="content">Lorem Ipsum
<br />Dolor</div>
</div>
</div>
Codepen Demo
Flexbox opens up all sorts of opportunities with margin: auto; this is one of them. Setting margin to auto along the flex axis (vertical in this case) will absorb any extra space before dividing it up between the flex items. Finally it's possible to vertically center stuff without creating a div soup.
.row {
display: flex;
align-items: stretch;
margin: -16px;
background: #ddd;
}
.row .col {
display: flex;
flex-direction: column;
flex: 1;
margin: 16px;
background: #fff;
}
.header, .content, .footer {
padding: 16px;
background: red;
}
.content {
margin-top: auto;
margin-bottom: auto;
}
<div class="row">
<div class="col">
<div class="header">Header #1</div>
<div class="content">Lorem Ipsum<br />Dolor<br />Sit Amet</div>
<div class="footer">Footer</div>
</div>
<div class="col">
<div class="header">Header #2</div>
<div class="content">Lorem Ipsum<br />Dolor</div>
</div>
</div>

Reorder columns in reverse order

I have a list of flex items within a flexbox. The order of the items matter, and for accessibility purposes, the items need to show up in the correct order in the dom.
[[itema][itemb][itemc]]
When the flexbox shrinks I would like to have the items wrap in reverse order, e.g. itema wraps first, etc. Is there any way to have the itema wrap first? Thanks!
Edit:
Here is the code
<div class="flex">
<div class="container">
<div class="item">item1</div>
<div class="item orange">item2</div>
<div class="item blue">item3</div>
</div>
<div class="last-item green">menu</div>
</div>
.flex {
display: flex;
background-color: yellow;
height: 80px;
overflow: hidden;
color: #fff;
}
.container {
display: flex;
flex: 1 1 auto;
flex-wrap: wrap;
}
.item {
flex: 0 0 auto;
background-color: red;
height: 80px;
padding: 0 40px;
}
.last-item {
width: 40px;
flex: 0 0 auto;
height: 80px;
}
JSFiddle
All the behavior is as desired except I want the first item to wrap first. Any ideas? Thanks!
You can use the flex-direction: column-reverse to get your solution.
#media (max-width: 768px) {
.flex-box {
display: flex;
flex-direction: column-reverse;
}
}
.first,
.second,
.third {
display: inline-block;
}
<div class="flex-box">
<div class="first">
<p>First Box</p>
<img src="http://placehold.it/300x300" />
</div>
<div class="second">
<p>Second Box</p>
<img src="http://placehold.it/300x300" />
</div>
<div class="third">
<p>Third Box</p>
<img src="http://placehold.it/300x300" />
</div>
</div>
JSfiddle Demo
To make item1 wrap first, you can use flex-wrap: wrap-reverse on your flex container.
Try this simplified version of you code:
<div class="container">
<div class="item">item1</div>
<div class="item orange">item2</div>
<div class="item blue">item3</div>
</div>
.container {
display: flex;
flex: 0 1 auto;
flex-wrap: wrap-reverse;
}
.item {
background-color: red;
height: 80px;
padding: 0 40px;
}
.orange {
background-color: orange;
}
.blue {
background-color: blue
}
See the MDN reference for browser support.

Resources