Scripting With Style Part 2

In this lab we shall cover further topics in CSS.

Task 1

Follow the link below to open codesandbox. Fork the project then sign in.

Open Lab 3

Pseudo elements allow us to style specific parts of an element. They are as follows:

Task 2

Box sizing refers to how css measures the size of an element. Every element has a box-sizing property which can have the following values:

The default value for all elements is content-box. However, this can be undesirable for layout as adding padding causes elements to grow larger.

When we use border-box, adding padding trades off content space for padding space so the element size remains the same.

Task 3

As we will be doing some precise layout in this lab let's style all elements to use border-box by using the wildcard selector.

<style>
   * {
     box-sizing: border-box;
   }
</style>

.

The position property alters how other positioning properties affect the element's position. The following are the values for position:

Positioning Properties

After the position property has been set to any value other than static then the following properties can be used to position the element.

Property

Relative

Absolute

Fixed

top:

Moves the element downward

Space between top edge of element and its parent

Space between top edge of element and the window

right:

Moves the element to the left

Space between right edge of element and its parent

Space between right edge of element and the window

bottom:

Moves the element upward

Space between bottom edge of element and its parent

Space between bottom edge of element and the window

left:

Moves the element to the right

Space between left edge of element and its parent

Space between left edge of element and the window

Flex box is a more modern and easier method for doing layout than float. In order to start using the flex properties we need to ensure the parent of any element we want to layout has its display property to flex.

Update index.html to set the body tag to flex display.

<style>
        * {
                box-sizing: border-box;
        }

        body{
                display: flex;
        }
</style>

Next let's add some layout elements and styling so we can see them on the page.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
        * {
                box-sizing: border-box;
                margin: 5px;
                padding: 1em;
        }

        header, footer{
                color: white;
                background-color:  #1976D2;
        }

        aside{
                color: #212121;
                background-color: #BBDEFB;
        }
        section{
                background-color: #FF4081;
                color: white;
        }

        main{
                background-color: #2196F3;
                color: white;
        }

        body{
                display: flex;
                background-color: #FFFFFF;
        }
        </style>
<body>

        <header>Header</header>
        <aside>
                Aside
                <section>Section 1</section>
                <section>Section 2</section>
        </aside>
        <main>Main</main>
        <footer>Footer</footer>

    
</body>
</html>

This markup and styles will give the following result. Notice how every top level element is aligned in a row and is evenly sized because of the flex display of the body.

Flex-Direction

The elements are aligned horizontally because the default value of flex-direction is row. However we would want to change this to columns so that header is at the top and footer is at the bottom of the page.

body{
  display: flex;
  flex-direction: column;
  background-color: #FFFFFF;
}

When we add flex-direction notice the elements are aligned within a single column.

Next we want the aside and main elements to be next to each other. In terms of flexbox this can be achieved by having an element with flex-direction:row within the column of the body.

Update index.html to group the aside and main element within a row by using a div tag the with an appropriate style.

Index.html should now look like

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<style>
        * {
                box-sizing: border-box;
                margin: 5px;
                padding: 1em;
        }

        header, footer{
                color: white;
                background-color:  #1976D2;
        }

        aside{
                color: #212121;
                background-color: #BBDEFB;
        }
        section{
                background-color: #FF4081;
                color: white;
        }

        main{
                background-color: #2196F3;
                color: white;
        }

        body{
                display: flex;
                flex-direction: column;
                background-color: #FFFFFF;
        }

        .row{
                display: flex;
                flex-direction: row;
        }

        .col{
                display: flex;
                flex-direction: column;
        }

        </style>
<body>

        <header>Header</header>
        <div class="row">
                <aside class="col">
                Aside
                <section>Section 1</section>
                <section>Section 2</section>
        </aside>
        <main>Main</main>
        </div>
        
        <footer>Footer</footer>

    
</body>
</html>

Using just rows and columns we can achieve our desired layout of our elements.

Next we want to switch to relative sizing so update the following selectors as follows.

* {
 box-sizing: border-box;
}

