I have a 'calendar' layout using the following css-grid styles:
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: 1.5em 1.5em repeat(6, 1fr);
width: 100%;
height: 100%;
}
(Codepen https://codepen.io/joelhoward0/pen/vJLmWK)
The first two rows are a 'controls' header and days of the week headers, followed by divs for each day in the month:
<div class="day">
<div class="header">26</div>
<div class="content"></div>
</div>
Each day has a .header
and .content
div. I want the .header
div to take up 1/5 of the height of the row, and the content to take up 4/5 and scroll if the content overflows.
However, any combination of styles I've tried just leads to .content
growing, shrinking the other grid rows to compensate. I assume this is due to the use of 1fr
on the container grid-template-rows.
Is it possible to achieve a max height of 4/5 of the grid row height, which is 1/6 of the vertical space available, on the .content
div?
(Note: setting overflow-y: auto;
on .day
achieves what I want, but the header is included in the scrolling area. Setting overflow-y: auto;
on .content
doesn't seem to do anything.)
Although @MichaelB's response is technically correct, I have found that you can actually do it without resorting to specifying heights manually. And it's dead simple to do it too.
In addition to adding overflow:auto
to the grid-item you want scrollbars on, you also need to add an overflow:auto
to the parent of that grid-item.
https://codepen.io/kumarharsh/pen/jejGMm?editors=1100
html,
body {
height: 100%;
}
body {
position: relative;
margin: 0;
}
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: 1.5em 1.5em repeat(6, 1fr);
width: 100%;
height: 100%;
box-sizing: border-box;
border: solid grey;
border-width: 1px 0 0 1px;
position: relative;
}
.dayHeader {
border: solid grey;
border-width: 0 1px 1px 0;
}
.day {
border: solid grey;
border-width: 0 1px 1px 0;
overflow: auto; /* added overflow here! */
}
.content {
overflow-y: auto;
}
.controls {
grid-column-start: 1;
grid-column-end: 8;
border: solid grey;
border-width: 0 1px 1px 0;
}
<div class="calendar">
<div class="controls">July 2017</div>
<div class="dayHeader">Sunday</div>
<div class="dayHeader">Monday</div>
<div class="dayHeader">Tuesday</div>
<div class="dayHeader">Wednesday</div>
<div class="dayHeader">Thursday</div>
<div class="dayHeader">Friday</div>
<div class="dayHeader">Saturday</div>
<div class="day">
<div class="header">25</div>
<div class="content">
this is a lot of content that I want to have scroll instead of just stretching the grid row and forcing the other rows to be smaller to compensate for this one's increased size due
</div>
</div>
<div class="day">
<div class="header">26</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">27</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">28</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">29</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">30</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">1</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">2</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">3</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">4</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">5</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">6</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">7</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">8</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">9</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">10</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">11</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">12</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">13</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">14</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">15</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">16</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">17</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">18</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">19</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">20</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">21</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">22</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">23</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">24</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">25</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">26</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">27</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">28</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">29</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">30</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">31</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">1</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">2</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">3</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">4</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">5</div>
<div class="content"></div>
</div>
</div>
Best of all, It works in all browsers (tested in Firefox, Chrome, and Edge), so it's likely not a hack, but an intended behaviour.
I can't find a clear answer in the spec yet, but I'll keep looking and update here when I have something concrete.
Do read @Victoria's followup comment: CSS Grid row max height 1fr, scroll content which has another way to do it - I'd recommend you use that way if your design allows it.
Each row in the grid (except for the headers) is set to 1fr
height. That means each row will consume an equal proportion of free space in the container.
Just note that fr
sizing doesn't actually define a length – either width
or height
. With fr
you are simply distributing free space.
But for the overflow
property to work, an actual height must be defined:
In order for
overflow
to have an effect, the block-level container must have either a set height (height
ormax-height
) orwhite-space
set tonowrap
.source: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow
Therefore, consider using actual heights as opposed to space distribution. Here's an example:
html,
body {
height: 100%;
}
body {
position: relative;
margin: 0;
}
.calendar {
display: grid;
grid-template-columns: repeat(7, 1fr);
grid-template-rows: 1.5em 1.5em repeat(6, 175px); /* adjusment */
width: 100%;
height: 100%;
box-sizing: border-box;
border: solid grey;
border-width: 1px 0 0 1px;
position: relative;
}
.dayHeader {
border: solid grey;
border-width: 0 1px 1px 0;
}
.day {
height: 175px; /* new */
border: solid grey;
border-width: 0 1px 1px 0;
}
.header { /* new */
height: 20%;
background-color: yellow;
}
.content {
height: 80%; /* new */
overflow-y: auto;
background-color: aqua;
}
.controls {
grid-column-start: 1;
grid-column-end: 8;
border: solid grey;
border-width: 0 1px 1px 0;
}
<div class="calendar">
<div class="controls">July 2017</div>
<div class="dayHeader">Sunday</div>
<div class="dayHeader">Monday</div>
<div class="dayHeader">Tuesday</div>
<div class="dayHeader">Wednesday</div>
<div class="dayHeader">Thursday</div>
<div class="dayHeader">Friday</div>
<div class="dayHeader">Saturday</div>
<div class="day">
<div class="header">25</div>
<div class="content">
this is a lot of content that I want to have scroll instead of just stretching the grid row and forcing the other rows to be smaller to compensate for this one's increased size due
</div>
</div>
<div class="day">
<div class="header">26</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">27</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">28</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">29</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">30</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">1</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">2</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">3</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">4</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">5</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">6</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">7</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">8</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">9</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">10</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">11</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">12</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">13</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">14</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">15</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">16</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">17</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">18</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">19</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">20</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">21</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">22</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">23</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">24</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">25</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">26</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">27</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">28</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">29</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">30</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">31</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">1</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">2</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">3</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">4</div>
<div class="content"></div>
</div>
<div class="day">
<div class="header">5</div>
<div class="content"></div>
</div>
</div>
revised demo
It looks like if you set the header to position: fixed
, set calc(100%/7)
and give it a non-transparent background
. Set .day
to overflow-y:auto
and give your .content
a margin-top
that seems to work as well as keeping the calender fluid to the browser height.
If it's important for the header to be the full width of the day block with borders you can add your current border properties to only the right side and add box-sizing: border-box
.header{
position:fixed;
background: white;
width: calc(100%/7);
border: solid grey;
border-width: 0 1px 0 0;
box-sizing: border-box;
}
.day {
border: solid grey;
border-width: 0 1px 1px 0;
overflow-y: auto;
}
.content {
margin-top: 20px;
}
Demo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With