Create a Professional Website: HTML & CSS For Beginners

html & css Oct 13, 2023

HTML and CSS are the fundamental building blocks of the web. They're almost always the first thing you learn when becoming a front-end or full-stack web developer. In this tutorial, we'll be creating a simple, professional website using HTML and CSS that we deploy to Netlify. I'm going to take you from just having a Figma file, which is just the layout design, to creating a full-blown responsive webpage. The project itself is a bit advanced for beginners, however, I'm going to explain absolutely everything to the best of my abilities and we'll talk about things like layout, naming conventions, and so on. So this will be a relatively long project. So grab some tea or a cup of coffee and let's build a website.

You can find the video version of this tutorial here.

The Project

The project that we will be building is actually from a website called iCodeThis, which is a new daily coding challenge website, run by my buddy Florin Pop. It's full of UI challenges using HTML, CSS as well as JavaScript, and I thought it would be a great place to find a project for this tutorial. This is one of the larger projects, but if you're fairly new to HTML and CSS, there are a ton of smaller UI projects that you can try out. There are free and paid challenges. They have a fully functional in-browser IDE that is very similar to VS Code. So it's something you may want to check out. For a limited time, you can use the code BRAD to get 10% off.

So the project we'll be doing is called Growth Landing Page. It is a website for a SaaS or "Software as a Service" company. I thought this was a good project because it's not super hard, beginners can follow it, and it's not super easy either. It's a good middle ground. This is one of the pro projects, however, I got permission to share the Figma file with you guys. Figma is a very popular design tool. It runs in the browser and it's free. So you can follow along with the design and you can also download the Figma file here and use it as a reference.

This will not be a pixel-perfect copy of the design. I'm going to make some changes to make it a little bit easier to build. We are also only doing the front landing page. If you want to do some inner pages, that is up to you. Once we get the main layout, adding inner pages is easy.

Let's look at the main sections that we will be creating:

  • Navbar: The navbar will include a logo and a menu with links. The login link will be styled as a button. We will create some button utility classes to make it easy to style buttons. We will use flexbox to align the logo and menu along with the links in the menu.
  • Hero: The main hero or showcase section will have a large heading, sub-heading, two buttons and some images related to this fictional platform. We could do this in multiple ways. We could slice out each image and put them inline, but since we don't need to interact with the images at all, we can just create one image and use it as a background image. We will also use our button classes here.
  • Video Section: We have a simple video section with a thumbnail and a play icon along with another button.
  • Testimonials: The testimonials section will have a heading and some cards with some text. We'll use CSS Grid to align these. -Pricing: The pricing section will have two boxes. One for the simple free plan and one for the premium plan. There is a small header and footer to this section as well.
  • FAQ: The FAQ section will have a heading and some questions and answers. We are going to use a little bit of JavaScript to toggle the answers.
  • Footer: The footer will have a logo, some links and a newsletter signup form.
  • Hamburger Menu & Mobile Nav: We will have an icon on smaller screens that will slide open a menu on the right. We will be writing a bit of JavaScript for this.

Using Figma & Exporting Images

This part of the project is completely optional. If you want to use the Figma file, you can download it https://shismqklzntzxworibfn.supabase.co/storage/v1/object/public/pro-challenges/landing.fig. I will show you how to export images if you want to do it yourself, but you can also just get the already sliced images from the GitHub repo.

If you want to use Figma, you can create a free account at https://www.figma.com. Once you're logged in, you can go to the file menu and choose Open File. You can then choose the file that you downloaded. You can also just drag and drop the file into the browser.

Once you have the file open, you can click on the Layers tab on the left. This will show you all the layers in the design. You can click on any layer to select it. You can also click on the eye icon to hide a layer.

If you want to export an image, you can click on the layer and then click on the "Export" button at the top right. You can then choose the format and size. You can also choose to export all the layers at once.

Whether you slice the images yourself or download them from the GitHub repo, create a new folder on your machine called sass-website and create an images folder inside of that. Put all the images in there.

Start Coding

Once you have the images, open the project folder in your editor or IDE. I am using VS Code, but you can really use anything. If you are using VS Code, I would suggest using the Live Server extension. This will allow you to see your changes live in the browser as you make them.

