Flexbox - Two column in a row - html

I'm trying to use flexbox in order to create two columns of three row for the Products. I looked to other similar problem on StackOverflow but the answers given didn't work for me. Could you help me please ?
Here the HTML code:
Informations {
list-style-type: none;
margin: 0;
padding: 0;
border: 1px solid blue;
width: 100%;
display: flex;
justify-content: space-between;
}
.Information {
border: 1px solid blue;
margin: 0.5em;
padding: 0.5em;
}
Game {
list-style-type: none;
border: 1px solid red;
width: 100%;
display: flex;
}
.ProductContainer {
display: flex;
flex-flow: column wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
}
.UpgradeContainer {
border: 1px solid black;
width: 10%;
}
.Upgrade {
display: flex;
flex-flow: column wrap;
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
}
<!DOCTYPE world>
<html>
<head>
<title> World </title>
</head>
<body>
<Informations>
<div class="Information">Your World:</div>
<div class="Information">Your Money:</div>
<div class="Information">Your ID:</div>
</Informations>
<Game>
<div class="UpgradeContainer">
<div class="Upgrade">Unlocks</div>
<div class="Upgrade">Cash</div>
<div class="Upgrade">Angels</div>
<div class="Upgrade">Managers</div>
<div class="Upgrade">Investors</div>
</div>
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
</Game>
</body>
</html>
I basically want to have to the left my upgrades (Cash, angels...) and in the middle and right two column of three row of products.
Here is my code pen to see: https://codepen.io/Tameiki/pen/oNXpNVe

You can use the flex-wrap property together with setting the flex-basis on the child elements:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
Notice how I removed the flex-direction:column property: the child elements will attempt to fit in a single row, overflowing the container if necessary.
.ProductContainer{
display: flex;
/*flex-flow: wrap;*/
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
/*flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
flex-wrap is what makes them start a new line instead of overflowing:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
/*flex-basis: calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
But how do we get only two of them per row? By telling each of the child elements to be half the row's width:
.ProductContainer{
display: flex;
flex-flow: wrap;
border: 1px solid black;
width: 90%;
}
.Product {
border: 1px solid red;
margin: 0.5em;
padding: 0.5em;
flex-basis: 50%; /*calc(50% - 2em - 5px); /* - Margins - Borders - 1px to mitigate subpixel rounding issues*/
}
<div class="ProductContainer">
<div class="Product">Product1</div>
<div class="Product">Product2</div>
<div class="Product">Product3</div>
<div class="Product">Product4</div>
<div class="Product">Product5</div>
<div class="Product">Product6</div>
</div>
Unfortunately, flex-basis applies to the inner width of an element - including paddings, but excluding margins and borders. Usually, Flexbox tries to shrink child elements to fit the row if possible, but flex-wrap disables this, so we will have to adjust manually. That gets you to the code at the top.

Related

Flexbox keep wrapping point while increasing item width

