How to override flexbox justify-content: space-between? - html

Is it possible to override space-between so that the last item would horizontally align to the next to last? Or should I just drop space-between and go with flex-start and custom margins?
JSfiddle Demo
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
width: 300px;
margin: 30px auto;
padding: 0;
box-sizing: border-box;
position: relative;
}
.item {
width: 90px;
height: 90px;
background-color: #111;
margin-bottom: 10px;
}
.next-to-last {
background-color: blue;
}
.last-item {
background-color: red;
}
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item next-to-last"></div>
<div class="item last-item"></div>
</div>

Fake element method:
You can add a fake element for the 4th item so that 5 and 6 are next to each other.
This will work if you use visibility: hidden to hide the element and preserve the space occupied by it. The common alternative display: none will not work since the item is not calculated in the flexbox alignment.
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
justify-content: space-between;
width: 300px;
margin: 30px auto;
padding: 0;
box-sizing: border-box;
position: relative;
}
.item {
width: 90px;
height: 90px;
background-color: #111;
margin-bottom: 10px;
}
.next-to-last {
background-color: blue;
}
.last-item {
background-color: red;
}
.invisible {
visibility: hidden;
}
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item invisible"></div> <!-- Invisible fake element -->
<div class="item next-to-last"></div>
<div class="item last-item"></div>
</div>
Custom margin method:
If you don't want to create an additional element then you need to use your own suggestion of flex-start and custom margin.
.wrapper {
display: flex;
flex-direction: row;
flex-wrap: wrap;
align-items: flex-start;
justify-content: flex-start;
width: 300px;
margin: 30px auto;
padding: 0;
box-sizing: border-box;
position: relative;
}
.item {
width: 90px;
height: 90px;
background-color: #111;
margin-bottom: 10px;
margin-right: 10px;
}
.next-to-last {
background-color: blue;
margin-left: 100px;
}
.last-item {
background-color: red;
}
<div class="wrapper">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item next-to-last"></div>
<div class="item last-item"></div>
</div>

Related

How to apply flex-grow?

I'm trying to create a flex row with a growth of 2 and then a wrap but can't understand why it is not working properly.
Here is the CSS and HTML.
.flex {
height: 50px;
width: 50px;
background-color: black;
}
.flex1 {
height: 50px;
width: 50px;
background-color: yellow;
margin-left: 50px;
}
.flex2 {
height: 50px;
width: 50px;
background-color: green;
margin-left: 50px;
}
.flexcontainer {
display: flex;
flex-wrap: wrap;
flex-grow: 2;
flex-direction: row;
}
<div class="flexcontainer">
<div class="flex">
<div class="flex1">
<div class="flex2">
</div>
</div>
</div>
</div>
The way you implement the flex-grow is totally wrong because the flex-grow have to be applied to child elements as shown in below code snippet as a example.
#content {
display: flex;
justify-content: space-around;
flex-flow: row wrap;
align-items: stretch;
}
.box {
flex-grow: 1;
border: 3px solid rgba(0,0,0,.2);
}
.box1 {
flex-grow: 2;
border: 3px solid rgba(0,0,0,.2);
}
<h4>This is a Flex-Grow</h4>
<div id="content">
<div class="box" style="background-color:red;">A</div>
<div class="box" style="background-color:lightblue;">B</div>
<div class="box" style="background-color:yellow;">C</div>
<div class="box1" style="background-color:brown;">D</div>
<div class="box1" style="background-color:lightgreen;">E</div>
<div class="box" style="background-color:brown;">F</div>
</div>
To read more about flex-grow, you should learn from there : https://developer.mozilla.org/en-US/docs/Web/CSS/flex-grow

How to add a line between flex box rows?

