COSC203 Web, Databases, and Networks
Toggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Lab 3.x: CSS Layout

⚠️ Unmarked Lab

This lab is optional and unmarked.

Quite useful for Assignment 1.

🎯 Lab Objective

In this lab, you will page layout in CSS.

This lab teaches the following concepts:

  1. FlexBox layout
  2. Grid layout
  3. responsive design

Table of Contents

CSS Selectors Review

The basic selectors:

SelectorExampleDescription
universal*selects all elements
typeh1select all <h1> elements
class.nameselects all elements with class="name"
id#nameselects all elements with id="name"

Combining selectors:

SelectorExampleDescription
Groupingdiv, h1selects all <h1> elements and <div> elements
Descendantdiv h1selects all <h1> inside <div> elements
Direct Descendantdiv > h1selects all <h1> where the parent is a <div>
Adjacent Siblingdiv + h1selects the first <h1> that is immediately after a <div>
General Siblingdiv ~ h1selects every <h1> that is after a <div>
Chaining.class1.class2selects all elements with both class1 and class2 as class attributes
Attributediv[lang]selcts all <div> elements which have a lang attribute

Pseudo selectors

SelectorExampleDescription
Hoverdiv:hoverselects a <div> when mouse enters its bounds
Not:not(div)selects all elements which are not <div> elements
Root:rootselects the root element of the page (usually <html>)
Only childdiv p:only-childselects every <p> if it is also the only child of a <div>
First childdiv p:first-childselects every <p> if it is also the first child of a <div>
First occurencediv p:first-of-typeselects the first occurence of <p> within each <div>
Last childdiv p:last-childselects every <p> if it is also the last child of <div>
Last occurencediv p:last-of-typeselects the last occurence of <p> within each <div>
nth childdiv p:nth-child(2)selects every <p> which is the second child of each <div>
nth occurencediv p:nth-last-child(2)selects every <p> which is the second to last child of each <div>
nth Typediv p:nth-of-type(odd)selects every odd indexed <p> inside a <div>

1. Page Layout

The most important aspect of CSS is layout. We need presentable websites for a variety of screen sizes; from smart phones to 4K smart TVs. Using CSS to create your layout can seem simple but if you don’t understand the fundamental concepts it can lead to frustration…

CSS Gif

Layout Fundamentals

In the previous lab we covered most fundamentals.

  • Document Flow
    • display: block;
      • <div> block
    • display: inline;
      • <span> inline
  • Box Model
    • width the elements width
    • height the elements height
    • margin transparent space between elements.
    • padding transparent space around content.
    • border visual space around the padding and content.
  • Positioning
    • position: static; cannot move from the normal flow.
    • position: relative; can move; relative to normal flow position.
    • position: fixed; can move; relative to viewport (ignores scrolling).
    • position: absolute can move; relative to a positioned ancestor element.
    • Properties which move a positioned element: top, right, bottom, left

Layout Idioms

The layout fundamentals we have covered so far are sufficient to create any website layout. However, some of the concepts are unintuitive and can lead to idiomatic code.

 Tip

In software development an idiom is a reusable code snippet that is commonly used to achieve some task. Idioms are always obvious to newcomers, they can feel cryptic or even hacky.

Idioms are usually shared by experts to newcomers on websites like https://stackoverflow.com/

Programming idiom on Wikipedia.


Justify Middle Idiom

This idiom uses margin: auto to centre elements. The margin is calculated by the browser to be equal on all sides. This idiom only works on block elements.

HTML
CSS
JavaScript
Result

Positioning Idiom

The below popular idiom shows how to arbitrarliy position a block element (within a parent container) using position: absolute

HTML
CSS
JavaScript
Result

Centering Idiom

Another idiom all CSS developers know (similar to the previous) is how to centre a block element vertically and horizontally:

HTML
CSS
JavaScript
Result

With enough reading and practice you can understand exactly how these idioms work, but we all agree many are not intuitive for a newcomer and some feel a bit hacky.

Surely there’s an easier way?

