issue with horizontal scrolling div using flexbox - html

I am using flexbox css to make a container with number of divs to scroll horizontally but the problem is when I try to add more divs to the container, it moves to the left side and the divs left to the display are hidden.
I don't understand what's happening
here is the code snippet and codepen
.scroll{
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
justify-content: space-evenly;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
}
.item{
flex: 0 0 auto;
background: #e4e4e4;
width: 150px;
height: 150px;
margin: 10px;
}
<div class="scroll">
<div class="item">
</div>
<div class="item">
</div> <div class="item">
</div> <div class="item">
</div> <div class="item">
</div> <div class="item">
</div>
<div class="item">
</div> <div class="item">
</div>
<div class="item">
</div> <div class="item">
</div>
</div>
Thank you

The main issue here is that for some justify-content values, the overflow distribution will overflow the flex parent at both its left and right edge.
https://www.w3.org/TR/css-align-3/#distribution-values
Therefor a new keyword has been introduced, safe, where one can control how that overflow should behave.
https://www.w3.org/TR/css-align-3/#overflow-values
As this is a quite new addition to the Flexbox model, it won't work cross browsers yet, nor does space-evenly.
When it does (and for browsers that support it), this CSS line will fix the issue
justify-content: space-evenly safe;
A possible workaround, to achieve both evenly spaced items when they won't fill their parent, and only overflow at the right edge when too many, could be to use auto margins.
Stack snippet
.scroll{
display: flex;
/*flex-wrap: nowrap; this is the default, can be removed */
overflow-x: auto;
/*justify-content: space-evenly; removed */
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
}
.item{
flex: 0 0 auto;
background: #e4e4e4;
width: 150px;
height: 75px;
margin: 10px;
}
.item{
margin-left: auto; /* added */
}
.item:last-child{
margin-right: auto; /* added */
}
Too many
<div class="scroll">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<br>Too few
<div class="scroll">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>

Remove justify-content: space-evenly; from .scroll.
Demo:
.scroll{
display: flex;
flex-wrap: nowrap;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: -ms-autohiding-scrollbar;
}
.item{
flex: 0 0 auto;
background: #e4e4e4;
width: 150px;
height: 150px;
margin: 10px;
}
<div class="scroll">
<div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div><div class="item">
</div>
</div>
This will stop the elements from being out of bounds on both sides.
All div's get displayed in a row this way.

.Wrapper {
display: flex;
flex-direction: row;
overflow-x: auto;
max-width: 100%; //this will solve issue
}
.TagWrapper:{
display: flex;
flex-shrink: 0;
}

You can set the position of the Parent or Container to be Relative and the child inside them to be absolute.
.Parent{
display: flex;
// and use any flexbox property
width: 100%;
height: 100%
position: relative; // important point
overflow: auto;
}
.Child{
position: absolute; // important point
}

Related

Making the second item of flex container sticky with CSS

I have flex container that contains two columns.
Each column is a flex container as well.
I wish to make the second item of the side column sticky, so when you scroll down it will stay visible until the end of the page
In my example you can see that I tried with position: sticky;
But it seems like the item gets stick but not all the way to the end of the page.
What am I missing?
I tried some answers like My position: sticky element isn't sticky when using flexbox but I didn’t managed to make it work.
Demo: https://codepen.io/avneri/pen/yLONZVy
.page-container {
display: flex;
justify-content: space-evenly;
}
.column-container {
max-width: 50%;
}
.item-wrapper {
display: flex;
flex-direction: column;
}
.item {
min-width: 150px;
margin: 15px;
padding: 30px;
background: red;
text-align: center;
}
.sticky {
background: green;
position: -webkit-sticky;
position: sticky;
top: 0;
align-self: flex-start;
}
<div class="page-container">
<div class="column-container">
<div class="item-wrapper">
<div class="item">
Item 1
</div>
<div class="item">
Item 2
</div>
<div class="item">
Item 3
</div>
<div class="item">
Item 4
</div>
<div class="item">
Item 5
</div>
...
</div>
</div>
<div class="column-container">
<div class="item-wrapper">
<div class="item">
Side item 1
</div>
<div class="item sticky">
Side item 2
</div>
</div>
</div>
</div>
It's because the second column's inner wrapper doesn't extend to the full height; sticky will not let the element pass the limits of its container.
Try adding height: 100%; as below (I did it with a class):
.page-container {
display: flex;
justify-content: space-evenly;
}
.column-container {
max-width: 50%;
}
.item-wrapper {
display: flex;
flex-direction: column;
}
.item {
min-width: 150px;
margin: 15px;
padding: 30px;
background: red;
text-align: center;
}
.sticky {
background: green;
position: -webkit-sticky;
position: sticky;
top: 0;
align-self: flex-start;
}
.full-height {
height: 100%;
}
<div class="page-container">
<div class="column-container">
<div class="item-wrapper">
<div class="item">
Item 1
</div>
<div class="item">
Item 2
</div>
<div class="item">
Item 3
</div>
<div class="item">
Item 4
</div>
<div class="item">
Item 5
</div>
...
</div>
</div>
<div class="column-container">
<div class="item-wrapper full-height">
<div class="item">
Side item 1
</div>
<div class="item sticky">
Side item 2
</div>
</div>
</div>
</div>