Create a file in the root called index.html. This will be our main HTML file. We will also create a folder called css with a style.css file. This will be our main CSS file. There will be a bit of JavaScript, so create a folder called js with a main.js file.

Base HTML & CSS

Let's add the basic HTML structure to our index.html file. We will link our CSS file as well as the Poppins font and the Font Awesome library for icons. I also included a favicon. You can use the one I have in the GitHub repo or you can create your own. Finally, we will add the JS file at the bottom of the body.

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Growth App</title>
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link rel="preconnect" href="https://fonts.googleapis.com" />
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
    <link
      href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600;700&display=swap"
      rel="stylesheet"
    />
    <link
      rel="stylesheet"
      href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.2/css/all.min.css"
      integrity="sha512-z3gLpd7yknf1YoNbCzqRKc4qyor8gaKU1qmn+CShxbuBusANI9QpRohGBreCFkKxLhei6S9CQXFEbbKuqLg0DA=="
      crossorigin="anonymous"
      referrerpolicy="no-referrer"
    />
    <link rel="stylesheet" href="css/style.css" />
    <link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon" />
  </head>
  <body>
    <!-- Code here -->

    <script src="js/main.js"> </script>
  </body>
</html>

We are going to build desktop-first and then make it responsive for smaller screens after using media queries. So as we are creating the website, for now, have your browser at around 1200px wide. We will make it responsive later on.

For the base CSS, we will do the following:

  • Include a simple reset that will set box-sizing to border-box and remove any margin and padding from all elements.
  • Add some custom properties in the root scope for the main colors. This is so we can easily change the colors later on if we want to.
  • Set the font family of the body to Poppins, set the background to white and set the font size to 16px.
  • Set the line height to 1.5.
  • Remove the underline from all links and remove the list style from all unordered lists.
  • Set the max width of all images to 100% so that they don't overflow their container.
* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  --primary-color: #4891ff;
  --light-color: #f4f4f6;
  --dark-color: #111;
}

body {
  font-family: 'Poppins', sans-serif;
  background: #fff;
  font-size: 16px;
  line-height: 1.5;
}

a {
  text-decoration: none;
}

ul {
  list-style: none;
}

img {
  max-width: 100%;
}

Now we will add the HTML for the Navbar. I am not going to add the hamburger button and mobile menu just yet. We will do that later on.

<nav class="navbar">
  <div class="container">
    <div class="logo">
      <a href="index.html"><img src="images/logo.png" alt="logo" /></a>
    </div>
    <div class="main-menu">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Blog</a></li>
        <li>
          <a class="btn btn-light" href="#"
            ><i class="fas fa-user"></i>Log In</a
          >
        </li>
      </ul>
    </div>
  </div>
</nav>

There is a logo on the left and a menu on the right. We will use flexbox to align these. We will also use flexbox to align the links in the menu. We will use a utility class called btn for the login button. We will also use a utility class called btn-light to style the button. Let's add the main navbar stuff first, then we will create the utility classes.

.navbar {
  background: #fff;
  padding: 20px;
}

.navbar .container {
  display: flex;
  justify-content: space-between;
  align-items: space-between;
}

.navbar .main-menu ul {
  display: flex;
}

.navbar ul li a {
  color: #333;
  text-decoration: none;
  padding: 10px 20px;
  display: block;
  font-weight: 600;
  transition: 0.5s;
}

.navbar ul li a:hover {
  color: var(--primary-color);
}

.navbar ul li:last-child a {
  margin-left: 10px;
  text-align: center;
}

.navbar ul li:last-child i {
  margin-right: 10px;
}

We put display: flex on the container, rather than the navbar itself because the container is what directly wraps the items that I want to make flex items. We will create the container class soon.

We use justify-content: space-between to push the logo and menu to the left and right respectively. We also use align-items: center to vertically align the logo and menu. We use display: flex on the menu itself to align the links horizontally. We then style the links and add a hover effect. Finally, we add some margin to the login button and some margin to the right of the icon.

Notice I did not use the class .main-menu for the basic styling other than displaying as flex. This is because I want a lot of these styles to apply to the mobile menu as well. So I will use the .mobile-menu class for the mobile menu and I will use the .navbar ul selector for the basic styling of both.