body{
        display: flex;
        flex-direction: column;
        background-color: #FFFFFF;
        height: 100vh;
        width: 100vw;
            margin: 0;
}


div.row{
        height: 80%;
}

We should now see that our markup takes up all the space on the page

Flex-Grow Property

We can use the flex-basis property to affect the sizing of our elements. Flex-grow determines how much an element can grow in size relative to the other children of the flex container.

Lets update index.html to allow a 3:7 ratio between the length of the aside and main element respectively by using flex grow. We will apply flex grow to our header, footer and div as well.

Update Index.html

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
</head>
<style>
* {
        box-sizing: border-box;
}

header, footer, section, aside, main{
        padding: 1em;
}


header, footer{
        color: white;
        background-color:  #1976D2;
        flex-grow: 1;
}

aside{
        color: #212121;
        background-color: #BBDEFB;
        flex-grow: 3;
}
section{
        background-color: #FF4081;
        color: white;
}

main{
        background-color: #2196F3;
        color: white;
        flex-grow: 7;
}

body{
        display: flex;
        flex-direction: column;
        background-color: #FFFFFF;
        height: 100vh;
        width: 100vw;
        margin:0;
}

.row{
        display: flex;
        flex-direction: row;
}

div.row{
        flex-grow: 8;
}

.col{
        display: flex;
        flex-direction: column;
}

</style>
<body>

<header>Header</header>
<div class="row">
                <aside class="col">
                Aside
                <section>Section 1</section>
                <section>Section 2</section>
        </aside>
        <main>Main</main>
</div>

<footer>Footer</footer>

        
</body>
</html>

We also add some padding to some of our elements as well so now the result should look like

Justify Content

We can align content within flex containers by using the justify content property which can have the following values:

Lets style our sections to be centered, add a flex-grow to them and a margin. Also remove the "Aside" text so that the sections are the only children of the aside element.

aside{
        display: flex;
        justify-content: center;
        color: #212121;
        background-color: #BBDEFB;
        flex-grow: 3;
}
section{
        background-color: #FF4081;
        color: white;
        flex-grow: 1;
        margin: 0.5em;
}

We should get the following result.

We use media queries to allow our page's layout to respond to various screen sizes, hence achieving responsive design.

Media queries simply apply a subset of css rules if a specified feature is present on the client such as:

Arguably the most commonly used feature for responsive design is max-width.

We shall apply a media query to reposition our row as a column if the device width is less than 600px.

@media screen and (max-width: 600px) {
  div.row{
        flex-direction: column;
   }
}

With this simple rule our css is overwritten if the window is sized under 600px.

Finally index.html should look like

<!DOCTYPE html>
<html lang="en">
<head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Document</title>
</head>
<style>
* {
        box-sizing: border-box;
}

header, footer, section, aside, main{
        padding: 1em;
}

header, footer{
        color: white;
        background-color:  #1976D2;
        flex-grow: 1;
}

aside{
        display: flex;
        justify-content: center;
        color: #212121;
        background-color: #BBDEFB;
        flex-grow: 3;
}
section{
        background-color: #FF4081;
        color: white;
        flex-grow: 1;
        margin: 0.5em;
}

main{
        background-color: #2196F3;
        color: white;
        flex-grow: 7;
}

body{
        display: flex;
        flex-direction: column;
        background-color: #FFFFFF;
        height: 100vh;
        width: 100vw;
        margin:0;
}

.row{
        display: flex;
        flex-direction: row;
}

div.row{
        flex-grow: 8;
}

.col{
        display: flex;
        flex-direction: column;
}

@media screen and (max-width: 600px) {
  div.row{
                flex-direction: column;
        }
}

</style>
<body>

<header>Header</header>
<div class="row">
                <aside class="col">
                <section>Section 1</section>
                <section>Section 2</section>
        </aside>
        <main>Main</main>
</div>

<footer>Footer</footer>

        
</body>
</html>

Congratulations we have implemented a basic responsive design. Flexbox is very powerful and makes layout easy once it's understood.

References

A complete guide to flexbox

Media Queries

Responsive Design and Media Queries