Is there a possibility to add separated lines between flex box rows?
Or any other solution for that?
Adding a border to all element it is not an option, as you can see in the example.
.container{
width:400px;
flex-flow: row wrap;
box-sizing: border-box;
display: flex;
place-content: flex-start space-between;
align-items: flex-start;
border: 1px solid #2662c3;
}
.item{
flex-direction: row;
box-sizing: border-box;
display: flex;
place-content: center flex-start;
align-items: center;
flex: 1 1 150px;
max-width: 150px;
min-width: 150px;
padding: 16px;
height: 65px;
/* this is bab solution*/
border-bottom: 1px solid #2662c3;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Link.
You can use border on each item, though you need one of their pseudo element's, absolute positioned at the top, full width and set overflow: hidden on the container.
The downside with this is they need to top (or bottom) align or else the "border line" might break.
The upside, it will move dynamically with the items content, so one row can be higher than another.
Stack snippet
.container{
width:400px;
flex-flow: row wrap;
box-sizing: border-box;
display: flex;
place-content: flex-start space-between;
align-items: flex-start;
border: 1px solid #2662c3;
overflow: hidden; /* added */
}
.item{
position: relative; /* added */
flex-direction: row;
box-sizing: border-box;
display: flex;
place-content: center flex-start;
align-items: center;
flex: 1 1 150px;
max-width: 150px;
min-width: 150px;
padding: 16px;
height: 65px;
margin-bottom: 1px; /* compensate for border */
}
.item.higher{
height: 95px;
}
.item::after{
content: ' ';
position: absolute;
left: 0;
top: -1px;
width:100vw;
border-top: 1px solid #2662c3;
}
.item{
background: #eee; /* for this demo only */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item higher"></div>
<div class="item higher"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
The other way, were the border will adjust with different row heights, would be to either use a pseudo element on the container, and using order, position it between the 2 rows.
The downside with this is, there is only 2 pseudo and will only handle up to 3 rows.
Stack snippet
.container{
width:400px;
flex-flow: row wrap;
box-sizing: border-box;
display: flex;
place-content: flex-start space-between;
align-items: flex-start;
border: 1px solid #2662c3;
}
.item{
flex-direction: row;
box-sizing: border-box;
display: flex;
place-content: center flex-start;
align-items: center;
flex: 1 1 150px;
max-width: 150px;
min-width: 150px;
padding: 16px;
height: 65px;
}
.container::before{
content: ' ';
width:100%;
border-top: 1px solid #2662c3;
order: 1;
}
.container .item:nth-child(n+3){
order: 1;
}
.item.higher{
height: 95px;
}
.item{
background: #eee; /* for this demo only */
}
<div class="container">
<div class="item higher"></div>
<div class="item higher"></div>
<div class="item"></div>
<div class="item"></div>
</div>
For more than 3 rows, one need to add an extra element, either combined with the pseudo or not, here shown when not.
Stack snippet
.container{
width:400px;
flex-flow: row wrap;
box-sizing: border-box;
display: flex;
place-content: flex-start space-between;
align-items: flex-start;
border: 1px solid #2662c3;
}
.item{
flex-direction: row;
box-sizing: border-box;
display: flex;
place-content: center flex-start;
align-items: center;
flex: 1 1 150px;
max-width: 150px;
min-width: 150px;
padding: 16px;
height: 65px;
}
.container .border{
width:100%;
border-top: 1px solid #2662c3;
}
.container .border:nth-of-type(1){
order: 1;
}
.container .item:nth-child(n+3){
order: 2;
}
.container .border:nth-of-type(2){
order: 3;
}
.container .item:nth-child(n+5){
order: 4;
}
.container .border:nth-of-type(3){
order: 5;
}
.container .item:nth-child(n+7){
order: 6;
}
.item.higher{
height: 95px;
}
.item{
background: #eee; /* for this demo only */
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item higher"></div>
<div class="item higher"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<span class="border"></span>
<span class="border"></span>
<span class="border"></span>
</div>
Use a background coloration to create a line at the center:
.container {
width: 400px;
flex-flow: row wrap;
box-sizing: border-box;
display: flex;
justify-content: space-between;
align-items: flex-start;
border: 1px solid #2662c3;
/*you border*/
background: linear-gradient(#2662c3, #2662c3) center/100% 1px no-repeat;
}
.item {
box-sizing: border-box;
flex: 1 1 150px;
max-width: 150px;
padding: 16px;
height: 65px;
}
<div class="container">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
</div>

flex-flow: column wrap doesn't stretch the parent element's width [duplicate]

This question already has answers here:
When flexbox items wrap in column mode, container does not grow its width
(9 answers)
Closed 4 years ago.
When I use flex-flow: column wrap, the parent element's width is not stretched.
*{
margin: 0;
padding: 0;
}
.box{
background: #f03;
position: relative;
display: inline-block;
/* top:10px; */
/* left: 10px; */
padding: 20px;
}
.in{
display: flex;
align-items: center;
flex-flow: column wrap;
max-height: 300px;
align-content: flex-start;
justify-content: space-between;
}
.item{
background: #fe3;
width: 100px;
margin-bottom: 20px;
height: 100px;
}
.item:last-child{
margin-left: 15px;
}
<body>
<div class="box">
<div class="in">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
</div>
</body>
https://jsfiddle.net/p4oLk7dz/5/
So what should I do?
You are trying to have a flex container inside the oder one, the first one needs the display flex to get the content of the element below
I would also make some small changes but it really depends on what you are trying to achive.
If this isnt what you were looking for, please comment so i can try to improve it.
Hope this works :)
.box{
background: #f03;
position: relative;
display: flex;
max-width: 220px;
padding: 20px;
}
.in{
display: flex;
flex-wrap: wrap;
max-width: 220px;
}
*{
margin: 0;
padding: 0;
}
.box{
background: #f03;
position: relative;
display: flex;
max-width: 220px;
padding: 20px;
}
.in{
display: flex;
flex-wrap: wrap;
max-width: 220px;
}
.item{
background: #fe3;
width: 100px;
margin-bottom: 20px;
height: 100px;
}
.item-2{
order: 3;
}
.item-3{
margin-left: 20px;
}
<body>
<div class="box">
<div class="in">
<div class="item">1</div>
<div class="item item-2">2</div>
<div class="item item-3">3</div>
</div>
</div>
</body>
<!-- 第三个并没有把父元素宽度撑开 -->
Remove the display properties from this class
.box{
background: #f03;
display: inline-block;
display:relative;
/* top:10px; */
/* left: 10px; */
padding: 20px;
}
and everything works !!!
*{
margin: 0;
padding: 0;
}
.box{
background: #f03;
padding: 20px;
}
.in{
display: flex;
align-items: center;
flex-flow: column wrap;
max-height: 300px;
align-content: flex-start;
justify-content: space-between;
}
.item{
background: #fe3;
width: 100px;
margin-bottom: 20px;
height: 100px;
}
.item:last-child{
margin-left: 15px;
}
<body>
<div class="box">
<div class="in">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
</div>
</div>
</body>
you can check the result here https://jsfiddle.net/p4oLk7dz/30/

How to correctly align these elements with flexbox?

Sorry for the really vague question title but I have no idea how to best describe it...
Take the following code example:
.wrapper {
border: 2px solid green;
}
.container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
border: 2px solid red;
margin: 5px;
height: 64px;
}
.item {
display: flex;
border: 2px solid #0000ff;
padding: 3px;
}
.left {
justify-content: flex-end;
}
.right {
justify-content: flex-start;
}
<div class="wrapper" style="width: 100%">
<div class="container">
<div class="item left">FIXED</div>
<div class="item right">abc</div>
</div>
<div class="container">
<div class="item">FIXED</div>
</div>
<div class="container">
<div class="item left">FIXED</div>
<div class="item right">abcdefgh</div>
</div>
</div>
<br />
<div class="wrapper" style="width: 50%">
<div class="container">
<div class="item left">FIXED</div>
<div class="item right">abc</div>
</div>
<div class="container">
<div class="item">FIXED</div>
</div>
<div class="container">
<div class="item left">FIXED</div>
<div class="item right">abcdefgh</div>
</div>
</div>
Observations:
FIXED represents an element of fixed size, always same width/height.
The right side element can vary on size (mostly width).
The right side element is always aligned to the left.
The left side element is always aligned to the left.
What I'm trying to achieve:
The FIXED element should always be centered on the red row.
THE FIXED element on the first/third rows needs to be aligned to the right side of the FIXED element on the second row.
Here's an image to better demonstrate what I'm looking for:
EDIT: My final solution based on the #vals answer. I had to change this a bit because I'm using CSS Modules with selector composition in a React app and I need a single class per element.
.container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
/* UNREQUIRED (FOR DEMONSTRATION ONLY) */
border: 2px solid red;
padding: 5px;
}
.container::before {
content: "";
flex: 1 0 14px; /* UNREQUIRED (FOR DEMONSTRATION ONLY) (14px -> 0) */
}
.container-single {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
/* UNREQUIRED (FOR DEMONSTRATION ONLY) */
border: 2px solid red;
padding: 5px;
}
.item {
display: flex;
flex: 0 0 auto;
/* UNREQUIRED (FOR DEMONSTRATION ONLY) */
border: 2px solid #0000ff;
padding: 5px;
}
.item-right {
display: flex;
flex: 1 0 0;
/* UNREQUIRED (FOR DEMONSTRATION ONLY) */
border: 2px solid #0000ff;
padding: 5px;
}
.item-left {
display: flex;
flex: 0 0 auto;
margin-left: auto;
/* UNREQUIRED (FOR DEMONSTRATION ONLY) */
border: 2px solid #0000ff;
padding: 5px;
}
<div class="container">
<div class="item-left">FIXED</div>
<div class="item-right">abc</div>
</div>
<br />
<div class="container-single">
<div class="item">FIXED</div>
</div>
<br />
<div class="container">
<div class="item-left">FIXED</div>
<div class="item-right">abcdefgh</div>
</div>
For anyone interested, the CSS selector composition goes like this:
.container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
.container::before {
flex: 1 0 0;
content: "";
}
.container-single {
composes: container;
}
.item {
display: flex;
flex: 0 0 auto;
}
.item-right {
flex: 1 0 0;
composes: item;
}
.item-left {
margin-left: auto;
composes: item;
}
I have changed the layout slighty, I have add a class on the single container.
Is it ok for the right element to grow ?
.container {
display: flex;
flex-direction: row;
border: 2px solid red;
padding: 5px;
}
.item {
display: flex;
flex-basis: auto;
flex-grow: 0;
border: 2px solid #0000ff;
padding: 5px;
}
.item.right {
flex-basis: 0;
flex-grow: 1;
}
.item.left {
margin-left: auto;
}
.container:not(.single):before {
content: "";
flex-basis: 14px; /* border 2px + padding 5px */
flex-grow: 1;
}
.single .item {
margin: 0px auto;
}
<div class="container">
<div class="item left">FIXED</div>
<div class="item right">abc</div>
</div>
<br />
<div class="container single">
<div class="item">FIXED</div>
</div>
<br />
<div class="container">
<div class="item left">FIXED</div>
<div class="item right">abcdefgh</div>
</div>

How can i create a Tile System like this?

So i am creating a Responsiv Website in which i want to have a Tile System like in the Image above. Unfortunatly i just cant get it done right.Here is my current ATTEMPT. Using Flexbox
.flex-container {
padding: 0;
margin: 0;
list-style: none;
width: 100%;
height: 30px;
display: -webkit-box;
display: -moz-inline-box;
display: -ms-inline-flexbox;
display: -webkit-inline-flex;
display: inline-flex;
-moz-justify-content: space-around;
-ms-justify-content: space-around;
justify-content: space-around;
-webkit-flex-flow: row wrap;
-moz-flex-flow: row wrap;
flex-flow: row wrap;
}
.flex-item {
background: #eaeaea;
padding: 5px;
width: 130px;
height: 90px;
margin-top: 0px;
margin-left: 0px;
color: black;
font-weight: bold;
font-size: 12px;
text-align: center;
cursor: pointer;
}
.flex-item:hover {
background: #d9d9d9;
}
.flex-item-stop {
background: crimson;
padding: 5px;
width: 130px;
height: 90px;
margin-top: 0px;
color: black;
font-weight: bold;
font-size: 12px;
text-align: center;
cursor: pointer;
}
.flex-item-stop:hover {
background-color: #bb1133;
}
#Menue {
position: fixed;
left: 0;
height: 25%;
width: 650px;
float: right;
padding: 25px 0;
margin: -25px 0;
display: inline-flex;
display: -moz-inline-flex;
display: -webkit-inline-flex;
justify-content: space-around;
-moz-justify-content: space-around;
-webkit-justify-content: space-around;
flex-flow: column wrap;
-moz-flex-flow: column wrap;
-webkit-flex-flow: column wrap;
}
<div id="Menue">
<div class="flex-container">
<div class="flex-item">Vanilla</div>
<div class="flex-item">Citrus</div>
<div class="flex-item">Bananasplit</div>
<div class="flex-item">Gum</div>
</div>
<div class="flex-container" style="margin-top:10%;">
<div class="flex-item">Sweden</div>
<div class="flex-item">Austria</div>
<div class="flex-item">Russia</div>
<div class="flex-item">Brazil</div>
</div>
<div class="flex-container" style="margin-top:10%;">
<div class="flex-item">Positiv</div>
<div class="flex-item">Negativ</div>
<div class="flex-item">Neutral</div>
<div class="flex-item-stop"> </div>
</div>
</div>
I just cant create the spacing between the tiles and my result seems different in different browsers, especially in the Internet Explorer 11. What i also would like to have is that there should always be 4 Tiles in a singel "line" is this possible?
Now comes my Question: What exactly do i have to change in my Code to accomplish such a Tile System?
Are the alternatives to Flexbox?
Any Examples suggestions are appreciated.
You can try something like this :
.row{
display:table;
content:'';
clear:both;
width:100%;
}
.item{
box-sizing:border-box;
width:25%;
border:1px solid white;
height:100px;
background-color:yellow;
float:left;
text-align:center;
}
<div class="row">
<div class="item">Vanilla</div>
<div class="item">Gum</div>
<div class="item">Citrus</div>
<div class="item">BananaSplit</div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<div class="row">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
Give this a crack:
HTML:
<div class="container">
<div class="inner-block"></div>
<div class="inner-block"></div>
<div class="inner-block"></div>
<div class="inner-block"></div>
<div class="inner-block"></div>
<!-- e.t.c... !-->
</div>
CSS:
.container{
width: 100%;
}
.container > .inner-block{
display: inline-block;
position: relative;
width: calc(25% - 13px);
height: 0;
padding-bottom: calc(25% - 13px);
margin: 5px;
background: blue;
}
JsFiddle: https://jsfiddle.net/r4w1v0dm/2/