---
tags: COMP-1850
---
<style>
.markdown-body h1:first-of-type {
margin-top: 24px;
}
.markdown-body h1 {
margin-top: 64px;
}
.markdown-body h1 + h2 {
margin-top: 32px;
}
.markdown-body h2 {
margin-top: 48px;
}
.markdown-body h3 {
color: cornflowerblue;
}
.exercise {
font-size: 150%;
font-weight: bold;
color: rgb(227,112,183);
}
.note {
color: red;
}
</style>
## Advanced Page Layout: CSS Grid
CSS Grid is a responsive, ==two-dimensional== (both horizontal and vertical) layout method that allows us to easily create complex layouts for the web.
Similar to CSS Flexbox, CSS Grid requires any elements you want to lay out to have a ==parent== element whose display value is set to `grid` or `inline-grid`.
The number of columns and rows in a grid are defined by two properties: `grid-template-columns` and `grid-template-rows`
Below is an example of a grid with three columns and three rows:
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
background-color: #aaa;
}.
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
```
<style>
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
background-color: #aaa;
}
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
</style>
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
<br>
In the simple example above, we are creating a grid of three columns and three rows by explicitly defining a size for each, i.e.:
`grid-template-columns: 100px 100px 100px;`
means we want three columns in total, each with a fixed width of 100px. The same is true of the value for `grid-template-rows`, so we get a grid of 9 equally sized squares.
Note that the child elements, the cyan, magenta, and yellow divs __do not__ explicitly have their dimensions defined – they are 100px square because they are filling the width and height of the column and row respectively.
### Units of measurement for columns and rows
In the previous example we used fixed widths and heights, but there are several ways we can defined _responsive_ dimensions. The `auto` keyword for a particular column or row means "take up as much empty space as possible". Similarly, the `fr` unit (for 'fraction') means "take up a _fraction_" of the remaining empty space"
Here is an example of two fixed columns with one `auto` column:
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px auto 100px;
grid-template-rows: 100px auto 100px;
background-color: #aaa;
}.
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
```
<style>
.auto {
grid-template-columns: 100px auto 100px;
}
</style>
<div class="grid auto">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
<br>
and an example of three columns that equally take up a 'fraction' of the available space (in this case, one third). Note that for this example we have to define a width and height for the grid itself (600px x 600px), so that the browser knows how to calculate a fractional width/height for the child elements:
<br>
```
CSS:
.grid {
width: 600px;
height: 600px;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
background-color: #aaa;
}.
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
```
<style>
.fr {
width: 600px;
height: 600px;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
</style>
<div class="grid fr">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
<br>
### The repeat() function
In cases where we have several columns that are all the same width (or rows that are the same height), we can use the `repeat()` function as a shorthand for declaring values.
Imagine a 12 column grid with equally sized 40px columns. Without using `repeat()` we would have to write:
`grid-template-columns: 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px 40px;`
Tiring to type and easy to write incorrectly! Instead we can tell the browser we want 12 _repeated_ columns of 40px, like this:
`grid-template-columns: repeat(12, 40px);`
The repeat function can also be mixed in with other values:
`grid-template-columns: 10px repeat(12, 40px) 10px;`
Perfect for defining small gutters on the right and left-hand side of a grid.
### The minmax() function
For _responsively_ sized child grid items, we can use the `fr` or `auto` values mentioned above, or we can use responsive units like `%` and `vw`. Additionally, CSS allows us to define a ==range== of sizes for our child items using the `minmax()` function.
The `minmax()` function takes two arguments, the _minimum_ size and the _maximum_ size. Below is an example of columns that should be greater than or equal to a _minimum_ value (100px) but less than or equal to a _maximum_ value (200px). Try resizing your browser to see how the child elements start shrinking at smaller viewport widths:
```
CSS:
.grid {
display: grid;
grid-template-columns: repeat(3, minmax(100px, 200px));
grid-template-rows: repeat(3, minmax(100px, 200px));
background-color: #aaa;
}.
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
```
<style>
.minmax {
grid-template-columns: repeat(3, minmax(100px, 200px));
grid-template-rows: repeat(3, minmax(100px, 200px));
}
</style>
<div class="grid minmax">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
### Column and row gaps
CSS Grid allows us to define gaps (empty spaces) between columns and/or rows using the `column-gap` and `row-gap` properties, or the shorthand `gap` property that sets both.
Below is a variation of our first example, a 3x3 grid, with the addition of a 20 pixel gap between the columns and rows:
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
gap: 20px 20px;
background-color: #aaa;
}.
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
```
<style>
.grid-gap {
gap: 20px 20px;
}
</style>
<div class="grid grid-gap">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
</div>
<br>
### Alignment of child items
In the examples above, child items inside a grid automatically fill the width and height of their columns and rows respectively. This behaviour is due to the default value of two grid properties: `justify-items` (which controls alignment along the row axis) and `align-items` (which controls alignment along the column axis).
By default both these properties are set to a value of `stretch`, but by changing them to one of `start`, `center`, or `end` we can change how items are aligned within their grid cell.
Below is an example of circular elements centered inside their grid positions:
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-items: center;
align-items: center;
background-color: #aaa;
}.
.grid > div {
width: 50px;
height: 50px;
border-radius: 50px;
}
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
</div>
```
<style>
.grid-align {
justify-items: center;
align-items: center;
}
.grid-align > div {
width: 50px;
height: 50px;
border-radius: 50px;
}
</style>
<div class="grid grid-align">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
</div>
<br>
and the same grid with values of `start` for both `justify-items` and `align-items`:
<style>
.grid-align-s {
justify-items: start;
align-items: start;
}
.grid-align-s > div {
width: 50px;
height: 50px;
border-radius: 50px;
}
</style>
<div class="grid grid-align-s">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
</div>
<br>
## CSS Grid properties for child elements
As with Flexbox, most Grid properties (including those above) are intended to be declared on a parent element, however several child properties exist that allow us to size and place elements within a grid.
### `grid-column-start` and `grid-column-end`
The `grid-column-start` and `grid-column-end` properties allow us to place a child item on a specific column and fill as many columns as we specify.
Below is an example of a child item that begins on the second column of a three column grid, and ends on the third column:
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
background-color: #aaa;
}.
.bg-lgrey {
background-color: #eee;
}
.bg-cyan {
grid-column-start: 2;
grid-column-end: 4;
background-color: cyan;
}
HTML:
<div class="grid">
<div class="bg-lgrey"></div>
<div class="bg-cyan"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
</div>
```
<style>
.grid-col {
gap: 10px 10px
}
.grid-col .bg-cyan {
grid-column-start: 2;
grid-column-end: 4;
}
.bg-lgrey {
background-color: #eee;
}
</style>
<div class="grid grid-col">
<div class="bg-lgrey"></div>
<div class="bg-cyan"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
</div>
<br>
<span class="note">Note that in the above example we used the value '4' for the ending column – that is because the numbers refer to the __lines__, not the columns themselves, i.e. we have a three column grid with four __lines__
```
|1| column one |2| column two |3| column three |4|
```
<br>
### `grid-row-start` and `grid-row-end`
Below is an example similar to the previous example, but adding values for `grid-row-start` and `grid-row-end`
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
background-color: #aaa;
}.
.bg-lgrey {
background-color: #eee;
}
.bg-cyan {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 2;
grid-row-end: 4;
background-color: cyan;
}
HTML:
<div class="grid">
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-cyan"></div>
<div class="bg-lgrey"></div>
</div>
```
<style>
.grid-row {
gap: 10px 10px
}
.grid-row .bg-cyan {
grid-column-start: 2;
grid-column-end: 4;
grid-row-start: 2;
grid-row-end: 4;
}
.bg-lgrey {
background-color: #eee;
}
</style>
<div class="grid grid-row">
<div class="bg-lgrey"></div>
<div class="bg-cyan"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
<div class="bg-lgrey"></div>
</div>
<br>
### `grid-row`, `grid-column`, and the `span` value
The `grid-row` and `grid-column` properties are shorthand for column start/end and row start/end, and have a special slash syntax for specifying start and end lines:
```
grid-column: 2 / 4
```
declares that our child must start at line 2, and end at line 4. Likewise we can simplify the previous example of a square to:
```
grid-column: 2 / 4;
grid-row: 2 / 4;
```
An alternative to specifying particular lines is using the `span` value. Below are a few examples:
```
grid-column: 2 / span 2; /* start at line 2, span 2 columns */
grid-row: 2 / span 2; /* start at line 2, span two rows */
```
```
grid-row: span 3; /* start at the first line, span three rows */
```
<br>
### `justify-self` and `align-self`
Similar to Flexbox, we can override the parent values of justify-items and align-items on a _per-child_ basis.
Below is an example of overriding both properties for the whitered item in the grid:
```
CSS:
.grid {
display: grid;
grid-template-columns: 100px 100px 100px;
grid-template-rows: 100px 100px 100px;
justify-items: center;
align-items: center;
background-color: #aaa;
}.
.grid > div {
width: 50px;
height: 50px;
border-radius: 50px;
}
.bg-cyan {
background-color: cyan;
}
.bg-magenta {
background-color: magenta;
}
.bg-yellow {
background-color: yellow;
}
.bg-white {
background-color: white;
justify-self: end;
align-self: start;
}
HTML:
<div class="grid">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-magenta"></div>
<div class="bg-whiteblack"></div>
<div class="bg-cyan"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
</div>
```
<style>
.bg-white {
background-color: whiteblack;
justify-self: end;
align-self: start;
}
</style>
<div class="grid grid-align">
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
<div class="bg-yellow"></div>
<div class="bg-magenta"></div>
<div class="bg-white"></div>
<div class="bg-cyan"></div>
<div class="bg-yellow"></div>
<div class="bg-cyan"></div>
<div class="bg-magenta"></div>
</div>
<br>
<span class="exercise" id="a5b">Assignment 5b: Recreating Assignment 5a using CSS Grid</span>
For assignment 5b you must remake the page you created for the previous assignment with the following caveats:
1. On mobile devices (600px or smaller) the images must display in a single column rather than a grid
2. On mobile devices the images must fill the column, i.e. take up approximately 100% of the width of the screen (margins on the left and right side are allowed)
For your submission, zip your .html and .css files together and submit them to the assignment 5b dropbox as firstname-lastname-a5b.zip (where firstname and lastname are your actual first and last names)
## Optional Reading Before Next Class
- [HTML Forms](https://developer.mozilla.org/en-US/docs/Learn/Forms)
- [HTML Form Validation](https://developer.mozilla.org/en-US/docs/Learn/Forms/Form_validation) - up to but not including 'Validating forms using JavaScript'
## Tasks To Complete Before Next Class
- [ ] Complete [assignment 5b](#a5b)
- [ ] (Optionally) complete the [readings](#Optional-Reading-Before-Next-Class)
---