CSS Grid Cookbook
Creating responsive layout elements
A common pattern for creating responsive layout elements is the following:
grid-template-columns: repeat(auto-fit, minmax(<col width>, 1fr));
The only hard width we're going to set for our element is in the first argument of the minmax()
function; the max width as long as the number of columns will adapt to the available space.
Another useful CSS grid property for responsive layouts is grid-template-areas
, which will set our grid without the need to size any of its rows/cols. When defining responsive media queries, we can simply re-arrange the grid areas to adapt the layout.
.top {
display: grid;
grid-gap: 20px;
grid-template-areas:
"hero hero cta1"
"hero hero cta2"
}
@media (max-width: 500px) {
.top {
grid-template-areas:
"hero"
"cta1"
"cta2"
}
}
The areas "hero hero cta1"
are roughly equivalent to grid-template-columns: 1fr 1fr 1fr
; as for the rows, the browser now knows that an hero
element will span 2 rows. It will then determine the size of our grid rows by reading into the height of our hero
, subtracting the grid-gap
, and dividing by 2.
So with this technique we can "just place our elements" and the browser will figure out the grid for us.
Overlaying items
In CSS Grid it's easy to overlay items w/o resorting to relative-absolute positioning; given:
<div class="item">
<img src="images/img.jpg">
<div class="item__overlay">
<button>View →</button>
</div>
</div>
We can position .item__overlay
on top of img
by creating a 1x1 grid on .item
and setting the two children to cover all the available space:
.item {
overflow: hidden;
display: grid;
grid-template-columns: 1;
grid-template-rows: 1;
}
.item img {
grid-column: 1 / -1;
grid-row: 1 / -1;
width: 100%;
height: 100%;
object-fit: cover;
}
.item__overlay {
background: #ffc60032;
grid-column: 1 / -1;
grid-row: 1 / -1;
position: relative;
display: grid;
justify-items: center;
align-items: center;
transition: 0.2s;
transform: translateY(100%);
}
Splitting space asymmetrically
By declaring a grid w/ only one column and setting grid-auto-flow: column;
, the first item will be assigned the most space, and the remaining items will be automatically sized by implicit columns.
.item {
display: grid;
grid-template-columns: 1fr;
grid-auto-flow: column;
}
Complete Bootstrap-like grid with CSS variables
.grid {
display: grid;
grid-gap: 20px;
grid-template-columns: repeat(var(--cols, 12), minmax(0, 1fr));
grid-auto-flow: dense;
}
.item {
min-width: 0;
width: 100%;
--span: 1;
grid-column: span var(--span);
}
In repeat(var(--cols, 12)
, 12
is a default value; the repeat()
function can accept a 2nd argument.
Notice how in <div class="grid" style="--cols: 10;">
we are declaring the --cols
variable in a style
attribute.
Then, when we want an .item
element to span more than 1 column, we reassign the --span
var in a style
attribute.
<div class="grid" style="--cols: 10;">
<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 class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item" style="--span: 2">11</div>
<div class="item">12</div>
<div class="item">13</div>
<div class="item">14</div>
<div class="item">15</div>
<div class="item">16</div>
<div class="item">17</div>
<div class="item">18</div>
<div class="item">19</div>
<div class="item" style="--span: 3">20</div>
<div class="item">21</div>
<div class="item">22</div>
<div class="item">23</div>
<div class="item">24</div>
<div class="item">25</div>
<div class="item">26</div>
<div class="item">27</div>
<div class="item" style="--span: 4">28</div>
<div class="item">29</div>
<div class="item">30</div>
<div class="item">31</div>
<div class="item">32</div>
<div class="item">33</div>
<div class="item">34</div>
<div class="item" style="--span: 5">35</div>
<div class="item">36</div>
<div class="item">37</div>
<div class="item">38</div>
<div class="item">39</div>
<div class="item">40</div>
<div class="item" style="--span: 6">41</div>
<div class="item">42</div>
<div class="item">43</div>
<div class="item">44</div>
<div class="item">45</div>
<div class="item" style="--span: 7">46</div>
<div class="item">47</div>
<div class="item">48</div>
<div class="item">49</div>
<div class="item" style="--span: 8">50</div>
<div class="item">51</div>
<div class="item">52</div>
<div class="item" style="--span: 9">53</div>
<div class="item">54</div>
<div class="item" style="--span: 10">55</div>
</div>
Set a bottom margin on every layout block, in 2 LOC
CSS Grid will lay out items in a column by default, so we just have to enable grid on our container and set a grid-gap
which will act as a margin-bottom
.
.wrapper {
display: grid;
grid-gap: 20px;
}