Flexbox practise: Freelancer website

We are going to build a freelancer website and in doing so we will make use of the Flexbox CSS3 module to practise how to use it for layout. By the end we will build the following freelancer website:

figure1-1

Adding the markup for the site

To start the project we’re going to add the markup for our freelancer website as follows:

<nav class="main-navigation">
        <a href="#">Home</a>
        <a href="#">About Us</a>
        <a href="#">Clients & Work</a>
        <a href="#">Contact Us</a>
    </nav>

    <div class="hero">
        <div class="hero-content">
            <h1>Freelance Web Developer</h1>
            <p><i class="fas fa-map-marker-alt"></i> Guadalajara, Jalisco</p>
            <a class="button" href="#">Contact Us Here</a>
        </div>
    </div>

    <div class="container">
        <main class="services">
            <h2>My Services</h2>
            <div class="services-container">
                    <div class="service">
                        <h3>Web Design</h3>
                        <div class="icons">
                            <i class="fas fa-pen-nib"></i>
                        </div>
                        <p>Blanditiis omnis dolorum nihil, dolor dolore corporis, ducimus vero officia beatae reiciendis velit quos quis deserunt placeat laboriosam necessitatibus saepe iure eaque?</p>
                    </div><!--.service-->
                    <div class="service">
                        <h3>App Development</h3>
                        <div class="icons">
                            <i class="fab fa-android"></i>
                            <i class="fab fa-apple"></i>
                        </div>
                        <p>Blanditiis omnis dolorum nihil, dolor dolore corporis, ducimus vero officia beatae reiciendis velit quos quis deserunt placeat laboriosam necessitatibus saepe iure eaque?</p>
                    </div><!--.service-->
                    <div class="service">
                        <h3>Social Media</h3>
                        <div class="icons">
                            <i class="fab fa-twitter"></i>
                            <i class="fab fa-facebook"></i>
                        </div>
                        <p>Blanditiis omnis dolorum nihil, dolor dolore corporis, ducimus vero officia beatae reiciendis velit quos quis deserunt placeat laboriosam necessitatibus saepe iure eaque?</p>
                    </div><!--.service-->
            </div>
        </main>

        <section id="contact" class="contact">
            <h2>Contact Me</h2>
            <form action="#">
                <div class="form-container">
                    <div class="field">
                        <label>Name:</label>
                        <input type="text" placeholder="Name">
                    </div>
                    <div class="field">
                        <label>Phone Number:</label>
                        <input type="tel" placeholder="Phone Number">
                    </div>
                    <div class="field w-100">
                        <label>Email:</label>
                        <input type="mail" placeholder="Email">
                    </div>
                    <div class="field w-100">
                        <label>Message:</label>
                        <textarea cols="30" rows="3"></textarea>
                    </div>
                </div><!--.form-container-->
                <div class="submit-form">
                    <input type="submit" class="button" value="Send">
                </div>
            </form>
        </section>
    </div>

The markup is simple and pretty much self explanatory. Next we’re going to add some assets before we start applying styles.

Adding a font, Font Awesome, and CSS normalize

We’re going to add CSS normalize to reset the user agent styling in the browsers, and we’re going to use a font from google fonts with a couple of font weights, and we’re going to add font awesome icons. The head of the index.html you should look like the following:

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Flexbox - Freelancer Website</title>
    <link rel="stylesheet" href="https://necolas.github.io/normalize.css/8.0.1/normalize.css">
    <link href="https://fonts.googleapis.com/css?family=Krub:400,700" rel="stylesheet">
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
    <link rel="stylesheet" href="css/style.css">
</head>

We’re also going to make use of CSS3 root variables, so that we can reuse them in our code:

:root {
     --mainFont : 'Krub', sans-serif;
     --white: #ffffff;
     --primary: #FFC107;
     --secondary: #0097A7;
     --gray : #757575;
     --dark : #212121;
}

You can read more about cs3 root variables here: https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties

We’re also going to make use of box sizing and we’re going to set a height for the html parent element on the page:

html {
     box-sizing: border-box;
     min-height: 100%;
}
*, *:before, *:after {
     box-sizing: inherit;
}