I want to mention this again. We are doing the hamburger menu last, so it may not look great on small screens at the moment.

Utility Classes

Utility classes are an important part of any project. They allow you to create reusable classes that you can use throughout your project. This is a great way to keep your code DRY (Don't Repeat Yourself). We will create a few utility classes for the container, buttons, text, cards and more.

Let's add the containers. Some sections of the website are much more narrow than others. So we will have a container class as well as a container-sm class.

.container {
  max-width: 1170px;
  margin: 0 auto;
  padding: 0 15px;
}

.container-sm {
  max-width: 800px;
  margin: 0 auto;
  padding: 0 15px;
}

We could just put the margin and padding in one container class, but you would have to override it for the smaller containers. So I will just separate classes. It is all preference though.

Button Classes

For buttons, we will have a core btn class and then we will have a few modifier classes for different colors. We will also have a btn-block class to make the button full width.

.btn {
  display: inline-block;
  padding: 13px 20px;
  background: var(--primary-color);
  color: #fff;
  font-weight: 600;
  text-decoration: none;
  border: none;
  border-radius: 10px;
  cursor: pointer;
  transition: 0.5s;
}

.btn-primary {
  background: var(--primary-color);
  color: #fff;
}

.btn-primary:hover {
  opacity: 0.8;
}

.btn-light {
  background: var(--light-color);
  color: #333;
}

.btn-light:hover {
  background: opacity(0.8);
  color: var(--primary-color);
}

.btn-dark {
  background: var(--dark-color);
  color: #fff;
}

.btn-dark:hover {
  background: opacity(0.8);
  color: var(--dark-color);
}

.btn-block {
  display: block;
  width: 100%;
}

We have color variations of btn-primary, btn-light and btn-dark.

We have more utility classes, but let's move on to the next section and we will add them as we need them.

Hero Section

The hero has a large heading, some text, buttons and what looks like multiple images. There are a few ways to handle this. We could slice out each image and put them inline, but since we don't need to interact with the images at all, we can just create one image and use it as a background image. Again, this is just preference. You can do it either way.

Here is the HTML:

<section class="hero">
  <div class="container">
    <div class="hero-content">
      <h1 class="hero-heading text-xxl">
        A powerful solution to grow your startup. Fast!
      </h1>
      <p class="hero-text">
        Organize, collaborate, and track progress seamlessly with our
        one-stop-shop startup growth tool.
      </p>
      <div class="hero-buttons">
        <a class="btn btn-primary" href="#">Get Started</a>
        <a class="btn btn-light" href="#"
          ><i class="fas fa-laptop"></i> Book a Demo</a
        >
      </div>
    </div>
  </div>
</section>

Here is the CSS

.hero {
  margin-bottom: 50px;
}

.hero .container {
  background: url('../images/hero-bg.png') no-repeat;
  background-size: contain;
  background-position: center bottom;
  height: 550px;
}

.hero .hero-content {
  width: 70%;
}

.hero .hero-text {
  width: 70%;
  margin-bottom: 20px;
}

We used the background image on the container. We set the background size to contain so that it doesn't overflow the container. We also set the background-position to center bottom so that it is centered horizontally and at the bottom vertically. We set the height to 550px so that it is tall enough to fit the image.

I did not want the text to go all the way to the right, so I set the width of the .hero-content div to 70%. I also set the width of the .hero-text paragraph to 70% and added some bottom margin.

Text Styles

I want to have classes for different text sizes. We used the class text-xxl for the hero heading. Let's add that class as well as a few others.

.text-xxl {
  font-size: 3rem;
  line-height: 1.2;
  font-weight: 600;
  margin: 40px 0 20px 0;
}

.text-xl {
  font-size: 2.2rem;
  line-height: 1.4;
  font-weight: normal;
  margin: 40px 0 20px 0;
}

.text-lg {
  font-size: 1.8rem;
  line-height: 1.2;
  font-weight: normal;
  margin: 30px 0 20px 0;
}

.text-md {
  font-size: 1.2rem;
  line-height: 1.4;
  font-weight: normal;
  margin: 20px 0 10px 0;
}

.text-sm {
  font-size: 0.9rem;
  line-height: 1.4;
  font-weight: normal;
  margin: 10px 0 5px 0;
}

.text-center {
  text-align: center;
}

Now we have a bunch of different sizes that we can use. We also have a text-center class to center text. I used rem units for sizing, which is relative to the root font size. So if we change the root font size, all the text sizes will change. This makes the layout more flexible. 1 rem is equal to 16px, so 3rem is equal to 48px.

So far, the website should look like this:

Background Classes

The next section is the video section and it will have a black background. I want to create some classes that we can add on any element to give it a background color. We will have bg-primary, bg-light, bg-dark and bg-black.

.bg-primary {
  background: var(--primary-color);
  color: #fff;
}

.bg-black {
  background: #000;
  color: #fff;
}

.bg-dark {
  background: var(--dark-color);
  color: #fff;
}

.bg-light {
  background: var(--light-color);
  color: #333;
}

Video Section

Now let's add the HTML for the video section:

<section class="video bg-black">
  <div class="container-sm">
    <div class="video-heading text-xl text-center">
      See how it works and get started in less than 2 minutes
    </div>
    <div class="video-content">
      <a href="#">
        <img src="./images/video-preview.png" alt="" class="video-preview" />
      </a>

      <a href="#" class="btn btn-primary">Get Started</a>
    </div>
  </div>
</section>

This is pretty simple. We have a heading, a thumbnail and a button. We will use flexbox to align the items in the .video-content div.

.video {
  padding: 10px 0 40px;
}

.video .video-preview {
  width: 100%;
  background: #333;
  position: relative;
  margin-bottom: 20px;
}

.video .video-content {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin-top: 20px;
}

The video section should look like this:

Testimonials Section

Now we will do the testimonials, which will be a heading and then 3 cards with some testimonials. We will use CSS Grid to align the cards.

<section class="testimonials bg-dark">
  <div class="container">
    <h3 class="testimonials-heading text-xl">
      Don't just take our word for it, see the success stories from businesses
      just like yours.
    </h3>
    <div class="testimonials-grid">
      <div class="card">
        <p>
          “Our business has seen a significant increase in productivity since we
          started using the Growth app.”
        </p>

        <p>Katherine Smith</p>
        <p>Capodopera</p>
      </div>

      <div class="card">
        <p>
          “As a small business owner, it's important to have a tool that can
          help me keep track of everything. The Growth app has been a lifesaver
          for me, allowing me to manage my contacts, schedule appointments, and
          track progress all in one place..”
        </p>

        <p>Johnathan Lee</p>
        <p>Red Bolt</p>
      </div>

      <div class="card">
        <p>
          “The dashboards and reporting feature has provided valuable insights
          into our performance and helped us make data-driven decisions. It's a
          game changer for us.”
        </p>

        <p>David Wilson</p>
        <p>Slide</p>
      </div>
    </div>
  </div>
</section>

Testimonials CSS

.testimonials {
  padding: 40px 0;
}

.testimonials .testimonials-heading {
  width: 700px;
  margin-bottom: 40px;
}

.testimonials .testimonials-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-gap: 20px;
}