First of all, here is a codepen with the issue I am trying to solve.
This is a simplified version of the problem I have on an actual project. My goal is to keep the grid in the same format with 5 columns and to be able to increase the width of these cells so the content is always visible, but also so that it doesn't wrap before the first row of 5 columns is displayed. Whenever I try to increase the width of the cells the grid wraps and I lose the structure I want.
So, basically, increase width of items, but prevent wrapping, is it possible? It is fine if the content overflows the flex container itself, the goal is to add overflow-x to this grid.
.flex-container {
border: 1px solid silver;
display: flex;
width: 50%;
}
.wrap {
flex-wrap: wrap;
}
.wrap div {
background: gold;
}
.flex-item {
width: 160px;
border-bottom: 1px solid black;
border-right: 1px solid black;
line-height: 100px;
color: black;
font-weight: bold;
font-size: 2em;
text-align: center;
}
<div class="flex-container wrap">
<div class="flex-item">11111111111111</div>
<div class="flex-item">22222222222222</div>
<div class="flex-item">33333333333333</div>
<div class="flex-item">44444444444444</div>
<div class="flex-item">55555555555555</div>
<div class="flex-item">66666666666666</div>
<div class="flex-item">77777777777777</div>
<div class="flex-item">88888888888888</div>
<div class="flex-item">99999999999999</div>
<div class="flex-item">00000000000000</div>
</div>
From the comments, it does look like grid is the option you need, it won't allow content to be wrapping and justify content will stick it on the side if shorter thant the width of the container.
here is the snippet with grid:
/* flex turned into grid */
.flex-container {
border: 1px solid silver;
display: grid;
grid-template-columns:repeat(5,auto);
justify-content:start;
overflow:auto;
width: 80%;
}
.wrap {
}
.wrap div {
background: gold;
}
.flex-item {
border-bottom: 1px solid black;
border-right: 1px solid black;
line-height: 100px;
color: black;
font-weight: bold;
font-size: 2em;
text-align: center;
}
<div class="flex-container wrap">
<div class="flex-item">11111111111111</div>
<div class="flex-item">22222222222222</div>
<div class="flex-item">33333333333333</div>
<div class="flex-item">44444444444444</div>
<div class="flex-item">55555555555555</div>
<div class="flex-item">66666666666666</div>
<div class="flex-item">77777777777777</div>
<div class="flex-item">88888888888888</div>
<div class="flex-item">99999999999999</div>
<div class="flex-item">00000000000000</div>
</div>
I think, if it is allowable, that css grid may be a better candidate for the layout you are proposing...
.grid-container {
border: 1px solid silver;
display: grid;
width: 50%;
grid-template-columns: 20% 20% 20% 20% 20%; /* hard set five columns and no more */
}
.grid-container div {
background: gold;
}
.grid-item {
/* width: 160px; */
border-bottom: 1px solid black;
border-right: 1px solid black;
line-height: 100px;
color: black;
font-weight: bold;
font-size: 2em;
text-align: center;
overflow-x: hidden; /* overflow-x to hide overflow as discussed in question */
}
<div class="grid-container">
<div class="grid-item">11111111111111</div>
<div class="grid-item">22222222222222</div>
<div class="grid-item">33333333333333</div>
<div class="grid-item">44444444444444</div>
<div class="grid-item">55555555555555</div>
<div class="grid-item">66666666666666</div>
<div class="grid-item">77777777777777</div>
<div class="grid-item">88888888888888</div>
<div class="grid-item">99999999999999</div>
<div class="grid-item">00000000000000</div>
</div>
.flex-container {
display: flex;
flex-wrap: wrap;
background-color:red;
}
.flex-container > div {
background-color: #f1f1f1;
width: 100px;
margin: 10px;
text-align: center;
line-height: 75px;
font-size: 30px;
word-wrap: break-word;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div class="flex-container">
<div>11111111111111</div>
<div>22222222222222</div>
<div>33333333333333</div>
<div>44444444444444</div>
<div>55555555555555</div>
<div>66666666666666</div>
<div>77777777777777</div>
<div>88888888888888</div>
<div>99999999999999</div>
<div>00000000000000</div>
</div>
</body>

Make a responsive layout using flex and css grid

I'm trying to do a responsive layout, I'm not good with css so I need help.
Here is the code:
.container {
outline: 1px solid black;
max-width: 490px;
margin: 0 auto;
}
.columns {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.map {
background-color: cyan;
width: 150px;
min-width: 150px;
height: 150px;
min-height: 150px;
margin-right: 20px;
}
.content {
outline: 1px solid black;
background-color: lightgray;
max-width: 320px;
}
.cards {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.card {
background-color: pink;
outline: 1px solid black;
width: 150px;
height: 70px;
display: inline-block;
}
.card.left {
margin-right: 20px;
}
.texts {
outline: 1px solid black;
display: inline-flex;
flex-wrap: wrap;
}
.text {
background-color: gold;
outline: 1px solid black;
width: 150px;
height: 200px;
display: inline-block;
}
.text.left {
margin-right: 20px;
}
<div class="container">
<div class="columns">
<div class="map"></div>
<div class="content">
<div class="cards">
<div class="card left">card #1</div>
<div class="card">card #2</div>
<div class="card left">card #3</div>
<div class="card">card #4</div>
</div>
<div class="texts">
<div class="text left">text #1</div>
<div class="text">text #2</div>
</div>
</div>
</div>
</div>
Basically there are two rows.
The first one contains an element with fixed width and height, and on the right four cards.
The second rows contains only two elements.
Each element of this layout has width 150px.
The code shown above works partially.
The first row is ok, the second one no because the gold elements should stay aligned with the cards so when cards are on the right of el1, contents should below the cards.
It is like if there were to be a hidden element (on the left side of contents) that has the same size as el1.
Also I would like everything to always be centered because now it is only if the window width is > 490px.
This is what I'd like to have:
How can I do that?

How to select the last item of a wrapped flex row in CSS

I have a flex row that wraps around when the content is too large for 1 row. Items are divided by a small red border on the left, and the last item has a red border on the right too end the list. The issue is that the last item on a row does not have the right border, and I can't find a CSS selector to apply the right border to it:
#container {
width: 500px;
display: flex;
flex-wrap: wrap;
padding: 25px;
background-color: black;
color: white;
align-items; stretch;
}
.item {
width: 100px;
text-align: center;
border-left: 3px solid firebrick;
margin-bottom: 5px;
}
.item:last-of-type {
border-right: 3px solid firebrick;
}
<div id="container">
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
</div>
Does a CSS selector exist to select the last item in a wrapped flexbox row? If not, is there another easy solution for this?
do it differently like below:
#container {
display: flex;
flex-wrap: wrap;
padding: 25px;
background-color: black;
color: white;
align-items; stretch;
}
.item {
width: 100px;
text-align: center;
border-left: 3px solid firebrick;
border-right: 3px solid firebrick;
margin-right:-3px;
margin-bottom: 5px;
}
<div id="container">
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
<div class="item">Test</div>
</div>

CSS style div3 differently if div1 and div2 don't exist

If a user is signed up to my site, in their login area I have 3 divs as follows:
<div id="psts-cancel-link" class="psts-cancel-link"></div>
<div class="psts-receipt-link"></div>
<div id="psts-signup-another"></div>
These divs all have a width of 32% and sit inline with each other.
#psts-cancel-link {
background: white;
border-left: 3px solid #ccc;
padding: 1em;
width: 32%;
min-height: 270px;
float: left;
}
.psts-receipt-link {
background: white;
border-left: 3px solid #ccc;
min-height: 270px;
float: left;
width: 32%;
margin: 0 10px;
padding: 20px;
}
#psts-signup-another {
background: white;
padding: 1em;
border-left: 3px solid #ccc;
margin-bottom: 30px;
width: 32%;
min-height: 270px;
float: left;
}
When a user is not signed up, only one of the divs displays:
<div id="psts-signup-another"></div>
Is it possible to change the styling of this so that it's width is 100% when div1 and div2 aren't displayed?
So far I have tried this, but with no success:
#psts-cancel-link ~ .psts-receipt-link ~ #psts_existing_info #psts-signup-another {
width:100%;
}
Table Layout Implementation
Use a table layout. Specify display: table on the parent and display: table-cell on the child elements.
#psts-cancel-link {
background: tomato;
border-left: 3px solid #ccc;
padding: 1em;
min-height: 270px;
display: table-cell;
word-wrap: break-word;
}
.psts-receipt-link {
background: lightblue;
border-left: 3px solid #ccc;
min-height: 270px;
margin: 0 10px;
padding: 20px;
display: table-cell;
word-wrap: break-word;
}
#psts-signup-another {
background: tomato;
padding: 1em;
border-left: 3px solid #ccc;
margin-bottom: 30px;
min-height: 270px;
display: table-cell;
word-wrap: break-word;
}
.container {
display: table;
width: 100%;
table-layout: fixed;
}
Logged in
<div class="container">
<div id="psts-cancel-link"></div>
<div class="psts-receipt-link"></div>
<div id="psts-signup-another"></div>
</div>
Logged out
<div class="container">
<div id="psts-signup-another"></div>
</div>
Flexbox Layout Implementation
You can also use flexbox which expands and shrinks the child items according to the parent container.
#psts-cancel-link {
background: tomato;
border-left: 3px solid #ccc;
padding: 1em;
min-height: 270px;
flex: 1;
}
.psts-receipt-link {
background: lightblue;
border-left: 3px solid #ccc;
min-height: 270px;
margin: 0 10px;
padding: 20px;
flex: 1;
}
#psts-signup-another {
background: tomato;
padding: 1em;
border-left: 3px solid #ccc;
margin-bottom: 30px;
min-height: 270px;
flex: 1;
}
.container {
display: flex;
}
Logged in
<div class="container">
<div id="psts-cancel-link"></div>
<div class="psts-receipt-link"></div>
<div id="psts-signup-another"></div>
</div>
Logged out
<div class="container">
<div id="psts-signup-another"></div>
</div>
You could simply use :first-child if it's indeed the only child in the second case.
#psts-signup-another:first-child {}
You can use the adjacent selector. Have a look at the following snippet:
#psts-signup-another {padding: 5px; background: #f99;}
div + div + #psts-signup-another {padding: 5px; background: #99f;}
<h2>Div when three divs are present</h2>
<div class="theDivs">
<div id="psts-cancel-link" class="psts-cancel-link"></div>
<div class="psts-receipt-link"></div>
<div id="psts-signup-another"></div>
</div>
<h2>Div when three divs are not present</h2>
<div class="theDivs">
<div id="psts-signup-another"></div>
</div>
i think you should use another container div with a new class when user logout.
Logged:
<div class="container">
<div id="psts-cancel-link" class="psts-cancel-link"></div>
<div class="psts-receipt-link"></div>
<div id="psts-signup-another"></div>
</div>
Logout:
<div class="container logout">
<div id="psts-cancel-link" class="psts-cancel-link"></div>
<div class="psts-receipt-link"></div>
<div id="psts-signup-another"></div>
</div>
CSS:
.container.logout > div {
display:none;
}
.container.logout > .psts-signup-another {
display:block;
}

