In this lab we shall cover further topics in CSS.
Follow the link below to open codesandbox. Fork the project then sign in.
Pseudo elements allow us to style specific parts of an element. They are as follows:
::after
: used with the content
property to insert text after the content of an element::before:
used with the content
property to insert text after the content of an element::first-letter
: selects the first letter of text content::first-line
: selects the first-line of text content::selection
: selects the text content highlighted by the userBox sizing refers to how css measures the size of an element. Every element has a box-sizing property which can have the following values:
content-box
- The element's size is measured by its content.border-box
- The element's size is measured by its border.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.
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:
static
- default, unaffected by the positioning propertiesrelative
- treat the top left corner of the element's current position as the origin pointabsolute
- treat the top left corner of its parent as origin pointfixed
- treat the top left corner of the browser window as the origin point, unaffected by scrollingsticky
- starts as relative but becomes fixed after the user scrolls past a given offsetAfter 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 |
| Moves the element downward | Space between top edge of element and its parent | Space between top edge of element and the window |
| Moves the element to the left | Space between right edge of element and its parent | Space between right edge of element and the window |
| Moves the element upward | Space between bottom edge of element and its parent | Space between bottom edge of element and the window |
| 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.
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
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
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.