.testimonials .card p:nth-child(2) {
  margin-top: 30px;
  font-weight: bold;
}

We used CSS Grid to align the cards. We used grid-template-columns: repeat(3, 1fr) to create 3 columns with equal width. We also added some margin to the second paragraph in the card.

Card Class

We will add another utility class for cards, since we will use them in multiple places.

.card {
  background: #fff;
  color: #000;
  border-radius: 10px;
  padding: 20px;
}

The testimonials section should look like this:

Pricing Section

Now we will create our pricing boxes. We will be using a lot of the utility classes that we created earlier.

<section class="pricing">
  <div class="container-sm">
    <h3 class="pricing-heading text-xl text-center">Pricing</h3>
    <p class="pricing-subheading text-center text-md">
      Start free and scale while you grow. No hidden fees. Unlimited users for
      free.
    </p>

    <div class="pricing-grid">
      <!-- Pricing Card 1 -->
      <div class="card bg-light">
        <div class="pricing-card-header">
          <h4 class="pricing-card-heading text-xl">Simple</h4>
          <p class="pricing-card-subheading">
            Keep track of your contacts, gain valuable insights, analyse live
            data and performance metrics.
          </p>
          <p class="pricing-card-price">
            <span class="text-xl">Free</span> *No credit card required
          </p>
        </div>
        <div class="pricing-card-body">
          <ul>
            <li><i class="fas fa-check"></i> Real-Time Monitoring</li>
            <li>
              <i class="fas fa-check"></i>Track key performance indicators
            </li>
            <li><i class="fas fa-check"></i>Schedule appointments</li>
            <li>
              <i class="fas fa-check"></i>Organize, delegate and keep track of
              tasks
            </li>
          </ul>
          <a href="#" class="btn btn-primary btn-block">Get Started</a>
        </div>
      </div>

      <!-- Pricing Card 2 -->
      <div class="card bg-black">
        <div class="pricing-card-header">
          <h4 class="pricing-card-heading text-xl">Premium</h4>
          <p class="pricing-card-subheading">
            Keep track of your contacts, gain valuable insights, analyze live
            data and performance metrics.
          </p>
          <p class="pricing-card-price">
            <span class="text-xl">$49</span> /month
          </p>
        </div>
        <div class="pricing-card-body">
          <p>Everything from the free plan plus:</p>
          <ul>
            <li><i class="fas fa-check"></i>Data-driven decisions</li>
            <li><i class="fas fa-check"></i>Data visualization</li>
            <li><i class="fas fa-check"></i>Schedule appointments</li>
          </ul>
          <a href="#" class="btn btn-primary btn-block">Get Started</a>
        </div>
      </div>
    </div>
    <p class="pricing-footer text-center">
      All prices are in USD and charged per month with applicable taxes added at
      checkout.
    </p>
  </div>