Finally we’re going to make use of the root variable to set the font family value in the body:

body {
     font-family: var(--mainFont);
}

Building the nav

Next we’re going to build the navigation menu, we’re going to first align the nav menu using max width and margin properties and also add some padding to the top and bottom of the navigation container:

figure2-2

This center aligns our nav menu and applies padding to the top and bottom. Next we’re going to style the nav menus mobile first. To do this we’re going to first set the diplay to flex and then we’re going to use flex-direction: colum to stack the menu items and then we’re going to center align them in the Cross Axis using the align-items property:

.main-navigation {
     max-width: 1200px;
     margin: 0 auto;
     padding: 1rem 0;
     display: flex;
     flex-direction: column;
     align-items: center;
}

figure3-1

This nicely stacks the menu items for mobile view. We need to now apply some colors, remove the underline from the anchor elements, and give a font size and margin bottom for some breathing space:

.main-navigation a {
     color: var(--dark);
     text-decoration: none;
     font-size: 1.4rem;
     margin-bottom: 1.4rem;
}

Notice we’re making use of the root variable dark, to use the value we call the var function and between the parenthesis place the name of the variable. This nicely styles are menu items:

figure5-1

Next we’re going to add styling for the larger devices and we’re going to use a media query. We want the menu items to be in a row and we we’re going to space them out using the justify-content: space-between value:

@media (min-width:768px) {
     .main-navigation {
          flex-direction: row;
          justify-content: space-between;
     }
}

In larger viewports this will set the menu items to be in a row and have space between them:

figure6-1

Finally for the nav menu we want to remove the margin of each menu item for the larger viewports:

@media (min-width:768px) {
     .main-navigation {
          flex-direction: row;
          justify-content: space-between;
     }

     .main-navigation a{
          margin-bottom: 0;
     }
}

Adding a hero image

We’re going to now add the hero image under the main nav menu. To add styling for the hero we’re going to target the div with the class hero and we’re going to set the height, background image, with the position set to relative:

.hero {
     height: 450px;
     background-image: url(../img/hero.jpg);
     position: relative;     
}

This will add the image as a background and set the position to relative with a fixed height:

figure7-1

Next we want to center align the contents of the hero container, so for that we’ll use Flexbox:

.hero {
     height: 450px;
     background-image: url(../img/hero.jpg);
     position: relative;
     
     display: flex;
     align-items: center;
     justify-content: center;     
}

This center aligns all of the content:

figure8-1

Next we will add a dark overlay to cover the entire hero content. For that we’re going to make use of the pseudo after and set a background color. We also want it to cover the entire hero area, so we will set it’s position to absolute and set each side to have a value 0:

.hero::after {
     content: '';
     background-color: rgba(0,0,0, .7);
     display: block;
     
     top: 0;
     left: 0;
     right: 0;
     bottom: 0;
     position: absolute;
}

This adds the overlay onto the hero container:

figure9-1

Now we’re going to style the hero content, we need to set the color for the text:

.hero-content {
     color: var(--white); 
}

This doesn’t quite work, as you can see it sets the color to gray:

figure10-1

This happens because we have the overlay after content that is on top of the hero items. To fix this, we’ll set the position of the hero-content to relative and bring the content forward with z-index:

.hero-content {
     color: var(--white);
     position: relative;
     z-index: 1; 
}

figure11-1

Now we have the hero-content moved on top of the overlay.We need to position all of the contents inside the hero-content div to center. We can achieve this with Flexbox, but it will mean that we write more code:

.hero-content {
     color: var(--white);
     position: relative;
     z-index: 1;
     
     display: flex;
     flex-direction: column;
     align-items: center;
}

Now all the content is centered:

figure12-1

However, we can achieve the same result without having to write all of the Flexbox properties with just the text-align property:

.hero-content {
     color: var(--white);
     position: relative;
     z-index: 1;
     
     text-align: center;
}

This has the exact same effect as the Flexbox properties, only this time we are only using a single property to get the same result. You don’t have to use Flexbox for everything, it’s great for layouts, but it’s perfectly fine to use text-align to center the content as well.

Styling the main container

