Overflow auto not working with justify-content: flex-end - html

I'm trying to get an element to have items aligned to the right, and all overflowing elements to be hidden but accessed by scrollbar.
But it seems like the scrollbar disappears when specifying justify-content: flex-end. Why is that, and how do I fix it?
Here is demo: https://jsfiddle.net/efguz4mp/1/
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
justify-content: flex-end;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
...and here is demo without justify-content: flex-end;: https://jsfiddle.net/efguz4mp
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>

When an overflow occur to the left (or top), a scroll doesn't get rendered, and the reason is that a HTML document's normal flow is left-to-right (top-to-bottom).
Flexbox has a row-reverse direction, which will solve that, thought 2 things comes with that:
One need to reorder the items or use an inner wrapper
I.a. Firefox and Edge doesn't show the scroll (possible bug)
Stack snippet
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
flex-direction: row-reverse;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
/* no wrapper */
.row > .box:nth-child(1) { order: 6; }
.row > .box:nth-child(2) { order: 5; }
.row > .box:nth-child(3) { order: 4; }
.row > .box:nth-child(4) { order: 3; }
.row > .box:nth-child(5) { order: 2; }
.row > .box:nth-child(6) { order: 1; }
/* wrapper */
.inner {
display: flex;
}
<div class="row">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
<div><br><br></div>
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Possible workarounds are:
Use direction: rtl to change the flow direction
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
direction: rtl;
}
.inner {
display: flex;
direction: ltr;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Use transform to flip the row element
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
transform: scale(-1,1); /* flip horizontally */
}
.inner {
display: flex;
transform: scale(-1,1); /* reset so items is not backwards */
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="inner">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
</div>
Use a script on page load to scroll to the right
window.addEventListener("load", function(e) {
var el = document.querySelector(".row");
el.scrollLeft = el.scrollWidth;
});
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
display: flex;
overflow: auto;
}
.box {
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>

The main problem is that you're dealing with a contradiction:
The justify-content property is designed to distribute extra space in the container.
However, an overflow condition occurs when there is no space left in the container.
Basically, justify-content and overflow have no association. The former applies only inside the container. The latter applies only outside the container.
With justify-content: flex-end, the flex items must be packed at the end of the container (not the end of the flex-start overflow area).
If the end-aligned items are too big to fit in the container, they will overflow on the start side, which is what you're seeing in your layout. But because the overflow property only applies in the direction of the writing mode (LTR, in this case), scrollbars are not rendered (more details).
So I would suggest forgetting about justify-content to make this layout work.
Instead, consider this: Use an invisible spacer item to push your content items to the right.
.row {
display: flex;
overflow: auto;
max-width: 500px;
background: #DADADA;
}
.box {
flex: 0 0 200px;
height: 40px;
margin: 4px 10px;
background: red;
}
.row::before {
content: "";
flex: 0 0 400px;
visibility: hidden;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
You'll notice that the last item margin collapses. That issue is explained here:
Last margin / padding collapsing in flexbox

Here's how I would recommend you do it
.row {
width: 100%;
max-width: 500px;
background: #DADADA;
flex: 1;
display: flex;
overflow: auto;
}
.box {
display: flex;
width: 200px;
height: 40px;
margin: 4px 10px;
background: red;
flex-shrink: 0;
}
<div class="row">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>

Related

How to get complex layout using flex grid css3?

im trying to achieve this layout using flex and it should be responsive without any media query
flex or grid can anyone write css for this layout?
i tried this:
.parent {
display: flex;
flex-wrap: wrap;
height: 100vh;
}
.box {
width: 33.33%;
border: 1px solid black;
min-height: 200px;
padding: 0 15px;
}
.box:first-child {
height: 100%;
min-height: 100%;
}
.box:nth-child(3n) {
min-height: 70%
}
<div class="parent">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
body {
margin:0;
}
.parent{
display: flex;
flex-wrap: wrap;
flex-direction: column;
height: 100vh;
}
.box{
flex: 0 0 33.33%;
box-shadow: 0 0 0 1px black;
padding: 0 15px;
}
.box:first-child{
flex: 1 0 100%;
}
.box:nth-child(5){
flex: 1 0 66.66%;
}
<div class="parent">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Create full width header and footer
Position sidebar next to main content area
Correct sizing of sidebar and main content area
Navigation elements positioning

Flexbox: Fill clicked row and wrap elements below/above to fill space

I am trying to set up a responsive grid so that when you click on a grid-item, it fills the horizontal space of its row and pushes the other items either above it or below it. To fill the remaining empty space.
Here's my current code which does fill the row but leaves empty space.
JSFIDDLE
$(".box").click(function() {
$(this).toggleClass("enlarge");
});
body {
margin: 0;
}
.enlarge {
flex-basis: 100% !important;
}
.boxes {
display: flex;
flex-wrap: wrap;
}
.boxes .box {
flex-basis: calc((100% / 3) - 2rem);
margin: 1rem;
height: 200px;
box-sizing: border-box;
text-align: center;
transition: all 1s;
background-color: rgb(220, 220, 220);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="boxes">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
Try this...
$(".box").click(function(){
$('.box').removeClass("enlarge");
$(this).toggleClass("enlarge");
});
body {
margin: 0;
}
.enlarge {
flex-basis: 100% !important;
}
.boxes {
display: flex;
flex-wrap: wrap;
}
.box {
flex-basis: calc((100% / 3) - 2rem);
flex-grow:1;
display:flex;
margin: 1rem;
height: 200px;
box-sizing: border-box;
text-align: center;
transition: all 1s;
background-color: rgb(220, 220, 220);
align-items:center;
justify-content:center;
}
<div class="boxes">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
<div class="box">5</div>
<div class="box">6</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

How can I make this responsive grid layout?

What I thought would be a simple layout turned out to be something I'm not able to accomplish yet.
I need the grid to be responsive and spread from one side to another (it has to be aligned with the text and box above).
I tried a few options, I commented them out for easier checking:
.big-container {
padding: 0 20%;
}
.header {
width: 100%;
height: 50px;
background-color: blue;
}
.container {
border: 1px solid black;
/* display: flex;
flex-wrap: wrap;
*/
/* display: flex;
flex-wrap: wrap;
justify-content: space-between;
*/
}
.box {
border: 1px solid black;
width: 100px;
height: 30px;
background-color: yellow;
/* float: left;
margin-left: 10px; */
}
<div class="big-container">
<div class="header"></div>
<p>Text</p>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>
I tried with flex but it doesn't sort nicely the last row, flex-wrap: wrap and float:left with some margin doesn't align correctly to the left.
If you use flexbox and set justify-content: space-between then last row will also have the same spacing instead of left align. Instead you can use grid-layout for this.
.big-container {
padding: 0 20%;
}
.header {
width: 100%;
height: 50px;
background-color: blue;
}
.container {
border: 1px solid black;
display: grid;
justify-content: space-between;
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
grid-gap: 10px;
}
.box {
border: 1px solid black;
height: 30px;
background-color: yellow;
}
<div class="big-container">
<div class="header"></div>
<p>Text</p>
<div class="container">
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
</div>
</div>

How to use flex row to elements with different heights

For example I'm trying to stack blockes with different heights like this:
.container {
display: flex;
flex-flow: row wrap;
}
.box {
width: 50%;
height: 50px;
background-color: lightgreen;
}
.box2 {
width: 50%;
height: 25px;
background-color: lightgreen;
}
<div class="container">
<div class="box"></div>
<div class="box2"></div>
<div class="box2"></div>
</div>
How It should be:
As far as I know, this can only be solved if you nest the two <div class="box2"> inside of a <div class="box"> wrapper
.container {
display: flex;
flex-flow: row wrap;
}
.box {
width: 50%;
height: 50px;
background-color: lightgreen;
}
.box2 {
width: 100%;
height: 25px;
background-color: lightgreen;
}
<div class="container">
<div class="box"></div>
<div class="box">
<div class="box2"></div>
<div class="box2"></div>
</div>
</div>
Here is an example:
https://jsfiddle.net/7j6uknck/2/
Another solution (but more a hack for this case than a generic solution) is to keep all what you have and adjust margin of last element.
Of course the margin-top value will depend on ther other values
.container {
display: flex;
flex-flow: row wrap;
}
.box {
width: 50%;
height: 50px;
background-color: lightgreen;
}
.box2 {
width: 50%;
height: 25px;
background-color: red;
}
.box2:last-child {
margin-left:auto;
margin-top:-25px;
}
<div class="container">
<div class="box"></div>
<div class="box2"></div>
<div class="box2"></div>
</div>
The other solution gave a working flexbox example for that particular scenario.
But if flexbox isn't mandatory and you don't want to change the html structure, you can make use of float for your particular layout.
.container {
}
.box {
float:left;
width: 50%;
height: 50px;
background-color: lightgreen;
}
.box2 {
float:right;
width: 50%;
height: 25px;
background-color: lightgreen
}
<div class="container">
<div class="box"></div>
<div class="box2"></div>
<div class="box2"></div>
</div>

flexbox grid under centered flex item

I would like an intro section on the left side of a .container and a side bar on the right.
On the left side underneath the .intro section I want there to be four divs equally spaced like a grid.
I'm having problems with getting the "grid set up". I think part of the problem is that the parent has some flexbox attribute effecting the children.
Requirement : The intro section should be centered in the .left-side and the "grid" should not be centered the boxes should take up as much space as necessary to fit 2 on a row with margins in between. The .intro should be 80 percent of the width of the leftside.
I don't want to do any major changes to the structure this is just a small sample of how my project is set up.
.container{
width: 80%;
margin: 0 auto;
display: flex;
}
.left-side{
flex:8;
display: flex;
justify-content:center;
flex-wrap: wrap;
}
.side-bar{
flex: 2;
height: 100vh;
background: powderblue;
}
.intro{
flex:3;
width:80%;
height: 300px;
background: skyblue;
}
.box{
background: red;
width: 45%;
height: 100px;
flex:4;
border:1px solid orange;
}
<div class="container">
<div class="left-side">
<div class="intro">
intro
</div>
<div class="recent">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
<div class="side-bar">
sidebar
</div>
Flex items can also be flex containers. This enables you to nest multiple containers, with flex-direction: row or column, in a larger container.
For your layout, you can build a column consisting of two flex items. The first item (.intro) has 80% width and can be centered horizontally. The second item (.recent) can be a flex container with four items arranged in a 2x2 grid.
.container {
width: 80%;
margin: 0 auto;
display: flex;
justify-content: center;
height: 100vh;
}
.left-side {
flex: 4;
display: flex;
flex-direction: column;
}
.side-bar {
flex: 1;
background: powderblue;
}
.intro {
flex: 3;
height: 300px;
width: 80%;
margin: 0 auto;
background: skyblue;
}
.recent {
display: flex;
flex-wrap: wrap;
background-image: url("http://i.imgur.com/60PVLis.png");
background-size: contain;
}
.box {
margin: 5px;
flex-basis: calc(50% - 10px);
height: 100px;
box-sizing: border-box;
background: red;
}
body { margin: 0; }
<div class="container">
<div class="left-side">
<div class="intro">intro</div>
<div class="recent">
<div class="box">1</div>
<div class="box">2</div>
<div class="box">3</div>
<div class="box">4</div>
</div>
</div>
<div class="side-bar">
sidebar
</div>
</div>