</section>

We added a heading area and then 2 cards. We used background, text and button classes to style the cards and added some font awesome icons. We also added a footer.

Pricing CSS

.pricing .pricing-grid {
  margin-top: 50px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  grid-gap: 30px;
}

.pricing .pricing-card-subheading {
  margin-bottom: 30px;
}

.pricing .pricing-card-price {
  margin-bottom: 30px;
  padding: 20px 0;
  border-bottom: 1px solid #ccc;
}

.pricing ul {
  margin: 30px 0;
}

.pricing ul li {
  margin-bottom: 20px;
}

.pricing ul li i {
  margin-right: 10px;
}

.pricing .btn {
  text-align: center;
  margin-top: 20px;
}

.pricing .pricing-footer {
  margin: 30px 0;
}

In the CSS, we used the grid system to align the cards. We also added some margin and padding to some of the elements.

The pricing section should look like this:

FAQ Section

The FAQ section is going to be a bit dynamic, so we will be using JavaScript so that we can click on the header of a question and then open the body/answer.

We will have a little menu at the top for categories, but it is just for looks, we won't be using it for anything.

Here is the HTML:

<section class="faq bg-light">
  <div class="container-sm">
    <h3 class="text-xl text-center">Frequently Asked Questions</h3>
    <ul class="faq-menu">
      <li class="active">All</li>
      <li>Getting Started</li>
      <li>Pricing</li>
    </ul>
    <div class="faq-content">
      <div class="faq-group">
        <div class="faq-group-header">
          <h4 class="text-md">
            How does the contact management feature help me keep track of
            clients and partners?
          </h4>
          <i class="fas fa-minus"></i>
        </div>
        <div class="faq-group-body open">
          <p>
            Keep track of your contacts, gain valuable insights, analyse live
            data and performance metrics.
          </p>
        </div>
      </div>

      <div class="faq-group">
        <div class="faq-group-header">
          <h4 class="text-md">
            Can I customize the dashboards and reporting feature to display the
            metrics that are most important to my business?
          </h4>
          <i class="fas fa-plus"></i>
        </div>
        <div class="faq-group-body">
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Ad culpa
            enim blanditiis rem ipsum aliquam, unde iste fugit praesentium eos?
          </p>
        </div>
      </div>

      <div class="faq-group">
        <div class="faq-group-header">
          <h4 class="text-md">
            How does the task management feature help me delegate tasks to my
            team and track progress?
          </h4>
          <i class="fas fa-plus"></i>
        </div>
        <div class="faq-group-body">
          <p>
            Lorem ipsum dolor sit amet, consectetur adipisicing elit. Incidunt,
            a! Quaerat, voluptatum. Animi molestias ex quasi explicabo minima
            perferendis commodi.
          </p>
        </div>
      </div>

      <div class="faq-group">
        <div class="faq-group-header">
          <h4 class="text-md">
            Can I collaborate with my team in real-time using all tools?
          </h4>
          <i class="fas fa-plus"></i>
        </div>
        <div class="faq-group-body">
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Obcaecati
            doloremque assumenda aut dolorem recusandae quibusdam aliquid.
            Repellat animi quam vitae.
          </p>
        </div>
      </div>

      <div class="faq-group">
        <div class="faq-group-header">
          <h4 class="text-md">Is the app available on all devices?</h4>
          <i class="fas fa-plus"></i>
        </div>
        <div class="faq-group-body">
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Obcaecati
            doloremque assumenda aut dolorem recusandae quibusdam aliquid.
            Repellat animi quam vitae.
          </p>
        </div>
      </div>

      <div class="faq-group">
        <div class="faq-group-header">
          <h4 class="text-md">
            How does the app help me stay compliant when working with
            freelancers and contractors?
          </h4>
          <i class="fas fa-plus"></i>
        </div>
        <div class="faq-group-body">
          <p>
            Lorem, ipsum dolor sit amet consectetur adipisicing elit. Obcaecati
            doloremque assumenda aut dolorem recusandae quibusdam aliquid.
            Repellat animi quam vitae.
          </p>
        </div>
      </div>
    </div>
  </div>