CSS Flexbox Wrap First of Line

I'm struggling with the wrapping option of the css flexbox in combination with margins between the items.
What I'm trying to archieve is: Have a flexcontainer with wrapping enabled and a number of items with variable with and minimum width. Between these items I want to have a small gap (margin) but I don't want a margin between the item and the container on the left or right side.
Right now I'm using the first-child and last-child pseudo class but this approach doesn't work unfortunatly when the container wraps the content. See JsFiddle for a minimalistic demo.
HTML
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div>
CSS
.container {
display: flex;
flex-wrap: wrap;
border: 1px solid red;
}
.item {
min-width: 100px;
flex: 1;
border: 1px solid black;
margin-left: 20px;
margin-right: 20px;
}
.item:first-child {
margin-left: 0px;
}
.item:last-child {
margin-right: 0px;
}
Any suggestions?
flexbox has some specific properties, so in your case this is what needs to be fixed:
instead of min-width use flex-basis
use justify-content: space-between
to apply margin on items there's a special hack (check out the
example -to fix border coherency apply a wrapper);
.container-bg {
width:100%;
border: 1px solid green;
overflow:hidden;
}
.container {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
/* border: 1px solid red;*/
margin: 0 -20px;
}
.item {
/*min-width: 100px;*/
flex: 1 0 100px;/*if you want to set 100px as min-width you'll have to set flex-shrink to 0*/
border: 1px solid black;
margin: 0 20px;
}
/*.item:first-child {
margin-left: 0px;
}
.item:last-child {
margin-right: 0px;
}*/
<p>resize the window for wrapping</p>
<div class="container-bg"><div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div></div>
EDIT :
set flex-shrink to 0 is don't want to go below a certain width..
If you add another wrapper around your items, you can use this dirty hack: https://jsfiddle.net/xw5uo2j1/13/
You set your main container to be 100% of the width, then your "sub" container to be 100% plus the amount of space between you're going to add. Then add the same amount of margin-right to the items.
.maincontainer {
width:100%;
border: 1px solid red;
}
.container {
display: flex;
flex-flow: row wrap;
justify-content:space-between;
align-content:space-between;
width:calc(100% + 5px);
}
.item {
min-width: 100px;
flex: 1;
border: 1px solid black;
margin-right:5px;
}
<p>resize the window for wrapping</p>
<div class="maincontainer">
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div>
</div>
UPDATED, with more than 5 items
Use calc and jusify-content: space-between;
* {
box-sizing: border-box;
margin: 0;
}
.container {
border: thin solid red;
display: -webkit-flex;
display: flex;
-webkit-flex-wrap: wrap;
flex-wrap: wrap;
margin: 0 -10px;
}
.item {
border: thin solid black;
-webkit-flex: 1 1 calc(20% - 20px);
flex: 1 1 calc(20% - 20px);
margin: 0 10px;
padding: 20px;
position: relative;
}
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
<div class="item">D</div>
<div class="item">E</div>
</div>