Reputation: 97
In this layout I'm using CSS grid with position: absolute
to show a list of items overlaid on top of a map. My problem is the overflow-x: auto
is not getting triggered causing only the first few items to be displayed.
By changing the grid-auto-columns
of the list from minmax(auto, 1fr)
to minmax(0, 1fr)
I do get a scrollbar however the items are then overlapping each other.
CodePen: https://codepen.io/tgel0/pen/ZEbKZvb
.wrapper{
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
height: 100vh;
width: 100vw;
grid-template-areas:
"side side main main"
"side side main main"
}
.side {
grid-area: side;
display: grid;
grid-template-columns: 1fr;
padding: 20px;
color: #fff;
background-color: green;
}
.main {
grid-area: main;
display: grid;
background-color: gray;
grid-template-columns: 1px 1fr 1px;
gap: 20px;
position: relative;
overflow-y: auto;
overflow-x: hidden;
}
.main > * {
grid-column: 1 / -1;
}
.map {
background-image: url("https://lh3.googleusercontent.com/-bQzIWFMAYus/WXy3WDcphBI/AAAAAAAAAMs/unOi6HiEoi4VWaM0WiP5q32q9zDbIhUvwCLcBGAs/s1600/7-29-2017%2B11-14-59%2BAM.jpg");
height: 100%;
overflow: auto;
}
.container-for-items {
display: grid;
grid-template-columns: 10px;
grid-template-rows: 1fr;
grid-auto-columns: minmax(0, 1fr); /* minmax(auto, 1fr); */
grid-auto-flow: column;
grid-gap: 20px;
padding: 20px;
z-index: 99;
position: absolute;
bottom: 20px;
overflow-x: auto;
}
container-for-items:before,
.container-for-items:after {
content: '';
width: 10px;
}
.item {
display: grid;
background-color: white;
border: 2px solid blue;
padding: 25px;
width: 300px;
height: 150px;
}
<div class="wrapper">
<div class="side">Don't scroll</div>
<div class="main">
<div class="map"></div>
<ul class="container-for-items">
<li class="item">This is item 1</li>
<li class="item">This is item 2</li>
<li class="item">This is item 3</li>
<li class="item">This is item 4</li>
<li class="item">This is item 5</li>
<li class="item">This is item 6</li>
<li class="item">This is item 7</li>
<li class="item">This is item 8</li>
<li class="item">This is item 9</li>
<li class="item">This is item 10</li>
<li class="item">This is item 11</li>
</ul>
</div>
</div>
Upvotes: 3
Views: 554
Reputation:
To enable scrolling an element must meet two rules:
overflow
set to auto
or scroll
In your case rule 1 is not honored.
We can simply add a a width to the grid and it will work as expected.
.wrapper{
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
height: 100vh;
width: 100vw;
grid-template-areas:
"side side main main"
"side side main main"
}
.side {
grid-area: side;
display: grid;
grid-template-columns: 1fr;
padding: 20px;
color: #fff;
background-color: green;
}
.main {
grid-area: main;
display: grid;
background-color: gray;
grid-template-columns: 1px 1fr 1px;
gap: 20px;
position: relative;
overflow-y: auto;
overflow-x: hidden;
}
.main > * {
grid-column: 1 / -1;
}
.map {
background-image: url("https://lh3.googleusercontent.com/-bQzIWFMAYus/WXy3WDcphBI/AAAAAAAAAMs/unOi6HiEoi4VWaM0WiP5q32q9zDbIhUvwCLcBGAs/s1600/7-29-2017%2B11-14-59%2BAM.jpg");
height: 100%;
overflow: auto;
}
.container-for-items {
display: grid;
grid-template-columns: 10px; /* this is making the first column shorter than the grid item so it will be overlapped by the next element */
grid-template-rows: 1fr;
/* removed columns rule */
grid-auto-flow: column;
grid-gap: 20px;
padding: 20px;
z-index: 99;
position: absolute;
bottom: 20px;
overflow-x: auto;
width:100%; /* Added */
}
container-for-items:before,
.container-for-items:after {
content: '';
width: 10px;
}
.item {
display: grid;
background-color: white;
border: 2px solid blue;
padding: 25px;
width: 300px;
height: 150px;
}
<div class="wrapper">
<div class="side">Don't scroll</div>
<div class="main">
<div class="map"></div>
<ul class="container-for-items">
<li class="item">This is item 1</li>
<li class="item">This is item 2</li>
<li class="item">This is item 3</li>
<li class="item">This is item 4</li>
<li class="item">This is item 5</li>
<li class="item">This is item 6</li>
<li class="item">This is item 7</li>
<li class="item">This is item 8</li>
<li class="item">This is item 9</li>
<li class="item">This is item 10</li>
<li class="item">This is item 11</li>
</ul>
</div>
</div>
In the snippet above you can see i removed grid-auto-columns
all together. Why?
First The grid is an absolutely positioned element which means it will depend on it's content to define it's width.
minmax(auto, 1fr);
Which is basically the same as 1fr
means a grid track/columns
cannot be smaller than the grid item's content, this will prevent the grid from shrinking but you can't see it because overflow is hidden on .main
therefore no scrollbars.
Changing to minmax(0, 1fr);
in this case the track/columns
can be whatever it needs to be, so if we only have few items the track/columns
will be equal to the grid item.
However if we keep adding items the grid will keep growing eventually it will stop when it hits the right edge of it's parent the track/columns
inside will shrink to fit (1fr
) but the grid items will overlap because they're wider than the track/columns
The grid stops growing in this case because it doesn't care about the content courtesy of minmax(0, 1fr);
and overflow:auto
so it fallsback to normal behavior of white-space wrapping but since it's a grid it can't wrap so they overlap.
Demo
body * {
padding: 10px;
border: 1px solid;
}
[positioned] {
border: 1px solid;
position: relative;
background: pink;
height: 150px;
width: 300px;
/* white-space:nowrap; un comment this line to see */
}
[grid] {
background: red;
position: absolute;
}
[item] {
background: orange;
display: inline-block;
width: 100px;
height: 100px;
animation :grow 10s linear infinite alternate;
}
@keyframes grow {
from {
width: 10px;
}
}
As childs grow the parent's grow as well but it stops when it hits the right edge of the parent, Normal overflow behaviour
<div positioned>
<div grid>
<div item></div>
<div item></div>
<div item></div>
</div>
</div>
Upvotes: 3
Reputation: 371231
There's a lot going on this layout—nested grids, absolute positioning, pseudo elements, a background image, and a lot of seemingly unnecessary code—so algorithms may be conflicting (e.g., I keep getting different renderings on Chrome/FF vs Edge).
I think the simplest solution is to remove all unnecessary code, absolutely position the image (not the container), and simplify the grid structures.
No changes are necessary in the HTML.
.wrapper{
display: grid;
grid-template-columns: 0.5fr 0.5fr 1fr 1fr;
grid-template-rows: 1fr 1fr;
height: 100vh;
/* width: 100vw; */
grid-template-areas:
"side side main main"
"side side main main"
}
.side {
grid-area: side;
display: grid;
/* grid-template-columns: 1fr; */
padding: 20px;
color: #fff;
background-color: green;
}
.main {
grid-area: main;
display: grid;
background-color: gray;
/* grid-template-columns: 1px 1fr 1px; */
gap: 20px;
position: relative;
/* overflow-y: auto; */
/* overflow-x: hidden; */
}
/* .main > * {
grid-column: 1 / -1;
} */
.map {
background-image: url("https://lh3.googleusercontent.com/-bQzIWFMAYus/WXy3WDcphBI/AAAAAAAAAMs/unOi6HiEoi4VWaM0WiP5q32q9zDbIhUvwCLcBGAs/s1600/7-29-2017%2B11-14-59%2BAM.jpg");
height: 100vh; /* adjustment */
width: 100%; /* new */
position: absolute; /* new */
/* overflow: auto; */
}
.container-for-items {
display: grid;
/* grid-template-columns: 10px; */
grid-template-rows: 150px; /* adjustment; from grid items */
grid-auto-columns: 300px; /* adjustment; from grid items */
/* grid-auto-flow: column; */
grid-gap: 20px;
padding: 20px;
z-index: 99;
/* position: absolute; */
/* bottom: 20px; */
align-self: end; /* new */
overflow-x: auto;
position: relative; /* for Edge */
}
/* reverse collapsing margin at container end */
/* https://stackoverflow.com/q/38993170/3597276 */
/* .container-for-items:before (unnecessary; remove) */
.container-for-items:after {
content: '';
width: 10px;
grid-row: 1;
}
.item {
grid-row: 1; /* new */
display: grid;
background-color: white;
border: 2px solid blue;
padding: 25px;
/* width: 300px; */ /* move to grid-template-columns */
/* height: 150px; */ /* move to grid-template-rows */
}
/* new */
body {
margin: 0;
}
* {
box-sizing: border-box;
}
<div class="wrapper">
<div class="side">Don't scroll</div>
<div class="main">
<div class="map"></div>
<ul class="container-for-items">
<li class="item">This is item 1</li>
<li class="item">This is item 2</li>
<li class="item">This is item 3</li>
<li class="item">This is item 4</li>
<li class="item">This is item 5</li>
<li class="item">This is item 6</li>
<li class="item">This is item 7</li>
<li class="item">This is item 8</li>
<li class="item">This is item 9</li>
<li class="item">This is item 10</li>
<li class="item">This is item 11</li>
</ul>
</div>
</div>
Upvotes: 2