</section>

So basically, we have a group for each question. Each group has a header and a body. The header has a question and an icon. The body has the answer. We will use JavaScript to toggle the body open and closed.

FAQ CSS

.faq {
  padding: 40px 0;
}

.faq .faq-group {
  border-bottom: 1px solid #ccc;
  padding-bottom: 20px;
}

.faq .faq-group-header {
  border-radius: 10px;
  padding: 20px 0;
  margin-bottom: 15px;
  position: relative;
}

.faq .faq-group-header h4 {
  font-weight: 600;
  width: 95%;
}

.faq i {
  position: absolute;
  right: 0;
  top: 35px;
  font-size: 1.5rem;
  cursor: pointer;
}

.faq .faq-group-body {
  display: none; /* Hide the content by default */
}

.faq .faq-group-body.open {
  display: block; /* Show the content when open */
}

.faq ul.faq-menu {
  max-width: 400px;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: auto;
  margin-bottom: 20px;
  cursor: pointer;
  background: #f4f4f6;
  padding: 10px 20px;
  border-radius: 10px;
  font-weight: 600;
}

.faq ul.faq-menu li {
  padding: 10px 20px;
  border-radius: 5px;
  text-align: center;
}

.faq ul.faq-menu li.active {
  background: var(--primary-color);
  color: #fff;
}

We used display: none on the .faq-group-body class to hide the content by default. We then used display: block on the .faq-group-body.open class to show the content when the class is added.

We used flexbox to align the menu items and we used the active class to style the active menu item.

FAQ JavaScript

now we need to make this function. I want to be able to click on the plus sign and toggle the open class on the parent element. We will use the closest() method to get the parent element. We will then use the querySelector() method to get the body element. We will then toggle the open class on the body element.

We will also toggle the plus and minus icons. We will use the classList property to toggle the classes.

We will also make it so that when we open one group, all the other groups close. We will use the querySelectorAll() method to get all the groups. We will then loop through them and close them all except the one that was clicked.

document.addEventListener('DOMContentLoaded', () => {
  const faqContainer = document.querySelector('.faq-content');

  faqContainer.addEventListener('click', (e) => {
    const groupHeader = e.target.closest('.faq-group-header');

    if (!groupHeader) return; // Ignore clicks that aren't on group headers

    const group = groupHeader.parentElement;
    const groupBody = group.querySelector('.faq-group-body');
    const icon = groupHeader.querySelector('i');

    // Toggle the plus and minus icons
    icon.classList.toggle('fa-plus');
    icon.classList.toggle('fa-minus');

    // Toggle the visibility of the FAQ group body
    groupBody.classList.toggle('open');

    // Close other open FAQ group bodies
    const otherGroups = faqContainer.querySelectorAll('.faq-group');
    otherGroups.forEach((otherGroup) => {
      if (otherGroup !== group) {
        const otherGroupBody = otherGroup.querySelector('.faq-group-body');
        const otherIcon = otherGroup.querySelector('.faq-group-header i');

        otherGroupBody.classList.remove('open');
        otherIcon.classList.remove('fa-minus');
        otherIcon.classList.add('fa-plus');
      }
    });
  });
});

