Grid Layout allows you to create responsive two-dimensional, grid-based designs. It provides a way to define rows and columns in a container and position elements within those grid cells. Apply `display: grid` to an element to make it a grid container. Direct children of the grid become grid items. - `grid-template-rows` & `grid-template-columns`: Defines explicit grid tracks. - Example: `grid-template-columns: 1fr 1fr 1fr;` creates three equal-width columns. - `grid-template`: Shorthand for defining rows and columns at once. - `grid-teplate: 50px 50px / 50px 50px 50px;` creates a 2-row by 3-column grid. - `grid-template-areas`: Defines named grid areas. - `grid-area`: Place elements in defined grid areas. - `gap`, `column-gap`, & `row-gap`: Create spacing between grid items. The below code creates a 3x3 grid. "Grid lines" are used to position grid items. Grid lines are the space between columns and rows, numbered starting from 1. Grid lines are created _implicitly_ whenever we create grid tracks. "Grid tracks" are the space between two adjacent grid lines. Every track has a start line and an end line. The lines are numbered left-to-right, top-to-bottom. ### Example: Simple 3x3 Grid A grid "cell" is the space shared by a single row track and single column track. ```css .container { display: grid; grid-template-rows: 50px 50px 50px; /* Three 50px length rows */ grid-template-columns: 50px 50px 50px; /* Three 50px length columns */ } ``` <html> <body> <div class="container" style=" display: grid; grid-template-rows: 50px 50px 50px; grid-template-columns: 50px 50px 50px;"> <div class="red-border">Cell A</div> <div class="red-border">Cell B</div> <div class="red-border">Cell C</div> <div class="red-border">Cell D</div> <div class="red-border">Cell E</div> <div class="red-border">Cell F</div> <div class="red-border">Cell G</div> <div class="red-border">Cell H</div> <div class="red-border">Cell I</div> </div> </body> </html> > [!tip] On the shorthand `grid-template` >`grid-template: row-length row-length / col-length` is equivalent to... > >`grid-template-rows: row-length row-length` >`grid-template-columns: col-length` > >However, prefer to use separate properties. They're more readable and maintainable. # Implicit Tracks If you place an item outside of the defined grid, CSS Grid will automatically create additional grid tracks to accommodate it. By default, CSS Grid will add additional content with implicit rows. However, that can be changed by applying `grid-auto-flow: column;`. Notably, the track sizes will not be applied to the implicit grid. But we can set implicit grid track sizes using the `grid-auto-rows` and `grid-auto-columns` properties. For example, the below code will create an explicit 2x2 grid, but a fifth item added to the container will be automatically slotted into a third row— an implicit grid. ```css .container { display: grid; grid-template-rows: 50px 50px; /* Two 50px length rows */ grid-template-columns: 100px 100px; /* Two 100px length columns */ } ``` <div class="container debug-grid" style=" display: grid; grid-template-rows: 50px 50px; grid-template-columns: 100px 100px; "> <div class="red-border">Item 1</div> <div class="red-border">Item 2</div> <div class="red-border">Item 3</div> <div class="red-border">Item 4</div> <div style="border: 1px dashed red;">Item 5</div> </div> The below code defines the implicit grid track row size: ```css .container { display: grid; grid-template-rows: 50px 50px; grid-template-columns: 100px 100px; grid-auto-rows: 75px; /* Sets the implicit grid track row size */ } ``` <div class="container debug-grid" style=" display: grid; grid-template-rows: 50px 50px; grid-template-columns: 100px 100px; grid-auto-rows: 75px; "> <div class="red-border">Item 1</div> <div class="red-border">Item 2</div> <div class="red-border">Item 3</div> <div class="red-border">Item 4</div> <div style="border: 1px dashed red">Item 5</div> </div> # Gap The gap between grid rows and columns is known as the "gutter" or "alley." `row-gap` & `column-gap` properties can set the gap sizes. `gap` is a shorthand property for setting both the row & column gaps, this is used most commonly. ```css .container { display: grid; grid-template-columns: 50px 50px; grid-template-rows: 50px 50px; gap: 4px 12px; /* row gap, column gap */ } ``` <div class="container" style=" display: grid; grid-template-columns: 50px 50px; grid-template-rows: 50px 50px; gap: 4px 12px; "> <div class="red-border">Item 1</div> <div class="red-border">Item 2</div> <div class="red-border">Item 3</div> <div class="red-border">Item 4</div> </div> # Units (`auto`, `fr`, & more) Various units can be used in grids: - The usual: `em`, `rem`, `vw`, `vh`, `px`, etc. - Percentages (%): Define sizes relative to the grid container's size. - `fr` (fractional units): Distributes available space proportionally. - e.g. `1fr 2fr` divides space into three parts, with second column taking 2x width. ###### `auto` `auto` automatically takes up appropriate space. - Row height sizes to fit its content. May collapse to 0 height if no minimum set. - Column expands to fill available space after fixed-width columns are accounted for. ```css grid-template-rows: auto 40px auto; grid-template-columns: 100px auto 100px; ``` <div class="container" style=" display: grid; grid-template-rows: auto 40px auto; grid-template-columns: 100px auto 100px; "> <div class="red-border">1</div> <div class="red-border">2 (Column expands to fill remaining space)</div> <div class="red-border">3 (Column: 100px)</div> <div class="red-border">4 (Row: 40px)</div> <div class="red-border">5</div> <div class="red-border">6</div> <div class="red-border" style="">7 (Accommodates intrinsic height of 100px)</div> <div class="red-border">8</div> <div class="red-border">9</div> </div> ###### `min-content` & `max-content` - `min-content`: the smallest size a grid track can have without overflowing its contents. - `max-content`: the largest size a grid track can have to fit its contents without causing overflow. ```css grid-template-columns: min-content max-content 1fr; ``` <div class="container" style=" display: grid; grid-template-columns: min-content max-content 1fr; "> <div class="red-border">min-content: For text, width of the longest word.</div> <div class="red-border">max-content: For text, width needed to display without line breaks.</div> <div class="red-border">1fr</div> </div> # Utility functions #### Sizing functions - `minmax(min, max)`: Sets minimum and maximum sizes for grid track. - Can only be used with `grid-template-rows`, `grid-auto-rows`, & column equivalents. - `clamp(minimum-size, ideal-size, maximum-size)`: allows item to resize until it reaches min or max threshold. - `fit-content(arg)`: Allows a grid track to grow to accommodate its content, up to a specified maximum. - `fit-content(100px)`: grows to accommodate content, but won't exceed 100px. - It's similar to `minmax(auto, max-content)`, but with an upper limit. #### repeat() - `repeat(count, track size)`: Useful helper for simplifying code. - e.g. `grid-auto-rows: repeat(2, 20px)` is equivalent to `grid-auto-rows: 20px 20px` - Useful for dynamic columns: `repeat(auto-fit, minmax(100px, 1fr));` ###### Dynamic columns: `auto-fit` and `auto-fill` - `auto-fit` and `auto-fill` dynamically update the number of columns based on the grid size. - Both return the largest possible positive integer without the grid items overflowing their container. - What's the difference between the two? - `auto-fill`: Creates a fixed number of tracks based on the container width, regardless of the number of items. Some tracks may be empty. - `auto-fit`: Creates only as many tracks as needed for the items and then expands these tracks to fill the container width. There are no empty tracks. **Auto-fill example:** This creates a grid with a consistent number of columns that wraps to the next line when there's not enough space. Each column will be at least 100px wide. _The empty space to the right is actually empty columns._ ```css .container { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); } ``` <html> <div style=" display: grid; grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));"> <div class="red-border">1</div> <div class="red-border">2</div> <div class="red-border">3</div> <div class="red-border">4</div> </div> </html> **Auto-fit example:** This creates a grid where items expand to fill the entire width of the container, with each item being at least 100px wide. ```css .container { grid-template-columns: repeat(auto-fit, minmax(100px, 1fr)); } ``` <html> <div style=" display: grid; grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));"> <div class="red-border">1</div> <div class="red-border">2</div> <div class="red-border">3</div> <div class="red-border">4</div> </div> </html> # Grid Area Grid area allows you to define and name specific regions within your grid container. Define areas using the `grid-template-areas` property on the grid container. - Each string represents a row, each word represents a cell. - Each '.' represents an empty cell. The below is an example of a grid containing three named areas: header, sidebar, and content. ```css .container { display: grid; grid-template-rows: auto 1fr auto; grid-template-columns: 120px 1fr 1fr 1fr; grid-template-areas: 'header header header header' 'sidebar main main .' 'footer footer footer footer'; } .header { grid-area: header; } .sidebar { grid-area: sidebar; } .main { grid-area: main; } .footer { grid-area: footer; } ``` <html> <body> <div class="container" style=" display: grid; grid-template-rows: auto 1fr auto; grid-template-columns: 120px repeat(3, 1fr); grid-template-areas: 'header header header header' 'sidebar main main .' 'footer footer footer footer' "> <div class="red-border" style="grid-area: header">Grid area: Header (full-width x auto)</div> <div class="red-border" style="grid-area: sidebar">Grid area: Sidebar (120px x 1fr)</div> <div class="red-border" style="grid-area: main">Grid area: Main (2fr x 1fr)</div> <div class="red-border" style="grid-area: footer">Grid area: Footer (1fr x 1fr)</div> </div> </body> </html> ### `grid-column` / `grid-row` > [!NOTE] grid-template-areas versus grid-column & grid-row > You can also place grid items using the `grid-column` and `grid-row` properties. > Both approaches are used equally by advanced developers. The above grid area could have also been filled using the `grid-column` and `grid-row` properties: <html> <body> <div class="container" style=" display: grid; grid-template-rows: auto 1fr auto; grid-template-columns: 120px repeat(3, 1fr); "> <div class="red-border" style="grid-column: 1 / -1; grid-row: 1;">grid-col: 1 / -1; grid-row: 1;</div> <div class="red-border" style="grid-column: 1; grid-row: 2;">grid-column: 1; grid-row: 2;</div> <div class="red-border" style="grid-column: 2 / -2; grid-row: 2;">grid-column: 2 / -2; grid-row: 2;</div> <div class="red-border" style="grid-column: 1 / -1; grid-row: 3;">grid-column: 1 / -1; grid-row: 3;</div> </div> </body> </html> #### When to use `grid-template-areas`versus `grid-column` / `grid-row`? Prefer `grid-template-areas` for: - Complex layouts: a visual representation that's easier to conceptualize and maintain. - Responsive design: allows for complete layout restructuring at different breakpoints by simply redefining the template using media queries. Prefer `grid-row` / `grid-column` for: - Numeric precision: when need items to span a specific number of grid tracks or align to exact gird lines. - Dynamic content: if layout adapts to changing content or user interaction, it's often easier to manipulate numeric values programmatically using JavaScript. - Flexibility: for small adjustments, changing numeric values is often quicker and doesn't require redefining the entire grid template.