Flexbox showing dynamic number of items with 5 items per row using flex basis to consume extra space

I want to show 5 items per row using flexbox.
.parent-wrapper {
height: 100%;
width: 181px;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: -10px 0 0 -10px;
}
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 10px;
flex: 1 1 calc(100% * (1/5) - 10px - 1px);
height: 100px;
}
<body>
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>
</body>
I want to use the flex grow, so that resize will not affect the data displayed. This code above will stretch the data if the row less than 5 items. If i didnt use the flex grow, it works fine for the view, but when resizing there will show some blank space after the data displayed.
If without flex grow, how can i consume extra space by just using the flex basis
calc(100% * (1/5) - 10px - 1px)
I create example for you, can try
.container {
display: flex;
flex-wrap: wrap;
flex-direction: row;
justify-content: center;
width: 600px;
height: 300px;
border: solid 1px;
align-items: center;
}
.item {
width: 100px;
height: 70px;
margin-right: 5px;
display: inline-block;
border: solid 1px;
}
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
</div
If I understand correctly, it seems that you are looking for the justify-content property. You want to remove space following the items while also preventing them from stretching. By setting justify-content: space-between you can achieve the desired effect. It will create an even space between the items but not after or before. I also set flex-grow: 0 0 as I assume you don't want your items to grow or shrink.
Here is a link to w3schools listing all possible values for justify-content if space-between is not the layout you need. For example, you also have the option to center your items in order to consume the extra space.
.parent-wrapper {
height: 100%;
width: 181px;
border: 1px solid black;
}
.parent {
display: flex;
font-size: 0;
flex-wrap: wrap;
margin: -10px 0 0 -10px;
justify-content: space-between; /* Spaces items evenly between each other */
}
.child {
display: inline-block;
background: blue;
margin: 10px 0 0 10px;
flex: 0 0 calc(100% * (1/5) - 10px - 1px); /* Setting 0 (none) for flex-grow and 0 for flex shrink */
height: 100px;
}
<div class="parent-wrapper">
<div class="parent">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
</div>

Flexbox wrap does not work properly in firefox

Compare example below on chrome and firefox.
It wraps properly on chrome for me, but firefox instead of wrapping, stretches flexbox and overflows parent. So who is right here, chrome or firefox? And how can I achieve same effect as on chrome on both?
html,
body,
#app {
margin: 0;
padding: 0;
}
#app {
height: 100vh;
width: 100vw;
display: flex;
flex-direction: column;
}
#top {
flex: 0 0 40px;
background-color: #ff0000;
}
#content {
flex: 1;
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
.item {
height: 200px;
}
<div id="app">
<div id="top">
</div>
<div id="content">
<div class="item">
1
</div>
<div class="item">
2
</div>
<div class="item">
3
</div>
<div class="item">
4
</div>
<div class="item">
5
</div>
<div class="item">
6
</div>
</div>
</div>
Try setting a min-height and min-width on parent like so
#content {
min-height: 0;
min-width: 0; }

How to create flexible div items that break after the line?