Modern CSS Layout

The easier way is Flexbox and/or CSS Grid. Both were designed to be easy to use and less reliant on hacky idioms. FlexBox became fully supported by all major web browsers around 2015 and CSSGrids around 2017.

Flexbox and CSS Grids

The main point of difference between these 2 is that Flexbox is designed to arrange items in a single direction (row or column) whereas CSS Grid is designed to arrange items in both directions.

3. Flexbox Layout

Introducing Flexbox. Any element with display: flex; will auto-magically arrange their child elements into a row (or column). We’ll only cover the basics but you may research the advanced properties on your own.

Flex Container

To use Flexbox you need a container element with display: flex;. Usually we use a <div> for the flex container, but any element would work. A flex item is any element which is a direct descendant (child) of the flex container.

HTML
CSS
JavaScript
Result

Flex Gap

The gap property assigns space between flex items.

Flex Direction

The flex-direction property defines the direction the children will be arranged. The default value is row, but there is also: row-reverse, column, and column-reverse.

Flex Direction

Nesting Flex Containers

You can nest flex containers by making any of the flex items a flex container (i.e display: flex). You can mix and match rows and columns to compose almost any layout with ease.

Flex Nesting

Justify Content

The justify-content property defines how flex items are spaced out, relative to the flex container’s direction. The default value is flex-start but there are several others.

Flex Justify Content

Align Items

The align-items property defines how flex items are aligned. Vertically aligned in a row, horizontally aligned in a column.

Flex Align Items

Flex Wrap

By default all the flex items will attempt to squeeze into a single line, but you can use flex-wrap to allow the items to flow into another row (or column).

Final Flex Example

Below is an example where you may inspect the HTML and CSS.

HTML
CSS
JavaScript
Result
📝 Task 1: Implement Flexbox
  1. Use Flexbox on the contact page
    • open the previous lab files (Polly’s website)
    • modify style.css to provide a better layout for contact.html
    • start by setting display: flex; on <main>
    • below is an ugly example, I’m sure yours will be much prettier

  1. Use Flexbox on the stories page

 Tip
A more complete guide to Flexbox on css-tricks.com

4. CSS Grid Layout

Grid layout shares many properties with Flexbox. Firstly, to use the Grid layout you need a container element with display: grid;. A grid item is any element which is a direct descendant (child) of the grid container.

Grid Container

The grid items won’t immediately arrange themselves until you have declared how many rows/columns and the size of each row/column.

Rows and Columns

To declare both the number or rows and their respective widths use the grid-template-rows property on the grid container. There is also grid-template-columns for declaring the columns.

For example, below is a grid with 2 rows and 4 columns. Each row is 150px tall, and each column is 100px wide.

.grid-container {
    display : grid;
    grid-template-rows: 150px 150px; /* 2 rows, 150px tall */
    grid-template-columns: 100px 100px 100px 100px; /* 4 columns, 100px wide */
}

04-grid-template

 Tip

Delcaring rows and columns can be simplified with repeat()

.grid-container {
    display : grid;
    grid-template-rows: repeat(2, 150px);
    grid-template-columns: repeat(4, 100px);
}

Gaps

Much like Flexbox we can declare the space between grid items with the gap property. Or we can declare different gap sizes for rows and columns using column-gap and row-gap.

.grid-container {
    gap: 16px;
    row-gap: 8px;
    column-gap: 16px;
}

Responsive Grid

If you want rows/columns to reisze to fit the browser window you might be tempted to use % units, something like: grid-template-rows: 50% 50%, but unfortunately this method doesn’t consider the gaps between rows/columns. Instead, you should use the fr unit, the fractional unit.

In the below example there are 3 columns, the middle column is 2fr so will be twice the width of the columns that are 1fr.

.grid-container {
    display : grid;
    grid-template-rows: 1fr 2fr 1fr;
    grid-template-columns: repeat(2s, 1fr);
}

fr unit

 Tip

You can mix units in the same declaration.

div {
    display: grid;
    grid-template-columns: 200px 3fr 1fr;
}