Now you should be able to click on the plus sign and open the body. You should also be able to click on another plus sign and open that body while closing the other one.

The FAQ section should look like this:

The footer will have 4 grid columns. The first will have a newsletter form in a card and the rest will just be links.

<footer class="footer bg-black">
  <div class="container">
    <div class="footer-grid">
      <div>
        <a href="index.html"><img src="images/logo-white.png" alt="logo" /></a>
        <div class="card">
          <h4>Subscribe to newsletter</h4>
          <p class="text-sm">
            Subscribe now to receive tips on how to take your business to the
            next level.
          </p>
          <form action="">
            <input type="email" placeholder="Enter your email" />
            <button type="submit" class="btn btn-primary btn-block">
              Subscribe
            </button>
          </form>
        </div>
        <i class="fab fa-linkedin"></i>
        <i class="fab fa-twitter"></i>
      </div>
      <div>
        <h4>Company</h4>
        <ul>
          <li><a href="#">About Us</a></li>
          <li><a href="#">Our Process</a></li>
          <li><a href="#">Join Our Team</a></li>
        </ul>
      </div>
      <div>
        <h4>Resources</h4>
        <ul>
          <li><a href="#">News</a></li>
          <li><a href="#">Research</a></li>
          <li><a href="#">Recent Projects</a></li>
        </ul>
      </div>
      <div>
        <h4>Contact</h4>
        <ul>
          <li><a href="#">[email protected]</a></li>
        </ul>
      </div>
    </div>
  </div>
</footer>
.footer {
  padding: 40px 0;
}

.footer h4 {
  margin-bottom: 10px;
}

.footer ul li {
  line-height: 2.5;
}

.footer a {
  color: #ccc;
}

.footer i {
  font-size: 1.5rem;
  margin-right: 10px;
}

.footer .footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr 1fr;
  grid-gap: 30px;
  justify-items: center;
  align-items: center;
}

.footer .card {
  margin: 20px 30px 30px 0;
}

.footer .card input[type='email'] {
  width: 100%;
  padding: 10px;
  border: 1px solid #ccc;
  border-radius: 5px;
  margin: 20px 0;
}

We made the first column 2fr and the rest 1fr. We styled the input as well.

The footer should look like this:

Hamburger Button & Mobile Menu

Now we want to start making this look good on smaller screens. Let's start by adding the HTML for the hamburger button and mobile menu.

This is what your entire nav should look like:

<nav class="navbar">
  <div class="container">
    <div class="logo">
      <a href="index.html"><img src="images/logo.png" alt="logo" /></a>
    </div>
    <div class="main-menu">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Blog</a></li>
        <li>
          <a class="btn btn-light" href="#"
            ><i class="fas fa-user"></i>Log In</a
          >
        </li>
      </ul>
    </div>
    <!-- Hamburger Button -->
    <button id="hamburger-button" class="hamburger-button">
      <div class="hamburger-line"></div>
      <div class="hamburger-line"></div>
      <div class="hamburger-line"></div>
    </button>
    <!-- Mobile Menu -->
    <div class="mobile-menu">
      <ul>
        <li><a href="index.html">Home</a></li>
        <li><a href="#">About Us</a></li>
        <li><a href="#">Blog</a></li>
        <li>
          <a class="btn btn-light" href="#"
            ><i class="fas fa-user"></i>Log In</a
          >
        </li>
      </ul>
    </div>
  </div>
</nav>

Let's add the CSS for them:

/* Hamburger Button */
.hamburger-button {
  display: none; /* Hide the button by default on larger screens */
  background: none;
  border: none;
  cursor: pointer;
  padding: 10px;
  z-index: 1000;
}

