facebook google plus twitter
Webucator's Free Introduction to CSS Tutorial

Lesson: Layouts

Welcome to our free Introduction to CSS tutorial. This tutorial is based on Webucator's Introduction to CSS Training course.

CSS provides multiple layout systems that can be mixed and matched to give incredible control over the layout of your pages. We will be briefly looking at three of them:

  1. Flexible Box Layout Module
  2. Grid Layout
  3. Multi-column Layout

Lesson Goals

  • Understand the basics of CSS Flexbox Layout.
  • Understand the basics of CSS Grid Layout.
  • Understand the basics of CSS Multi-column Layout.

Introduction to Flexible Box Layout Module

The CSS Flexible Box Layout Module (or "Flexbox", as it's commonly known) offers a handy way to control the horizontal and vertical arrangement of elements on a page. As the W3C description (https://www.w3.org/TR/css-flexbox-1/#abstract) states:

In the flex layout model, the children of a flex container can be laid out in any direction, and can "flex" their sizes, either growing to fill unused space or shrinking to avoid overflowing the parent. Both horizontal and vertical alignment of the children can be easily manipulated.

Some Flexbox Properties

Below are some common Flexbox properties:

Flexbox Properties
Property Explanation
display To create flexible boxes, the display of the parent element of the elements you wish to turn into flexible boxes must be flex.
flex-direction flex-direction sets the direction of the flex container to be either horizontal or vertical. If it is horizontal the child flexible boxes are side by side. If it is vertical, the child flexible boxes are placed on top of each other.
flex-wrap flex-wrap sets whether or not the flexible boxes will wrap to a new line if they overflow their container.
flex-flow flex-flow is shorthand for flex-direction and flex-wrap.
flex flex is shorthand for the flex-grow, flex-shrink, and flex-basis properties and is used to set how flexible boxes take up the space of their container.

Here are some further explanations with examples:

flex-flow

flex-flow takes one value for either flex-direction or flex-wrap, or two values for both together (order doesn't matter).

Common flex-direction values are:

  1. row - child flexible boxes are side by side. Flexbox row Example
  2. column - child flexible boxes are stacked on top of each other. Flexbox column Example

flex-direction (https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction) also has takes row-reverse and column-reverse values to display the elements in reverse order.

Common flex-wrap values are:

  1. wrap - Flexible boxes wrap if there is not enough space. Flexbox column Example
  2. nowrap - Flexible boxes extend outside of their container if there is not enough space. Flexbox column Example

flex-wrap (https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap) also has takes a wrap-reverse value to display the elements in reverse order.

These examples can be found in Layouts/Demos/flex-flow-examples.html.

flex

flex is shorthand for the flex-grow, flex-shrink, and flex-basis properties, but generally just takes one of the following values:

  1. initial - The default value. The flexible box is sized by its width and height properties and shrinks to its minimum size to fit in its container.
  2. auto - The flexible box is sized by its width and height properties, but grows to take up any extra space available in its container.
  3. none - The flexible box is inflexible. It is sized by its width and height properties, but does not shrink or grow in relation to its container.
  4. A positive, unitless number - The flexible box takes up the specified proportion of its container. For example, if there are two boxes, one with flex set to 1 and one with flex set to 2, then the box with flex: 2 will take up twice as much space as the other one.

Below you can see a basic Flexbox demo:

Code Sample:

Layouts/Demos/flexbox-styles.css
body {
  background: aliceblue;
}

main {
  background: white;
  width: 98%;
  margin: auto;
}

section {
  border: 1px solid black;
  display: flex;
  flex-flow: row wrap;
  margin: 0.5rem auto;
}

section article {
  border: 1px solid black;
  border-radius: 0.5rem;
  flex: 1;
  padding: 0.5rem;
  margin: 0.5rem;
  min-width: 200px;
}

h2 {
  width: 100%;
  margin-left: 0.5rem;
}

section article:target {
  flex: 3;
}

section article:target h3 {
  text-decoration: underline;
}

Code Sample:

Layouts/Demos/flexbox.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Basic Flexbox</h1>
<nav>
  <ol>
    <li><a href="#article1">Article 1</a></li>
    <li><a href="#article2">Article 2</a></li>
    <li><a href="#article3">Article 3</a></li>
    <li><a href="#article4">Article 4</a></li>
    <li><a href="#article5">Article 5</a></li>
    <li><a href="#article6">Article 6</a></li>
  </ol>
</nav>
<main>
  <section id="articles">
    <h2>Articles</h2>
    <article id="article1">
      <h3>Article 1</h3>
      <p>Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
        
---- C O D E   O M I T T E D ----

    </article>
    <article id="article2">
      <h3>Article 2</h3>
      <p>Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
        
---- C O D E   O M I T T E D ----

    </article>
    <article id="article3">
      <h3>Article 3</h3>
      <p>Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
        
---- C O D E   O M I T T E D ----

    </article>
    <article id="article4">
      <h3>Article 4</h3>
      <p>Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
        
---- C O D E   O M I T T E D ----

    </article>
    <article id="article5">
      <h3>Article 5</h3>
      <p>Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
        
---- C O D E   O M I T T E D ----

    </article>
    <article id="article6">
      <h3>Article 6</h3>
      <p>Lorem ipsum dolor 
        sit amet, consectetur adipiscing elit. 
        Curabitur tristique odio ac sem congue luctus.
        
---- C O D E   O M I T T E D ----

    </article>
  </section>
</main>
</body>
</html>

Code Explanation

The code above will render the following:Flexbox Demo

Some things to note:

  1. You will need to open Layouts/Demos/flexbox.html in the browser and click the article links to see the effect.
  2. The articles are the flexible boxes. They are set to be in rows and to wrap. They are set to have a flex value of 1 by default.
  3. The target article is given a flex value of 3. article1 is the target in this image.

Introduction to Grid Layout

Grid offers a convenient, powerful method for laying out elements on a page. As the W3C specification states (https://www.w3.org/TR/css-grid-1/#abstract):

This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a predefined flexible or fixed-size layout grid.

Some Grid Properties

Below are some common Grid properties:

Grid Properties
Property Explanation
display To create a grid, the display of the parent element of the elements you wish to layout in a grid must be grid.
grid-template-columns grid-template-columns sets the size and number of columns in the grid container.
grid-template-rows grid-template-rows sets the size and number of rows in the grid container.
grid-auto-columns If grid-template-rows is used to create rows, then columns are generated implicitly (automatically). grid-auto-columns sets the size of these implicitly-generated columns if they are not explicitly defined by the grid-template-columns property.
grid-auto-rows If grid-template-columns is used to create rows, then rows are generated implicitly (automatically). grid-auto-rows sets the size of these implicitly-generated columns if they are not explicitly defined by the grid-template-rows property.
gap gap sets the space between rows and columns.
grid-column grid-column sets an element's horizontal position and size by specifying where it starts and ends along the columns in the grid container.
grid-row grid-row sets an element's vertical position and size by specifying where it starts and ends along the rows in the grid container.

Here are some further explanations with examples:

grid-template-columns and grid-template-rows

Some common grid-template-columns and grid-template-rows values are:

  1. A non-negative length values in units (e.g., 200px).
  2. A percentage value relative to the size of the container grid (e.g., 30%).
  3. A non-negative flex value in fr units (e.g., 3fr) - Similar to the unitless values for Flexbox's flex property. It specifies the proportion of space that the columns or rows take up.
  4. minmax(min, max) (https://developer.mozilla.org/en-US/docs/Web/CSS/minmax) - Defines the size of the column or row ranging from the min to the max (e.g., minmax(100px, 1fr)).
  5. repeat(number, size) (https://developer.mozilla.org/en-US/docs/Web/CSS/repeat) - Creates the number of columns or rows sized by the size argument (e.g., repeat(5, 1fr)).
  6. auto - The element takes up the most space it can and doesn't shrink smaller than what is specified in min-width and min-height properties.

The syntax of grid-template-columns and grid-template-rows is shown below:

Syntax

grid-template-columns: column1, column2, column3, etc.

grid-template-rows: row1, row2, row3, etc.

The following example creates a grid with a 40% column, three 1fr columns, and a 1fr column that won't shrink below 150px:

grid-template-columns: 40% repeat(3, 1fr) minmax(150px, 1fr);

grid-template-columns Example

The following example creates a grid with a 100px row, three 1fr rows, and a 3fr row.

grid-template-rows: 100px repeat(3, 1fr) 3fr;

grid-template-rows Example

These examples can be found in Layouts/Demos/grid-examples.html.

grid-auto-columns and grid-auto-rows

grid-auto-columns and grid-auto-rows are very similar to grid-template-columns and grid-template-rows, but since they are targeting the implicitly-generated columns and rows, they only set size and not number.

Some common grid-auto-columns and grid-auto-rows values are:

  1. A non-negative length values in units (e.g., 200px).
  2. A percentage value relative to the size of the container grid (e.g., 30%).
  3. A non-negative flex value in fr units (e.g., 3fr) - Similar to the unitless values for Flexbox's flex property. It specifies the proportion of space that the columns or rows take up.
  4. minmax(min, max) (https://developer.mozilla.org/en-US/docs/Web/CSS/minmax) - Defines the size of the column or row ranging from the min to the max (e.g., minmax(100px, 1fr)).
  5. auto - The element takes up the most space it can and doesn't shrink smaller than what is specified in min-width and min-height properties.

The following example sizes the implicit rows from our grid-template-columns example:

grid-template-columns: 40% repeat(3, 1fr) minmax(150px, 1fr);
grid-auto-rows: 50px;

grid-auto-rows Example

The following example sizes the implicit columns from our grid-template-rows example:

grid-template-rows: 100px repeat(3, 1fr) 3fr;
grid-auto-columns: 75%;

grid-auto-columns Example

These examples can be found in Layouts/Demos/grid-examples.html.

gap

gap specifies the space in between rows and columns. It takes one or two length or percentage values.

  1. If one value is specified, it applies to the gap between rows and columns (e.g., gap: 1rem).
  2. If two values are specified, the first applies to the gap between rows and the second to the gap between columns (e.g., gap: 1rem, 0.5rem).

Alternatively, the longhand row-gap (https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap) and column-gap (https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap) properties can be used.

The following example adds a 1rem gap between rows and columns:

gap: 1rem;
grid-template-columns: 40% repeat(3, 1fr) minmax(150px, 1fr);

gap Example 1

The following example adds a 1rem gap between rows and a 0.5rem gap between columns:

gap: 1rem 0.5rem;
grid-template-columns: 40% repeat(3, 1fr) minmax(150px, 1fr);

gap Example 2

grid-column and grid-row

All the properties we have looked at so far are applied to the container grid element to create the grid. grid-column and grid-row are applied to the child elements and are used to size and position them within the grid. Both grid-column and grid-row take one or two values separated by a forward slash (/).

  1. The first value (or only value, if only one is specified) sets the starting point of the element.
  2. The second value sets the ending point of the element.

These values use grid lines as references. Grid lines are numbered lines between the columns and rows.

  1. Column line 1 is on the left-hand side of the first column, column line 2 is on the right-hand side of the first column and on the left-hand side of the second column, etc.
  2. Row line 1 is on the top of the first row, row line 2 is on the bottom of the first row and on top of the second row, etc.
  3. The last row or column line can be referred to as its positive number using the method above, or it can be referred to as -1.

See the image below to see the grid lines labeled on a basic grid: Grid Lines

Some common grid-column and grid-row values are:

  1. A unitless integer referring to grid lines (e.g., grid-column: 1 / 3 sets the element to start at column line 1 and end at column line 3).
  2. The span keyword and unitless positive number specifying the number of columns or rows to span (e.g., grid-row: span 2 / -1 sets the element to span two rows and to end at row line -1).

The following example gives Cell 1 a span of three and and makes it end at column line 5:

grid-columns: span 3 / 5;

grid-column Example

The following example positions Cell 1 starting at row line 2 and ending the last row line (-1):

grid-row: 2 / -1;

grid-row Example

These examples can be found in Layouts/Demos/grid-examples.html.

Below you can see a basic Grid Layout demo:

Code Sample:

Layouts/Demos/grid-styles.css
body {
  background: aliceblue;
}

main {
  background: white;
  display: grid;
  gap: 1rem 0.5rem;
  grid-template-columns: minmax(150px, 1fr) repeat(3, 1fr);
  grid-template-rows: repeat(3, 200px);
  margin: auto;
  min-width: 600px;
  padding: 0.5rem;
  width: 80%;
}

main nav {
  background: rgb(243, 241, 241);
  border: 1px solid black;
  border-radius: 0.5rem;
  font-size: 1.2rem;
  grid-column: 1 / 2;
  grid-row: 1 / -1;
}

article {
  border: 1px solid black;
  overflow: hidden;
  padding: 0.5rem;
  min-width: 100px;
}

article:target {
  border: solid black;
  grid-column: 2 / -1;
  grid-row: 1;
}

article:target h3 {
  text-decoration: underline;
}

Code Sample:

Layouts/Demos/grid.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Basic Grid Layout</h1>
<main>
  <nav>
    <ol>
      <li><a href="#article1">Article 1</a></li>
      <li><a href="#article2">Article 2</a></li>
      <li><a href="#article3">Article 3</a></li>
      <li><a href="#article4">Article 4</a></li>
      <li><a href="#article5">Article 5</a></li>
      <li><a href="#article6">Article 6</a></li>
      <li><a href="#article7">Article 7</a></li>
    </ol>
  </nav>
  <article id="article1">
    <h3>Article 1</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
  <article id="article2">
    <h3>Article 2</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
  <article id="article3">
    <h3>Article 3</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
  <article id="article4">
    <h3>Article 4</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
  <article id="article5">
    <h3>Article 5</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
  <article id="article6">
    <h3>Article 6</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
  <article id="article7">
    <h3>Article 7</h3>
    <p>Lorem ipsum dolor 
      sit amet, consectetur adipiscing elit. 
      Curabitur tristique odio ac sem congue luctus.
      
---- C O D E   O M I T T E D ----

  </article>
</main>
</body>
</html>

Code Explanation

The code above will render the following:Grid Demo

Some things to note:

  1. The main element is the grid container.
  2. The target article is positioned at the top. article4 is the target in this image.

Multi-column Layout

Multi-column offers a way to organize content into columns. We can control the size and number of columns, the gap between columns, and an optional rule between columns. List ed below are the relevant properties.

Multi-column Properties
Property Explanation Example/Possible Values
columns Sets the width and count (number) of columns. columns: 10rem 2
column-fill Sets how columns are populated with content. auto (fill columns sequentially) or balance (balance content as equally as possible).
column-gap Sets the size of the gap between columns. A length value in units or normal, which is 1em for Multi-column.
column-rule Sets the width, style, and color of the rule (a line that separates columns). column: 0.2rem dashed red
break-inside Sets whether or not an element can break inside itself. auto (can break) or avoid (avoids breaking).

Unlike Flexbox and Grid, Multi-column is not meant to be used to create the entire layout of your web page. It is best to use it for collapsing small text elements like lists, or for creating masonry layouts. We do both in the following demo:

Code Sample:

Layouts/Demos/multi-column-styles.css
body {
  background: aliceblue;
}

main {
  background: white;
  margin: auto;
  min-width: 600px;
  width: 90%;
}

h2 {
  margin: 0.2rem auto;
  padding: 0.2rem;
  width: 256px;
}

nav {
  border: solid black;
  border-radius: 0.5rem;
  margin: auto;
  min-width: 550px;
  width: 90%;
}

nav ol {
  columns: 4;
  column-gap: 2rem;
  margin: 0.2rem auto;
  width: 90%;
}

div {
  background: rgb(235, 233, 233);
  box-sizing: border-box;
  break-inside: avoid;
  margin: 0 auto 1rem;
  padding: 0;
}

div a {
  display: block;
  width: 100%;
}

div img {
  width: 100%;
  transition: transform 0.5s;
}

div img:hover {
  transform: scale(0.95);
  transition: transform 0.5s;
}

#gallery {
  columns: 200px;
  column-fill: balance;
  column-gap: 0.5rem;
  margin: 1rem auto;
  width: 90%;
}

p.caption {
  font-size: 1.2rem;
  font-style: italic;
  margin: 0 1em;
  padding: 0 1em;
}

Code Sample:

Layouts/Demos/multi-column.html
---- C O D E   O M I T T E D ----
<body class="webucator">
<h1>Multi-column</h1>
<main>
  <h2>Check out our cute dogs!</h2>
  <nav>
    <ol>
      <li><a href="#dog1">Cute Dog 1</a></li>
      <li><a href="#dog2">Cute Dog 2</a></li>
      <li><a href="#dog3">Cute Dog 3</a></li>
      
---- C O D E   O M I T T E D ----

      <li><a href="#dog20">Cute Dog 20</a></li>
    </ol>
  </nav>
  <section id="gallery">
    <div id="dog1">
      <a href="#dog1">
        <img src="images/dog1.jpg" alt="Cute Dog 1"></a>
      <p class="caption">
        Here is one cute dog!</p>
    </div>
    <div id="dog2">
      <a href="#dog2">
        <img src="images/dog2.jpg" alt="Cute Dog 2"></a>
      <p class="caption">
        And here's another one!</p>
    </div>
    <div id="dog3">
      <a href="#dog3">
        <img src="images/dog3.jpg" alt="Cute Dog 3"></a>
      <p class="caption">
        So cute!</p>
    </div>
    
---- C O D E   O M I T T E D ----

    <div id="dog20">
      <a href="#dog20">
        <img src="images/dog20.jpg" alt="Cute Dog 20"></a>
      <p class="caption">
        Mommy and baby. Adorable!</p>
    </div>
  </section> 
</main>
</body>
</html>

Code Explanation

The above code will render the following:Multi-column Demo

Some things to note:

  1. The top menu list will always have four columns, and this way it conserves vertical space.
  2. The gallery section will have as many 200px columns as will fit. Making the window bigger creates room for more columns.

Layouts

Duration: 25 to 40 minutes.

In this exercise, you will continue to work with a new page that is part of the Running Blog.

  1. Open Layouts/Exercises/photos.html in your editor.
  2. Open Layouts/Exercises/blog-styles.css. This is the stylesheet from the solution to the Positioning exercise. Feel free to continue working from your own stylesheet.
  3. Using your new knowledge of layouts add some styles to this page. The object of this exercise is to practice using the properties covered in this lesson, but note that for this page it may not make sense to use all the layouts. You may end up just using one or two. This is perfectly fine. Also, feel free to add or change any other properties that you know.
  4. When you are done, open photos.html in your browser to see the results. You are welcome to go back to the code and continue to work.

You can design it however you like, or you can try to make it look something like: Layouts Solution

Solution:

Layouts/Solutions/blog-styles.css
---- C O D E   O M I T T E D ----


main#photos {
  min-width: 620px;
}

#photos nav {
  margin: auto;
  min-width: 550px;
  width: 90%;
}

#photos nav ol {
  columns: 4;
  column-gap: 2rem;
  margin: 0.2rem auto;
  width: 90%;
}

#gallery {
  columns: 200px;
  column-fill: balance;
  column-gap: 0.5rem;
  margin: 1rem auto;
  width: 90%;
}

#gallery div {
  background: rgb(235, 233, 233);
  box-sizing: border-box;
  break-inside: avoid;
  margin: 0 auto 1rem;
  padding: 0;
}

#gallery div a {
  display: block;
  width: 100%;
}

#gallery div img {
  width: 100%;
  transition: transform 0.5s;
}

#gallery div img:hover {
  transform: scale(0.95);
  transition: transform 0.5s;
}

p.caption {
  font-size: 1.2rem;
  font-style: italic;
  margin: 0 1em;
  padding: 0 1em;
}

#gallery div:target {
  border: blue solid;
}

#gallery div:target p.caption {
  font-weight: bold;
}

Code Explanation

Some things to note:

  1. We omitted lines in Layouts/Solutions/blog-styles.css for brevity.
  2. Note that the running-shoes div is the target in the screenshot.
  3. We only used the Multi-column layout, but that does not mean you have to or that you can't also use the other layouts.