The above example declares 3 columns. The first column will occupy 200 pixels of the grid, and the remaining width of the grid will be distributed between the other 2 fractional columns, such that 3fr is triple the width of 1fr.

Spanning

Grid items will arrange themselves to fit within the next available Grid cell, from top left to bottom right. A grid item can span any number of rows and columns using the grid-row and grid-columns properties.

.grid-item-1 {
    grid-row: span 2;
}
.grid-item-2 {
    grid-column: span 3;
}
.grid-item-3 {
    grid-row: span 2;
    grid-column: span 3;
}

Grid Span

Placement

Grid items will place themselves in order. You can override this order and place a grid item in any arbitrary row/column with grid-row-start and grid-column-start.

There are also grid-row-end and grid-column-end which will span the grid item to any arbitrary row/column. All of these properties expect grid lines as values, where grid lines are the lines between row/columns.

In the below example the there are 3 rows, 3 columns, 4 grid row lines, and 4 grid column lines.

Grid Start End

Justify and Align Items

Much like flex items, we can justify and align grid items. Justify is the horizontal position within a cell, and align is the vertical position within a cell. Both default to stretch to fill the entire Grid cell.

You can set justify-items and align-items on the grid container to effect all grid items. You may also set each grid item individually with the justify-self and align-self properties.

Final Grid Example

Below is an example where you may inspect the HTML and CSS.

HTML
CSS
JavaScript
Result

FlexBox and Grid work very well together. Flexbox is best used to arrange elements which all have a similar size. Grid is best used to arrange elements which have different sizes, for example, the overall page structure (header, side-bar, footer, …).

📝 Task 2: CSS Grid
  1. Create a Grid layout for Polly’s website
    • start by setting display: grid; on the <body>
    • create 3 rows and 2 columns
    • <header> should fill the 1st row
    • <footer> should fill the 3rd row
    • <nav> and <main> in the second row
    • <nav> thinner than <main>
  2. Give links in <nav> a prettier style
  3. Now that <main> is thinner, you may have to adjust some flex properties
  4. Keep the <footer> always at the bottom
    • set min-height: 100vh; on the grid container (<body>)
    • this may be another css trick/idiom.

 Tip
There are plenty more grid properties we didn’t cover. If you wish to learn more about Grid, check out: css-tricks.com: A Complete Guide to Grid

5. Responsive Design

A responsive website is one which changes its layout depending on the size of the screen. The layout for a smart phone should be different than the layout for a desktop computer.

Proportional Units

Responsive websites avoid fixed width values like 200px. Instead we would use proportional values like 50%. This way our elements can grow or shrink to fit any screen size. We also have vw and vh units, which are relative to the size of the viewport, where 1vw is 1% of the browsers width, and 1vh is `% of the browsers height.

If you have to use exact pixel values, try and use min-width, max-width, min-height, and max-height where possible. The properties will help your elements grow and shrink to fill the availble screen space.

Media Queries

One way to support different screen sizes is declare a different set of CSS rules for different screen sizes. We can easily do this with the CSS @media query.

  1. Copy the below CSS into the style.css of Polly’s website.
  2. Resize the web browser (or zoom) to ensure it works as expected
/* X-Small screens (small phones) */
body {
    background-color: red;
}

/* Small screens (phones) */
@media (min-width: 320px) {
    body {
        background-color: orange;
    }
}

/* Medium screens (tablets) */
@media (min-width: 640px) {
    body {
        background-color: yellow;
    }
}

/* Large screens (laptops) */
@media (min-width: 1366px) {
    body {
        background-color: lime;
    }
}
📝 Task 3: Reponsive Layout
  1. Create 2 different Grid layouts for Polly’s site
    • one for smart phone browsers
    • one for desktop browsers
    • the page should automatically change the layout when the browser window changes size
 Tip
In the industry is is advised to prioritise the layout for mobile first. Largely because most people browse the web on their mobile phones.

7. Marking Off

This lab is worth marks. be sure to get signed off.