.hamburger-line {
  width: 30px;
  height: 3px;
  background: #333;
  margin: 6px 0;
  transition: 0.4s;
}

/* Mobile Menu */
.mobile-menu {
  position: fixed;
  z-index: 100;
  top: 0;
  right: -300px; /* Initially, it's hidden off-screen */
  width: 250px;
  height: 100%;
  background-color: #fff;
  box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
  transition: right 0.3s ease-in-out; /* Transition the right property */
}

.mobile-menu.active {
  right: 0;
}

.mobile-menu ul {
  margin-top: 100px;
  padding-right: 10px;
}

.mobile-menu ul li {
  margin: 10px 0;
}

.mobile-menu ul li a {
  font-size: 20px;
  transition: 0.3s;
}

We created the hamburger button and the mobile menu. We used display: none on the hamburger button so that it is hidden on larger screens. We used position: fixed on the mobile menu so that it is fixed to the top of the screen. We used right: -300px to hide it off-screen. We used transition: right 0.3s ease-in-out to transition the right property. We used right: 0 on the .mobile-menu.active class to show the menu when the class is added.

We want the menu to slide out on the right when we click the hamburger button. We will use JavaScript to add the .active class to the mobile menu when we click the hamburger button.

Hamburger Button & Mobile Menu JavaScript

document.addEventListener('DOMContentLoaded', function ( ) {
  const hamburgerButton = document.getElementById('hamburger-button');
  const mobileMenu = document.querySelector('.mobile-menu');

  hamburgerButton.addEventListener('click', () =>
    mobileMenu.classList.toggle('active')
  );
});

It still will not function how we want, because the hamburger menu is hidden and we need the main menu hidden on small screens. We will work on that now.

Responsive CSS / Media Queries

Now we want to make the site look good on smaller screens. We can use media queries to specify some CSS only for certain screen sizes. Those sizes will be 960px, 670px and 500px.

Let's start with the 960px media query. There is not much I want to do here. I just want the large text to be a bit smaller.

@media (max-width: 960px) {
  .text-xxl {
    font-size: 2.5rem;
  }
}

For the 670px, we will do quite a bit. We need to hide the main menu and show the hamburger button. I also want to change the background image on small screens, because the one we have, just will not work. It is too wide.

Also, any grid items need to be set to 1fr so that they are full width.

@media (max-width: 670px) {
  .navbar .hamburger-button {
    display: block; /* Show the button on smaller screens */
  }

  .navbar .main-menu {
    display: none; /* Hide the main menu on smaller screens */
  }

  /* Hero */
  .hero .container {
    background: url('../images/hero-bg-mobile.png') no-repeat;
    background-size: 350px 400px;
    background-position: bottom;
    height: 700px;
  }

  .hero .hero-content {
    width: 100%;
    text-align: center;
  }

  .hero .hero-text {
    width: 100%;
  }

  .video .container {
    width: 100%;
  }

  .testimonials .testimonials-heading {
    width: 100%;
    font-size: 1.8rem;
  }

  .pricing .container {
    width: 100%;
  }

  .testimonials .testimonials-grid,
  .pricing .pricing-grid,
  .footer .footer-grid {
    grid-template-columns: 1fr;
  }

  .footer .card {
    margin-right: 0;
  }

  .footer-grid > div {
    text-align: center;
  }

  .text-xl {
    font-size: 1.9rem;
  }

  .text-lg {
    font-size: 1.5rem;
  }

  .text-md {
    font-size: 1.1rem;
  }
}

Lastly, we have the 500px media query for mobile devices. All we are doing here is changing the font size of the large text and the height of the hero section.

@media (max-width: 500px) {
  .text-xxl {
    font-size: 2rem;
  }

  .hero .container {
    min-height: 700px;
  }
}

Now the site should look good on all screen sizes.

That's it! You should now have a nice-looking landing page for a SaaS product.

You can find the final code for this project here

Don't forget to check out the iCodeThis for daily web development challenges like this one.

Stay connected with news and updates!

Join our mailing list to receive the latest news and updates from our team.
Don't worry, your information will not be shared.

We hate SPAM. We will never sell your information, for any reason.