We’re going to finish styling the hero content area, we have already added a pin icon using the font awesome icon library that we have already added to our page. We’re going to style this by adding a font size and color:

figure13-1

Next we’re going to style the button, the styles are pretty much standard for a typical button:

.button {
     background-color: var(--secondary);
     padding: .5rem 3rem;
     border-radius: 5px;
     display: inline-block;
     margin-top: .5rem;
     font-weight: 700;
     text-decoration: none;
     text-transform: uppercase;
     font-size: 1.2rem;
     border: none;
     color: var(--white);
     cursor: pointer;
}

This styles our button nicely:

figure14-1

We’re now going to turn our attention to the main container area, this is the div that holds the services and contact form items. The following are the styles for the main container area:

.container {
     margin: 2rem auto 3rem auto;
     max-width: 1200px;
     padding: 2rem;
     background-color: var(--white);
     box-shadow: 0px 4px 12px -1px rgba(0,0,0,0.45);
     border-radius: 1rem;
}

This nicely styles our main container area, and gives it a nice box shadow effect:

figure15-1

Styling the services section

We’re going to now style the services section. Let’s first add some background color the page, for that we’ll use linear-gradient. First we need to add min-height to the HTML parent element and set that to 100%:

html {
     box-sizing: border-box;
     min-height: 100%;
}

Then we’re also going to set the min-height in the body element and set the linear gradient also:

body {
     font-family: var(--mainFont);
     min-height: 100%;
     background: linear-gradient(to top, #dfe9f3 0%, white 100%);
}

This will give a nice blue gradient color that will go from bottom to top:

figure16-1

Next we’re going to style the h2 and h3 elements:

h2, h3 {
     text-align: center;
}
h3 {
     color: var(--secondary);
     font-weight: 400;
     font-size: 1.6rem;
}

figure17-1

We’re going to use Flexbox to create the row of 3 service boxes when viewed in larger viewports. So when viewed in smaller devices like mobiles, the services divs will stack like above. But when viewed at 768px or higher they will be in a row:

@media (min-width:768px) {
     .services-container {
          display: flex;
          justify-content: space-between;
     }
     .service {
          flex: 0 0 calc(33.3% - 1rem);
     }
}

When viewed in larger viewports the services items are in a row:

figure18-1

Styling the icons

We have already added the icons to each service box, so we just need to style them. We will set the service container div with the class service as the flex container and center align the items using Flexbox:

.service {
     display: flex;
     flex-direction: column;
     align-items: center;
}

It’s worth noting that we can also use the text-align property top achieve the same result. So now the items, the h3 and the icons div, are nicely centred in side the flex container:

figure19-1

Next we’re going to add stiles for the icons div:

.icons {
     height: 100px;
     width: 100px;
     display: flex;
     background-color: var(--primary);
     border-radius: 50%;
     align-items: center;
     justify-content: space-evenly;
}

This styles the icons div nicely:

figure20-1

Finally for the icons we need to make them bigger so we’ll apply a font size to the icons:

.icons i {
     font-size: 2rem;
}

figure21-1

Styling the contact form

The following is the styles for the contact form, the majority of the css code is pretty straightforward. We have added the class w-100 to target the mail and message fields to make them take up the entire width available:

form {
     background-color: var(--gray);
     padding: 2rem;
     border-radius: 1rem;
}

@media (min-width:768px) {
     form {
          max-width: 800px;
          margin: 0 auto;
     }
     .form-container{
          display: flex;
          justify-content: space-between;
          flex-wrap: wrap;
     }
     .field {
          flex: 0 0 calc(50% - 1rem);
     }
}

.field {
     display: flex;
     margin-bottom: 1rem;
     align-items: center;
}

.field label {
     flex: 0 0 90px;
     color: var(--white);
}

.field input[type="text"], 
.field input[type="tel"],
.field input[type="mail"],
.field textarea{
     flex: 1;
     height: 2.4rem;
}

.w-100{
     flex: 0 0 100%;
}

.field textarea {
     height: 4rem;
}

.submit-form {
     display: flex;
     justify-content: flex-end;
}

This completes our freelancer website and nicely styles the contact form:

figure22-1