I am trying to create "shopping items" embedded in a div that have a certain fixed width and height. I know that you can do display: inline !important; to keep the div's on one line.
However, how can I make it such that it breaks when the window size becomes smaller, preferably when the outer div is smaller?
Here is an illustration:
Here is what I tried:
<div class="row">
<div class="col-sm-12">
<div class="items">
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
</div>
</div>
</div>
and css:
.items {
display: flex !important;
flex-wrap: wrap !important;
-webkit-flex-wrap: wrap !important;
-moz-flex-wrap: wrap !important;
-o-flex-wrap: wrap !important;
-ms-flex-wrap: wrap !important;
}
.item {
width: 200px !important;
height: 500px !important;
margin: 10px !important;
text-align: center !important;
}
With flex you can also set a breaking point (without mediaquerie) when boxes reaches 200px of width and also span them on the whole line:
(bootstrap included in snippet , i do not really see troubles there)
.row {
text-align: center;
}
.items {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-wrap: wrap;
-ms-flex-wrap: wrap;
flex-wrap: wrap;
-webkit-justify-content: space-around;
-ms-flex-pack: distribute;
justify-content: space-around;
}
.item {
/* with a breaking point at 200px width */
min-width: 200px;
-webkit-box-flex: 1;
-webkit-flex: 1;
-ms-flex: 1;
flex: 1;
/* or without min-width nor flex, just:
width:200px; it will wrap everytime needed and boxes will keep a static width */
height: 150px;/* none or whatever*/
margin: 10px 30px;/* whatever*/
text-align: center;
border: solid;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<div class="row">
<div class="col-sm-12">
<div class="items">
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
</div>
</div>
</div>
So easy like that;
float: left;
You can use CSS Flexbox. Its handles it easily.
Have a look at the snippet below (resize your browser to see them in action):
.outer {
display: flex;
flex-wrap: wrap;
}
.item {
width: 100px;
height: 100px;
padding-top: 10px;
text-align: center;
background: #eee;
border: 3px solid #aaa;
margin: 20px;
}
body {
padding: 20px;
}
<div class="outer">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
Hope this helps!
As an alternative to the other options I would suggest a look at isotope (http://isotope.metafizzy.co/). The benefits of using this over a pure css solution would become more apparent if you decided to include any filtering or sorting of your shopping items.
You can use flex-basis to ensure your elements are always 200px if it cannot grow nor shrink.
Using the flex shorthand property:
flex: 0 0 200px; /* 'flex-grow: 0' 'flex-shrink: 0' 'flex-basis: 200px' */
.items {
display: flex;
flex-wrap: wrap;
justify-content: space-around;
}
.item {
box-sizing: border-box;
flex: 0 0 200px; /* <'flex-grow'> <'flex-shrink'> <'flex-basis'> */
height: 100px;
margin-bottom: .5em; /* Space between flex-items vertically*/
text-align: center;
border: 2px dashed grey;
}
<div class="row">
<div class="col-sm-12">
<div class="items">
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
<div class="item">
<p>Hello</p>
</div>
</div>
</div>
</div>
Notes:
In the demo we use the recommended syntax, which is using
the flex shorthand property.
Do not overuse the !important flag. It should not be needed in any of your classes.
Removed vendor prefixes for demo simplicity.

css flex shrink container width to fit its items

I'm displaying a list of same sized items in a flex div. I've aligned them to the left. However I'd like the list to be centred as a whole. Any suggestions about how to do this?
Please try to snipped below.
$('button').click(function(){
$('.list').toggleClass('hack')
});
.item {
width: 40px;
height: 40px;
background-color: skyblue;
border: 1px solid black;
}
.list-container {
width: 100px;
background-color: grey;
flex-direction: row;
display: flex;
}
.spacer {
flex: 1;
}
.list.hack {
width: 84px;
}
.list {
display: inline-flex;
flex-direction: row;
flex-wrap: wrap;
background-color: yellow;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='list-container'>
<div class='spacer'></div>
<div class='list'>
<div class='item'></div><div class='item'></div>
<div class='item'></div><div class='item'></div>
<div class='item'></div>
</div>
<div class='spacer'></div>
</div>
<button>Toggle fixed list width (hack)</button>
I believe the best way is to insert the "item" elements to a new div, setting:
<div style="margin:0 auto;width: 85px;">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
and also applying .item{float:left;}
It's not enough when you set justify-content: center; to .list?
Then if you need to make the standalone item to be aligned to left, you can set its margin-right: 42px; (to compensate the space next to it)
You can do the same without using flex
HTML
<div class='list'>
<div class='item'>item 1</div><div class='item'>item 2</div>
<div class='item'>item 3</div><div class='item'>item 4</div>
<div class='item'>item 5</div>
</div>
CSS
.list{
display:inline-block;
background-color: grey;
width:100px;
clear:both;
justify-content: center;
}
.list .item{
float:left;
width:48%;
background-color: skyblue;
height: 40px;
border: 1px solid black;
}
.list .item:last-child{
margin-left:25%;
}
Click here for JSFiddle sample