↑

CSS Documentation

CSS (Cascading Style Sheets) is what makes your favourite websites look the way they do. It controls the visual appearance of a webpage, from its layout, colours, and typography to its spacing, animations, and responsive behaviour.

Modern CSS has become incredibly powerful. It can be used to create complex layouts, interactive effects, animations, and interfaces that work across different screen sizes.

In this documentation, you will not just learn what CSS properties do. You will learn how to use CSS to solve real design problems and turn a plain HTML structure into a complete interface.

You will also be encouraged to experiment, make your own design decisions, and use CSS as a tool to express your creativity.

Your First Task

Imagine that you have just joined Scybud as a frontend developer. You have been given a task: turn an existing HTML structure into a beautiful, user-friendly dashboard for LogHue .

The HTML has already been prepared for you. Your job is to use CSS to transform that structure into the finished interface.

Throughout this documentation, we will work through the design step by step. You will see the decisions behind the interface, learn the CSS concepts needed to make those decisions, and apply them to the project.

By the end, you will have taken a plain HTML document and turned it into a real interface used by an actual product.

LogHue dashboard design draft

LogHue dashboard draft designed in Canva.

Credit: Abdulroqib Oladipo

Instructions

Design instructions
  • The page must be dark mode.
  • It should have exactly 2 columns on large screens.
  • It should be responsive.
  • It should have a left sidebar.
  • The sidebar navigation links should be stacked vertically.
  • The user profile should be at the bottom of the sidebar.
  • The welcome heading should be centered.
  • The notification bell should be in the top-right corner of the page.
  • The 3 statistic cards should be centered below the heading.
  • The search bar should be wide, rounded, and below the statistics.
  • The 2 action buttons should be centered below the search bar.
  • The layout should use generous spacing and a minimal design.
  • Buttons, cards, and the search bar should have rounded corners.

What is CSS?

CSS stands for Cascading Style Sheets. It is the language used to describe how HTML elements should look and be arranged on a webpage.

While HTML gives a webpage its structure, CSS controls its presentation. With CSS, you can change colours, sizes, spacing, positioning, layouts, typography, and much more.

Think of HTML as the structure of a building and CSS as everything that makes the building look and feel the way it does.

What can CSS do?

  • Change the colour and appearance of elements.
  • Control spacing and sizing.
  • Create layouts using Flexbox and Grid.
  • Make interfaces responsive.
  • Create animations and transitions.
  • Change how elements behave in different states.

In this documentation, you will learn these concepts by using them to build real interfaces rather than learning them only as isolated CSS properties.

CSS & HTML

CSS and HTML work together. HTML defines the structure and content of a webpage, while CSS determines how that structure is presented to the user.

For example, HTML can tell the browser that a piece of text is a heading:

<h1>Welcome to Scybud</h1>

CSS can then determine how that heading should look:

h1 {
  font-size: 2rem;
  text-align: center;
}

The HTML tells the browser what the element is. The CSS tells the browser how it should look.

This documentation assumes that you already understand the basics of HTML. If you don't, we recommend completing the Scybud HTML Documentation before continuing.

How This Course Works

This is not a collection of CSS properties for you to memorise. You are going to learn CSS by following the process of building a real interface.

Throughout the documentation, you will be given problems that a frontend developer might encounter while designing a webpage. We will solve those problems one at a time using CSS.

Learn by building

Instead of learning a property first and trying to find a reason to use it later, you will encounter a problem first and then learn the CSS concepts that can solve it.

For example, if our sidebar needs to remain visible while the user scrolls, we will first look at that problem. Then we will learn about the CSS positioning techniques that can solve it.

Follow the process

Each project will be broken into smaller parts. You will gradually build the interface from its basic layout to its smaller details.

  1. Understand the design and the requirements.
  2. Identify the problem we need to solve.
  3. Learn the CSS concept needed to solve it.
  4. Apply the concept to the project.
  5. Experiment and see what happens when you change it.
  6. Move on to the next problem.

Make it your own

As you progress, you will be given opportunities to make your own design decisions. There may be a reference design, but you should not feel limited to copying it exactly.

Look at different designs, get inspiration, experiment with ideas, and develop your own taste. The goal is not simply to reproduce someone else's interface. The goal is to learn how to create your own.

By the end of the documentation, you will be given a project to complete on your own using the skills you have learned.

The Design Brief

You have been given a real design task: style the LogHue dashboard using the HTML that has already been prepared for you.

Your job is to turn the existing structure into a complete, polished dashboard interface. You are not being asked to change what the page contains. You are being asked to decide how it should look and how the different parts of the interface should work together visually.

LogHue dashboard design

LogHue dashboard design.

Credit: Abdulroqib Oladipo

Requirements

  • The page must use a dark theme.
  • The sidebar should remain visible while the main content is being viewed.
  • The main content should have clear spacing and visual hierarchy.
  • The design should work on both desktop and smaller screens.
  • The different sections should feel like parts of the same interface.

The final design may not look exactly like the original sketch. That is intentional. A draft is used to communicate an idea, not necessarily to define every detail of the final product.

As a designer, you need to know when a design should be adapted, improved, or changed as you build it. The sketch is your starting point, but you should always consider the principles of good design and make decisions that improve the final result.

However, if you are explicitly asked to recreate a design exactly as it is, then your job is to reproduce it accurately. Even then, never forget the principles of design behind what you are creating.

Understanding the HTML

Before you start writing CSS, take a moment to understand the HTML you have been given. You are not starting with an empty file. The structure of the LogHue dashboard has already been built for you, and your job is to turn that structure into the design from the brief.

You do not need to understand every line of this document yet. Focus on identifying the major parts of the page and understanding how they are related to one another.

The main structure


<main class="main">


  <aside class="sidebar">
    <!-- Sidebar -->
  </aside>


  <article class="mainContent">
    <!-- Dashboard content -->
  </article>


</main>
  

The <main> contains the main layout of the dashboard. The <aside> represents the sidebar, while the <article> contains the main dashboard content.

Inside the dashboard

The main content is divided into smaller parts. There is a header containing the menu and notification button, followed by the dashboard section containing the greeting, statistics, search bar, and action buttons.


<article class="mainContent">


  <div class="contentHeader">
    <!-- Header -->
  </div>


  <section class="dashboard-section">
    <h1>Welcome back, Abdulroqib</h1>


    <div class="dashboardStats"></div>


    <div class="searchBarContainer">
      <!-- Search and buttons -->
    </div>
  </section>


</article>
  

Notice how the HTML already describes what each part of the interface is. CSS will determine how those parts are positioned, sized, spaced, and presented to the user.

The complete starter HTML

The two snippets above only showed the shape of the page. Below is the complete starter HTML for the LogHue dashboard, exactly as it will be given to you. Use the button to copy it, rather than typing it out by hand.

<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>Dashboard | LogHue</title>
</head>

<body>

  <main class="main">

    <aside class="sidebar" id="sidebarContainer">

      <nav class="sidebarNav" aria-label="Main navigation">

        <a href="#" class="active">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M3 10.5 12 3l9 7.5"></path>
              <path d="M5 9.5V21h14V9.5"></path>
              <path d="M9 21v-7h6v7"></path>
            </svg>
          </span>
          Dashboard
        </a>

        <a href="#">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M5 3h10l4 4v14H5z"></path>
              <path d="M15 3v5h4"></path>
            </svg>
          </span>
          Notes
        </a>

        <a href="#">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M6 4h12v16H6z"></path>
              <path d="M9 8h6M9 12h6M9 16h4"></path>
            </svg>
          </span>
          Tasks
        </a>

        <a href="#">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8">
              <rect x="4" y="4" width="16" height="16" rx="3"></rect>
              <path d="M8 8h8v8H8zM10 10h4v4h-4z"></path>
            </svg>
          </span>
          ScanHue
        </a>

        <a href="#">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M12 3l1.5 2.2 2.6.3.9 2.4 2.2 1.4-.8 2.5.8 2.5-2.2 1.4-.9 2.4-2.6.3L12 21l-1.5-2.2-2.6-.3-.9-2.4-2.2-1.4.8-2.5-.8-2.5 2.2-1.4.9-2.4 2.6-.3z"></path>
              <circle cx="12" cy="12" r="3"></circle>
            </svg>
          </span>
          Settings
        </a>

      </nav>

      <div class="sidebarHeading">Workspaces</div>

      <nav class="sidebarNav" aria-label="Workspace navigation">

        <a href="#">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M3 7h18v13H3z"></path>
              <path d="M3 7l2-3h6l2 3"></path>
            </svg>
          </span>
          My Workspaces
        </a>

        <a href="#">
          <span class="navIcon">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <circle cx="12" cy="12" r="9"></circle>
              <path d="M12 7v6l4 2"></path>
            </svg>
          </span>
          Archive
        </a>

      </nav>

      <button class="sidebarAction">
        <span>+</span>
        Create Workspace
      </button>

      <div class="profile">

        <div class="avatar"></div>

        <div class="profileInfo">
          <span class="profileName">Abdulroqib Oladipo</span>
          <span class="profilePlan">Pro Plan</span>
        </div>

        <button class="signOut" aria-label="Sign out">
          ⇥
        </button>

      </div>

    </aside>


    <article class="mainContent" id="dashboardContent">

      <div class="contentHeader">

        <button
          class="menuBtn"
          id="toggleSidebar"
          aria-label="Toggle Sidebar"
        >
          ☰
        </button>

        <div class="headerRight">

          <button
            class="notificationBtn"
            id="notificationToggleBtn"
            title="Notifications"
            aria-label="Notifications"
          >

            <span id="notifBadge" class="badge">0</span>

            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <path d="M18 9a6 6 0 0 0-12 0c0 7-3 7-3 9h18c0-2-3-2-3-9"></path>
              <path d="M10 21h4"></path>
            </svg>

          </button>

        </div>

      </div>


      <div id="modalContainer"></div>
      <div id="actionsMessage"></div>
      <div id="infoDisplay"></div>


      <div id="notificationsContainer" hidden>

        <h2>Notifications</h2>

        <ul id="notificationsList">
          <p class="placeholderText">Nothing here yet.</p>
        </ul>

      </div>


      <section class="dashboard-section">

        <div class="sectionHeader dashboardHeader">

          <h1 id="dashboardGreeting">
            Welcome back, Abdulroqib
          </h1>

        </div>


        <div class="dashboardStats" id="dashboardStats">

          <div class="statCard">
            <strong>3</strong>
            <span>open tasks</span>
          </div>

          <div class="statCard">
            <strong>33</strong>
            <span>notes</span>
          </div>

          <div class="statCard">
            <strong>5</strong>
            <span>workspaces</span>
          </div>

        </div>


        <div class="searchBarContainer">

          <div class="searchInputWrapper">

            <span class="searchIcon">

              <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <circle cx="11" cy="11" r="7"></circle>
                <path d="m16.5 16.5 4 4"></path>
              </svg>

            </span>

            <textarea
              name="mainSearchInput"
              id="mainSearchInput"
              class="inputField mainSearchInput"
              rows="1"
              placeholder="Search tasks..."
            ></textarea>

          </div>


          <div class="quickActionsContainer">

            <button
              class="actionBtn createWorkspaceOpen"
              aria-label="New Workspace"
            >
              + New Workspace
            </button>

            <button
              type="button"
              class="actionBtn createNoteBtn"
              aria-label="Create Note"
            >
              + Create Note
            </button>

          </div>

        </div>


        <div
          id="MainSearchResults"
          class="mainSearchResultContainer"
        ></div>

      </section>

    </article>

  </main>

</body>
</html>

Key structural elements

Before moving on, get familiar with the class names below. You will be targeting each of them with CSS throughout this project.

  • .main wraps the entire dashboard. It holds the sidebar and the main content side by side.
  • .sidebar is the left navigation panel, containing the main links, the workspace links, and the profile section.
  • .sidebarNav groups a set of sidebar links together. The sidebar uses two of these, one for the main navigation and one for workspaces.
  • .mainContent holds everything to the right of the sidebar, including the header and the dashboard section.
  • .contentHeader is the top bar of the main content. It contains the sidebar toggle button and the notification button.
  • .dashboardStats holds the three statistic cards showing open tasks, notes, and workspaces.
  • .dashboard-section wraps the greeting, the statistics, and the search area.
  • .searchBarContainer wraps the search input and the action buttons beneath it.
  • .quickActionsContainer holds the two action buttons, New Workspace and Create Note.

Set up your project

  1. Click the Copy HTML button above.
  2. Create a new file on your computer named index.html.
  3. Paste the copied HTML into that file and save it.
  4. Open index.html in your browser.

When you open the file, the page will look mostly unstyled. The headings, buttons, and text will appear, but stacked plainly with no layout, colour, or spacing. This is expected. The HTML only describes what the page contains. You have not written any CSS yet, so the browser is rendering everything with its own default styles.

Before you continue

Look through the complete HTML yourself. Try to identify the sidebar, header, notification button, greeting, statistics, search area, and action buttons. You will be styling these elements throughout the project.

Your First CSS

You have the HTML, and you know what the finished dashboard should look like. Now it is time to start turning that structure into the design.

Start by creating a <style> element inside the <head> of your HTML document. This is where you will write the CSS for this project.


<style>


  /* Your CSS goes here */


</style>
  

Start with the page

Look at the finished design. The entire page has a black background, light text, and no default browser spacing around the page.

Before styling the sidebar or dashboard, handle these basic properties first.


html,
body {
  margin: 0;
  background: #000;
  color: #f5f5f5;
  font-family: Arial, Helvetica, sans-serif;
}
  

The body is the starting point for the visible page. Removing its default margin allows the interface to reach the edges of the browser window.

What did you just write?

CSS rules follow a simple pattern: select something, then describe how it should look.


body {
  background: #000;
  color: #f5f5f5;
}
  

body is the selector. It tells the browser which HTML element the rule should affect.

background and color are properties. Their values tell the browser what those properties should be.

The braces { } contain the declarations that make up the rule.

Now look at the result

At this point, the dashboard will not look finished. That is expected. You have only established the foundation of the page.

The sidebar is still in the wrong position, the dashboard content has not been arranged, and the buttons and search bar have not been styled. Each of those is a separate problem that you will solve as you continue.

Why?

Do not try to write all the CSS at once. Start with the broad structure of the page, then work your way toward individual components. This makes it easier to understand what each rule is doing and why it is needed.

Checkpoint: Step 1, Page Foundation

Before moving on, compare your page to the screenshot below. At this stage the layout is still unstyled, but the background, text colour, and font should already match.

LogHue dashboard with a black background, light text, and the base sans-serif font applied, before any layout styling

Step 1, Page Foundation: dark background, light text, and base font applied. Layout is not yet arranged.

Note: You might see the home icon first. Dont worry, it didnt show here becuase it was commented out for better screenshot coverage.

Credit: Abdulroqib Oladipo

The Cascade

So far, we have given our page a basic foundation. But CSS becomes more interesting when more than one rule can affect the same element.

The word cascade describes how the browser decides which CSS rule should win when multiple rules apply to the same element.

When Rules Conflict

Imagine we want all text on the page to be light, but we also want the dashboard heading to have a different color.


body {
  color: #f5f5f5;
}

.dashboard-section h1 {
  color: #007fc3;
}
  

Both rules set the color property, but they target different levels of the page. The more specific selector .dashboard-section h1 can override the general body rule for that heading.

Specificity Matters

CSS does not simply use the last rule it sees. The browser considers several things when deciding which declaration should be applied, including the selector's specificity.

For example, compare these two rules:


h1 {
  color: white;
}

.dashboard-section h1 {
  color: #007fc3;
}
  

The first selector targets every <h1>. The second selector targets an <h1> inside .dashboard-section, making it more specific.

This means the dashboard heading receives the second color.

Try It Yourself

Add these rules to your stylesheet and look at the dashboard heading.


h1 {
  color: red;
}

.dashboard-section h1 {
  color: #007fc3;
}
  

Now remove the second rule. What happens?

Then change the selectors and see which rule wins. The goal is not to memorize a list of rules. Instead, learn to recognize when CSS rules compete with each other and understand why the browser chooses one.

Checkpoint: Understanding the Cascade

At this point, your page should still look the same as the previous checkpoint. The important change is understanding how CSS decides which styles should be applied when rules overlap.

LogHue dashboard showing the page foundation while learning how CSS rules interact

Cascade checkpoint: the page does not need a new visual change here. You are learning how CSS decides which rule takes effect.

Credit: Abdulroqib Oladipo

Review Questions

  1. What does the cascade determine?
  2. What happens when two CSS rules set the same property?
  3. Why is .dashboard-section h1 more specific than h1?
  4. What happens when you remove the more specific rule?
  5. Why is understanding the cascade important as a stylesheet becomes larger?

Page Layout

Our page has a problem. The HTML contains a sidebar and a main content area, but CSS has not told the browser where they should go.

Right now, the sidebar and the main content appear one after another. We want the sidebar on the left and the dashboard content beside it.

Creating the Two-Column Layout

The .main element contains both the sidebar and the main content, so it is the element we need to control.

CSS Grid is useful here because we can divide the page into columns: one for the sidebar and one for everything else.


.main {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 100vh;
}
  

display: grid

display: grid tells the browser that the children of .main should be arranged using the CSS Grid layout system.

grid-template-columns

This property defines how wide each column should be.


grid-template-columns: 260px 1fr;
  

The first column is 260px wide, which gives our sidebar a fixed width.

The second column uses 1fr. The fr unit means a fraction of the available space, so the main content takes the remaining width.

min-height: 100vh

100vh represents the height of the browser's viewport. Setting the minimum height to 100vh makes the layout fill at least the entire screen.

Checkpoint: Step 2, Page Layout

Your sidebar and main content should now appear beside each other. The sidebar has a fixed width, while the main content fills the remaining space.

LogHue dashboard with the sidebar and main content arranged as two columns

Step 2, Page Layout: the sidebar and main content now sit beside each other.

Credit: Abdulroqib Oladipo

Experiment

Change 260px to another value. What happens when you make the sidebar wider or narrower?

You can also temporarily replace 1fr with another value and observe how the available space changes.

Review Questions

  1. What does display: grid do?
  2. What does 260px control?
  3. What does 1fr mean?
  4. Why are we applying the grid to .main?
  5. What does 100vh represent?

The Sidebar

The page is now divided into two columns, but the sidebar still needs to be styled. Look at the design again. The navigation should feel like part of the interface rather than a collection of default links.

Before changing individual links and buttons, we first need to give the sidebar its visual foundation: a background, a border, and some space around its contents.

Giving the Sidebar a Background

The sidebar uses the class .sidebar, so we can target it directly.


.sidebar {
  background: #111;
  border-right: 1px solid #2a2a2a;
}
  

The background creates the darker surface that separates the sidebar from the rest of the dashboard.

The border-right adds a subtle line between the navigation and the main content.

Adding Space Inside

The sidebar contains several groups of content. Without any internal spacing, everything would sit directly against its edges.


.sidebar {
  background: #111;
  border-right: 1px solid #2a2a2a;
  padding: 20px 8px;
}
  

padding creates space between an element's content and its edges. Here, it gives the navigation some breathing room.

Styling the Navigation Links

Our HTML already gives each navigation item a useful structure: an <a> element containing an icon and its label. We can use CSS to turn those links into full-width navigation items.

Styling the Navigation Items

Start by selecting the links inside the sidebar.


.sidebar a {
  background: none;
  border: none;
  width: 100%;
  padding: 8px;
  font-size: 0.875rem;
  border-radius: 8px;
  color: #f5f7fa;
  cursor: pointer;
  transition: 0.2s;
  display: flex;
  align-items: center;
  gap: 4px;
  text-decoration: none;
}
  

Remove the Default Appearance

The browser provides default styling for many elements. We don't want the navigation items to look like default links, so we remove the underline and make the background transparent.


background: none;
border: none;
text-decoration: none;
  

Make Each Item Fill the Sidebar


width: 100%;
  

This makes each navigation item use the available width of the sidebar. This is important because the user should be able to click the navigation area, not just the text.

Add Space and Shape


padding: 8px;
border-radius: 8px;
  

padding gives the content room around it, while border-radius rounds the corners of the navigation item.

Arrange the Icon and Text

Each navigation item contains an icon and a text label. Flexbox lets us place them beside each other and align them properly.


display: flex;
align-items: center;
gap: 4px;
  

display: flex places the icon and text in a row. align-items: center keeps them vertically aligned, while gap creates space between them.

The Active Navigation Item

The current page needs to be distinguishable from the other navigation items. The Dashboard link already has the active class in the HTML.


.sidebar a.active {
  color: #fff;
  background: #222;
}
  

Because the selector targets both the sidebar and the active class, this style only affects the currently active navigation item.

Controlling the Navigation Area

The sidebar contains more than one group of navigation items. The .sidebarNav element controls each navigation area.


.sidebarNav {
  flex: 1;
  width: 100%;
  overflow: auto;
  padding-bottom: 10px;
  margin-bottom: auto;
  overflow-x: hidden;
}
  

The navigation can therefore grow with its contents while still being able to scroll when there is not enough vertical space.

Checkpoint: Step 3, The Sidebar

Compare your result with the screenshot below. The sidebar should now have a dark surface, properly spaced navigation items, aligned icons, and a visible active Dashboard item.

LogHue dashboard with the sidebar navigation styled and the Dashboard item active

Step 3, The Sidebar: navigation items are now styled, aligned, and spaced inside the sidebar.

Credit: Abdulroqib Oladipo

Experiment

Change the gap value. What happens when the icons move farther away from their labels?

Then change the padding and border-radius. Try to make the navigation items feel more compact or more spacious.

Review Questions

  1. Why do we use width: 100% on the navigation items?
  2. What does display: flex do here?
  3. What is the purpose of gap?
  4. Why does the Dashboard item have the active class?
  5. What does overflow: auto allow the navigation area to do?

Main Content

The sidebar now has its own structure and styling. Next, we need to style the main content area of the dashboard.

The HTML already gives us everything we need: a header, a dashboard greeting, statistics, a search area, and action buttons. We will style these parts one at a time.

Styling the Main Content Area

The .mainContent element contains everything to the right of the sidebar. First, give it a subtle separating border, some internal spacing, and scrolling behaviour.


.mainContent {
  border-left: 1px solid #333;
  padding: 0 8px 8px;
  overflow-y: auto;
  scroll-behavior: smooth;
}
  

The border-left creates a subtle visual separation between the sidebar and the main content.

The padding adds space inside the main content so that its children do not sit directly against its edges.

overflow-y: auto allows the content area to scroll vertically when necessary, while scroll-behavior: smooth makes that scrolling smoother.

Creating the Content Header

At the top of the main content is .contentHeader. It contains the sidebar menu button and the notification button.


.contentHeader {
  white-space: nowrap;
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: sticky;
  top: 0;
  z-index: 1;
  margin-bottom: 16px;
  padding: 4px 12px;
  overflow-x: auto;
}
  

display: flex places the header's children in a row. justify-content: space-between pushes them to opposite sides of the header.

align-items: center keeps them vertically aligned.

position: sticky allows the header to remain at the top when the content is scrolled. top: 0 defines that position.

The z-index gives the header a stacking level so it can stay above other content when necessary.

Styling the Header Controls


.menuBtn {
  font-size: 0.9rem;
  font-weight: 600;
  background: none;
  border: none;
  cursor: pointer;
  transition: opacity 0.2s ease;
}

.headerRight {
  display: flex;
  align-items: center;
  gap: 8px;
}

#notificationToggleBtn {
  position: relative;
}
  

The .menuBtn removes the browser's default button background and border. The cursor property makes it clear that the element is interactive.

.headerRight uses Flexbox to position its contents and gap adds space between them.

The notification button uses position: relative so that elements positioned inside it can use the button as their reference.

Styling the Dashboard Section

The .dashboard-section contains the main dashboard content. We want its children to flow vertically and remain centered.


.dashboard-section {
  border: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: transform 1s ease, opacity 0.5s ease;
  border-radius: 8px;
  padding: 4px;
  margin: 10px auto;
}
  

display: flex creates a flexible layout for the section. flex-direction: column makes its children flow from top to bottom.

align-items: center centers the children horizontally.

Styling the Dashboard Heading


.sectionHeader {
  margin-bottom: var(--space-md);
}

.dashboardHeader h1 {
  font-size: 1.875rem;
}
  

The margin-bottom creates space between the heading and the statistics below it.

The font-size makes the dashboard greeting larger so it has more visual importance.

Arranging the Statistics

The three statistic cards should sit together while still being able to wrap when the available space becomes smaller.


.dashboardStats {
  display: flex;
  gap: 8px;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  flex-wrap: wrap;
  justify-content: center;
}
  

display: flex places the cards in a flexible row. gap creates space between them, while justify-content: center centers the group.

flex-wrap: wrap allows the cards to move onto another line when there is not enough horizontal space.

The max-width prevents the statistics from stretching across the entire screen on large displays.

Now style each individual .statCard:


.statCard {
  background: #111;
  border: 1px solid #2c2f36;
  border-radius: 8px;
  padding: 8px 16px;
  font-size: 0.85rem;
  color: #d1d5db;
  display: flex;
  align-items: center;
  gap: 6px;
}
  

This gives each card its own dark surface, border, rounded corners, and internal spacing. Flexbox keeps the number and its label aligned.

Building the Search Area

The search area contains the search input followed by the quick-action buttons.


.searchBarContainer {
  width: 100%;
  max-width: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 16px;
  margin: 0 16px;
  position: relative;
}
  

flex-direction: column places the search field above the action buttons. The gap creates space between them.

Positioning the Search Icon


.searchInputWrapper {
  position: relative;
  width: 100%;
  max-width: 800px;
  margin: 24px auto 0;
}

.searchIcon {
  position: absolute;
  left: 12px;
  top: 18px;
}
  

The wrapper uses position: relative so the search icon can be positioned relative to it.

position: absolute removes the icon from the normal layout, allowing it to sit inside the search field area.

Styling the Search Input


.mainSearchInput {
  background-color: #1c1c1c;
  color: #ffffff;
  outline: none;
  border: 1px solid #2c2f36;
  font-size: 1rem;
  transition: 0.3s;
  resize: none;
  border-radius: 50px;
  width: 100%;
  height: 20px;
  margin: 0;
  max-width: none;
  padding: 16px;
  padding-right: 0;
  padding-left: 40px;
}
  

The dark background and border make the search field visible against the page background.

The large border-radius creates the rounded search-bar shape, while the left padding leaves room for the search icon.

Adding the Quick Actions


.quickActionsContainer {
  display: flex;
  justify-content: center;
  gap: 16px;
  margin-bottom: 24px;
  color: #fff;
}

.actionBtn {
  background: #222;
  border: 1px solid #333;
  width: 100%;
  padding: 8px;
  font-size: 0.756rem;
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  transition: 0.2s;
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
}

.quickActionsContainer .actionBtn {
  width: 170px;
  display: flex;
  justify-content: center;
  align-items: center;
}
  

The quick actions are centered with Flexbox and separated with gap.

.actionBtn is a reusable button style. The more specific .quickActionsContainer .actionBtn selector changes the dashboard action buttons to a fixed width of 170px.

Checkpoint: Step 4, Main Content

Your main content should now contain a structured header, centered dashboard greeting, statistic cards, search field, and quick-action buttons.

LogHue dashboard with the main content styled

Step 4, Main Content: the dashboard now has its main content structure, statistics, search area, and action buttons.

Credit: Abdulroqib Oladipo

Experiment

Change the max-width of the statistics and search areas. Observe how their size changes while the rest of the dashboard remains centered.

Then change the gap values in the Flexbox containers. See how the spacing between the dashboard elements changes.

Review Questions

  1. What does display: flex do in the dashboard section?
  2. Why does .dashboard-section use flex-direction: column?
  3. What does flex-wrap: wrap allow the statistic cards to do?
  4. Why is .searchInputWrapper positioned relatively?
  5. Why does the search icon use position: absolute?
  6. Why does .quickActionsContainer .actionBtn use a more specific selector?

Containers

The dashboard is made up of several containers. Containers help control how much space content can use and keep the page from becoming difficult to read on larger screens.

We already have containers in our HTML. Instead of creating a new .container class, we can style the containers that are already part of the dashboard.

Controlling the Dashboard Width

Start with the main dashboard section:


.dashboard-section {
  width: 100%;
  max-width: 1200px;
  margin: 10px auto;
  padding: 4px;
}
  

width: 100% allows the section to use the available space. However, on a very large screen, using all of that space could make the content unnecessarily wide.

max-width: 1200px sets a limit. The section can become smaller when there is less available space, but it will not grow beyond 1200px.

margin: 10px auto adds vertical spacing and centers the container horizontally when its width is limited.

Limiting Nested Containers

Containers can also be nested inside other containers. This lets us give different parts of the dashboard different width limits.


.dashboardStats {
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
}

.searchBarContainer {
  width: 100%;
  max-width: 1000px;
  margin: 0 auto;
}

.searchInputWrapper {
  width: 100%;
  max-width: 800px;
  margin: 24px auto 0;
}
  

Notice that each container can have its own max-width. The statistics and search input are narrower than the overall dashboard.

This creates a visual hierarchy: the dashboard can occupy a large area, while important content such as statistics and search remains at a comfortable reading width.

Understanding width and max-width

These two properties work together:

  • width: 100% says the container can use the available width.
  • max-width says how wide it is allowed to become.

For example:


.searchInputWrapper {
  width: 100%;
  max-width: 800px;
}
  

On a small screen, the wrapper can shrink to fit the available space. On a large screen, it stops growing once it reaches 800px.

Checkpoint: Step 5, Containers

Your dashboard should now have controlled content widths instead of allowing every section to stretch indefinitely across the screen.

LogHue dashboard with controlled content containers

Step 5, Containers: the dashboard uses width limits to keep its content organized and readable.

Credit: Abdulroqib Oladipo

Experiment

Change max-width: 800px on .dashboardStats to 500px. Observe how the statistics area changes.

Then remove max-width completely. Compare the result on a large screen.

Finally, change max-width: 1200px on .dashboard-section to a smaller value and observe how all of the dashboard content is affected.

Review Questions

  1. What is the difference between width and max-width?
  2. Why use width: 100% together with max-width?
  3. What does margin: 0 auto do when a container has a limited width?
  4. Why might the search input need a smaller max-width than the dashboard section?
  5. What happens when you remove the max-width from a container?

Spacing

Your page now has a layout and containers, but the elements still need room to breathe. Spacing controls the distance between elements and determines whether a page feels cramped or comfortable.

Padding vs. Margin

CSS gives you two main ways to create space: padding and margin.

  • Padding creates space inside an element, between its content and its border.
  • Margin creates space outside an element, separating it from other elements.

Adding Space Inside Elements

Start by giving the dashboard cards some internal space:

.statCard {
  padding: 8px 16px;
}

The first value controls the top and bottom padding, while the second controls the left and right padding.

Separating Elements

Use margin when you need to separate one element from another:

.dashboard-section {
  margin: 10px auto;
}

.searchInputWrapper {
  margin: 24px auto 0;
}

You can also control individual sides when an element needs more precise spacing:

.searchInputWrapper {
  margin-top: 24px;
}

Using Gap

When elements are arranged with Flexbox or Grid, gap is often the simplest way to control the space between them.

.dashboardStats {
  display: flex;
  gap: 8px;
}

.quickActionsContainer {
  display: flex;
  gap: 16px;
}

This keeps the spacing between items consistent without adding margins to each individual element.

Build the Spacing

Now adjust the spacing throughout the dashboard. Give the content room around its edges, add comfortable spacing between the statistics cards, and separate the search area from the other content.

Do not try to make everything evenly spaced. Different elements can need different amounts of space depending on their role.

Checkpoint: Step 6, Spacing

Your dashboard should now have comfortable spacing between its sections, controls, and content. Compare your result with the checkpoint below.

Dashboard after completing Step 6, Spacing

Step 6, Spacing: The dashboard now has consistent and comfortable spacing between its elements.

Credit: Abdulroqib Oladipo

Fonts

Text is one of the most important parts of a web page. CSS allows you to control which font is used, how large it appears, and how it is displayed.

You have already used a font in the dashboard:

body {
  font-family: Arial, Helvetica, sans-serif;
}

The font-family property tells the browser which font to use. The browser tries the fonts from left to right and uses the first available one.

Font Size

Use font-size to control how large text appears.

.dashboardHeader h1 {
  font-size: 1.875rem;
}

.statCard {
  font-size: 0.85rem;
}

Font Weight

font-weight controls how thick the text appears.

.dashboardHeader h1 {
  font-weight: 700;
}

.menuBtn {
  font-weight: 600;
}

Common values include 400 for normal text, 500 for medium text, 600 for semi-bold, and 700 for bold.

Changing the Font

You can use another font by changing the font-family value.

body {
  font-family: Georgia, serif;
}

You can also use a custom web font by loading it with @font-face or importing it from a font provider.

Reference

For a refresher on how the dashboard's font was introduced, return to Your First CSS.

Headings

Headings help organize your content and make it easier to understand. HTML provides six heading levels, from h1 to h6.

CSS lets you control how each heading looks without changing its meaning.

Styling a Heading

You can target a specific heading and change its size, weight, spacing, or other visual properties.

h1 {
  font-size: 2rem;
  font-weight: 700;
}

You can also target a heading based on the component it belongs to. This is useful when different parts of your page need different heading styles.

.dashboardHeader h1 {
  font-size: 1.875rem;
}

Choose the Right Heading

Use headings according to the structure of your content, not simply because you want text to look bigger or smaller. CSS should control the appearance while HTML controls the document structure.

Reference

You already styled the dashboard's main heading earlier in Main Content.

Line Height

The line-height property controls the amount of vertical space between lines of text. Increasing it can make paragraphs easier to read, while a smaller value can make text feel more compact.

Setting Line Height

You can use a number, length, or percentage. A unitless number is often useful because it scales with the element's font size.

p {
  line-height: 1.6;
}

For example, a value of 1.6 means the line height is 1.6 times the element's font size.

Different Elements, Different Spacing

Headings usually need tighter line spacing, while paragraphs can benefit from more space between lines.

h1 {
  line-height: 1.2;
}

p {
  line-height: 1.6;
}

Reference

The heading used in the dashboard was styled earlier in Main Content.

Text Hierarchy

Not all text on a page should look equally important. Text hierarchy helps users quickly understand what is important, what supports it, and what is secondary information.

You can create hierarchy by changing properties such as font-size, font-weight, and line-height.

Creating Hierarchy

A large, bold heading can draw attention to the main idea, while smaller and lighter text can provide supporting information.

.dashboardHeader h1 {
  font-size: 1.875rem;
  font-weight: 700;
}

.statCard {
  font-size: 0.85rem;
  color: #d1d5db;
}

Keep It Consistent

Similar types of content should generally use similar styles. This makes the interface easier to scan and prevents every piece of text from competing for attention.

Reference

The dashboard heading was styled earlier in Main Content, while the text inside the statistic cards was styled in the same section.

Display

The display property controls how an element behaves in the layout. It is one of the most important CSS properties for arranging elements on a page.

Block Elements

A block element starts on a new line and normally takes up the available width.

.dashboard-section {
  display: block;
}

Inline Elements

An inline element stays within the same line as surrounding content.

span {
  display: inline;
}

Flex

Setting display: flex turns an element into a flex container. Its children can then be arranged and aligned using Flexbox properties.

.quickActionsContainer {
  display: flex;
  justify-content: center;
  gap: 16px;
}

Grid

Setting display: grid creates a grid layout. Grid is useful when you want to organize content into columns and rows.

.main {
  display: grid;
  grid-template-columns: 260px 1fr;
}

Choosing a Display Type

Use the display type that matches the layout you are trying to create. Block and inline are useful for normal document flow, while Flexbox and Grid give you more control over arranging elements.

Reference

The dashboard's main layout already uses Grid. You can see how it was introduced in Page Layout.

Flexbox

Flexbox is a CSS layout system designed to arrange elements in a row or column. It makes it easier to control the direction, alignment, spacing, and size of elements inside a container.

Creating a Flex Container

Start by setting display: flex on the parent element.

.quickActionsContainer {
  display: flex;
}

Direction

By default, Flexbox places items in a row. You can change this with flex-direction.

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

Aligning Items

justify-content controls how items are distributed along the main axis, while align-items controls their alignment across the other axis.

.container {
  display: flex;
  justify-content: center;
  align-items: center;
}

Spacing Between Items

Use gap to create consistent space between flex items.

.container {
  display: flex;
  gap: 16px;
}

Reference

Flexbox is already used throughout the dashboard. For example, .quickActionsContainer uses Flexbox to arrange the action buttons, while .headerRight uses it to align the controls in the header.

.quickActionsContainer {
  display: flex;
  justify-content: center;
  gap: 16px;
}

.headerRight {
  display: flex;
  align-items: center;
  gap: 8px;
}

You can also see Flexbox being used in the sidebar links in The Sidebar.

Grid

CSS Grid is a layout system designed for arranging elements in rows and columns. It is especially useful when you need control over the overall structure of a page.

Creating a Grid

Start by setting display: grid on the parent element.

.container {
  display: grid;
}

Creating Columns

Use grid-template-columns to define the columns in your grid.

.container {
  display: grid;
  grid-template-columns: 200px 1fr;
}

The 1fr unit means that the column takes a share of the available space.

Creating Rows

You can also define the size of rows with grid-template-rows.

.container {
  display: grid;
  grid-template-rows: 80px 1fr;
}

Spacing

Use gap to create space between grid items.

.container {
  display: grid;
  gap: 16px;
}

Reference

The dashboard uses Grid for its main page structure. The .main element creates a 260px sidebar column and gives the remaining space to the main content.

.main {
  display: grid;
  grid-template-columns: 260px 1fr;
  min-height: 100vh;
}

You can see where this layout was introduced in Page Layout.

Positioning

The position property controls how an element is positioned in relation to the page or another element.

Relative Positioning

position: relative keeps an element in the normal document flow while allowing you to move it using properties such as top, right, bottom, and left.

.element {
  position: relative;
  top: 10px;
}

Absolute Positioning

position: absolute removes an element from the normal flow and positions it relative to its nearest positioned ancestor.

.container {
  position: relative;
}

.element {
  position: absolute;
  top: 0;
  right: 0;
}

Fixed Positioning

position: fixed positions an element relative to the viewport. It stays in place when the page is scrolled.

.sidebar {
  position: fixed;
  top: 0;
  left: 0;
}

Sticky Positioning

position: sticky behaves like a normally positioned element until it reaches a specified position while scrolling.

.contentHeader {
  position: sticky;
  top: 0;
}

Reference

The dashboard already uses positioning for its header and search icon. You can see these examples in Main Content.

Cards

Cards are commonly used to group related information into separate visual containers. They can make dashboards easier to scan by giving each piece of information its own space.

The dashboard already uses cards for its statistics. Each statistic is placed inside an element with the statCard class.

Creating a Card

A simple card can be created by giving it a background, border, padding, and rounded corners.

.statCard {
  background: #111;
  border: 1px solid #2c2f36;
  border-radius: 8px;
  padding: 8px 16px;
}

Adding Spacing

Cards often contain multiple elements, so use spacing to keep their content readable and organized.

.card {
  padding: 16px;
  gap: 8px;
}

Reference

The dashboard's statistics cards were styled earlier in Main Content.

.statCard {
  background: #111;
  border: 1px solid #2c2f36;
  border-radius: 8px;
  padding: 8px 16px;
  font-size: 0.85rem;
  color: #d1d5db;
  display: flex;
  align-items: center;
  gap: 6px;
}

Buttons

Buttons allow users to perform actions. CSS can control their appearance, size, spacing, borders, colors, and interaction states.

Styling a Button

A basic button can be styled with a background, border, padding, text color, and rounded corners.

.actionBtn {
  background: #222;
  border: 1px solid #333;
  padding: 8px;
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
}

Aligning Button Content

Flexbox can be used to control the position of icons and text inside a button.

.actionBtn {
  display: flex;
  align-items: center;
  gap: 4px;
}

Button States

You can change a button's appearance when the user interacts with it. For example, :hover applies styles when the pointer is over the button.

.actionBtn:hover {
  background: #fff;
  color: #000;
}

The :active pseudo-class can be used while the button is being pressed.

button:active {
  transform: scale(0.95);
}

Reference

The dashboard's buttons were styled earlier in Main Content.

.actionBtn {
  background: #222;
  border: 1px solid #333;
  width: 100%;
  padding: 8px;
  font-size: 0.756rem;
  border-radius: 8px;
  color: #fff;
  cursor: pointer;
  transition: 0.2s;
  display: flex;
  align-items: center;
  gap: 4px;
  font-weight: 600;
}

Inputs

Inputs allow users to enter information. CSS can control their size, spacing, borders, colors, and appearance when they are focused.

Styling an Input

You can use properties such as background-color, color, border, padding, and border-radius to style an input.

.mainSearchInput {
  background-color: #1c1c1c;
  color: #fff;
  border: 1px solid #2c2f36;
  border-radius: 50px;
  padding: 16px;
}

Controlling the Size

Width and height can be used to control how much space the input takes.

.mainSearchInput {
  width: 100%;
  height: 20px;
}

Removing the Default Outline

Browsers usually add an outline when an input receives focus. You can remove it with outline: none and create your own focus style instead.

.mainSearchInput {
  outline: none;
}

Positioning Content Inside an Input

When an input has an icon beside it, the input can have extra left padding so the text does not overlap the icon.

.mainSearchInput {
  padding-left: 40px;
}

.searchInputWrapper {
  position: relative;
}

Reference

The dashboard's search input was styled earlier in Main Content.

.mainSearchInput {
  background-color: #1c1c1c;
  color: #ffffff;
  outline: none;
  border: 1px solid #2c2f36;
  font-size: 1rem;
  transition: 0.3s;
  resize: none;
  border-radius: 50px;
  width: 100%;
  height: 20px;
  margin: 0;
  max-width: none;
  padding: 16px;
  padding-right: 0;
  padding-left: 40px;
}

States

Interactive elements can look different depending on what the user is doing with them. These different appearances are called states.

CSS pseudo-classes allow you to style an element when it is being hovered, focused, pressed, or otherwise interacted with.

Hover

The :hover pseudo-class applies styles when the user's pointer is over an element.

.actionBtn:hover {
  background: #fff;
  color: #000;
}

Focus

The :focus pseudo-class applies styles when an element has keyboard or input focus.

.mainSearchInput:focus {
  border-color: #555;
}

Active

The :active pseudo-class applies while an element is being pressed.

button:active {
  transform: scale(0.95);
}

Disabled

You can also style elements that have been disabled using the :disabled pseudo-class.

button:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

Reference

The dashboard already uses interactive states for its action buttons. The hover and active styles were introduced in Buttons.

Dashboard showing interactive button states

Step 7, States: Interactive elements respond visually to user actions.

This image was AI generated and might not be accurate.

Credit: AI generated illustration

Responsive Thinking

A web page can be viewed on many different screen sizes. A layout that looks good on a large desktop screen may not work well on a phone. Responsive design means creating layouts that adapt to the available space.

Think About the Available Space

Before writing responsive CSS, look at how your elements behave when the available space becomes smaller. Ask yourself what should shrink, what should wrap, and what may need to move to another position.

Flexible vs. Fixed Sizes

Fixed sizes can be useful when an element needs a specific size, but relying on them everywhere can make a layout difficult to use on smaller screens.

.sidebar {
  width: 260px;
}

.mainContent {
  width: 100%;
}

Flexible units such as percentages, fr, and max-width allow elements to make better use of the available space.

.searchInputWrapper {
  width: 100%;
  max-width: 800px;
}

Let Content Adapt

Flexbox and Grid can help content adapt naturally as the available space changes.

.dashboardStats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

Here, flex-wrap allows the cards to move onto another line when there is no longer enough horizontal space.

Reference

The dashboard already uses flexible sizing and wrapping in Containers and Flexbox.

Media Queries

Media queries allow you to apply different CSS rules depending on the characteristics of the device or viewport. They are commonly used to adapt a layout for smaller screens.

Changing the Layout on Mobile

Our dashboard uses a two-column Grid layout on larger screens. On a smaller screen, the sidebar takes up too much space, so we can change the Grid to a single column and hide the sidebar.

@media (max-width: 768px) {
  .main {
    grid-template-columns: 1fr;
  }

  .sidebar {
    display: none;
  }
}

The @media rule tells the browser to apply these styles only when the viewport is 768 pixels wide or smaller.

What Happens to the Sidebar?

The sidebar is hidden on mobile because there is not enough horizontal space for both the sidebar and the main content.

However, hiding the sidebar also hides its navigation links. Making the navigation accessible through a mobile menu would require JavaScript to open and close the sidebar.

JavaScript is not covered in this CSS documentation, so we will only handle the responsive layout with CSS.

Checkpoint: Mobile Layout

Resize the page to a mobile-sized viewport and compare your result with the checkpoint below. The sidebar should be hidden and the main content should use the available width.

Dashboard adapted to a mobile layout with the sidebar hidden

Mobile Layout: The sidebar is hidden and the main content expands to use the available screen width.

Credit: Abdulroqib Oladipo

Reference

The original two-column Grid layout was created in Page Layout.

Mobile Layouts

A responsive layout should not only fit on a smaller screen. Its elements should also remain readable and usable when the available space changes.

Changing the Grid

On larger screens, the dashboard uses two Grid columns: one for the sidebar and one for the main content. On mobile, the layout changes to a single column.

@media (max-width: 768px) {
  .main {
    grid-template-columns: 1fr;
  }

  .sidebar {
    display: none;
  }
}

Making Content Fit

Elements that have a fixed width on larger screens may need to become flexible on smaller screens. Using width: 100%, max-width, wrapping, and flexible Grid or Flexbox layouts can help content fit the available space.

.searchInputWrapper {
  width: 100%;
  max-width: 800px;
}

.dashboardStats {
  display: flex;
  flex-wrap: wrap;
}

Mobile Navigation

In our example, the sidebar is hidden on mobile. A real application would normally provide another way to access those navigation links, such as a mobile menu.

Creating an interactive mobile menu requires JavaScript to open and close the navigation. JavaScript is outside the scope of this CSS documentation, so we will only handle the layout change with CSS.

Reference

The mobile Grid change was introduced in Media Queries.

Responsive Components

Responsive design is not only about changing the overall page layout. Individual components also need to remain usable when the available space changes.

Components Should Adapt

A component should be able to use the space available to it instead of assuming that the screen will always have the same width.

.searchInputWrapper {
  width: 100%;
  max-width: 800px;
}

This allows the search area to shrink when the screen becomes smaller while preventing it from becoming unnecessarily wide on larger screens.

Let Items Wrap

Components containing multiple items can also adapt by allowing those items to move onto another line when there is not enough space.

.dashboardStats {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

Combining Responsive Techniques

Responsive components often use several CSS techniques together. In this dashboard, flexible widths and wrapping are used alongside the media query that changes the main Grid layout on smaller screens.

The media query controls the major layout change, while the components themselves use flexible sizing and wrapping to adapt within that layout.

Reference

The main responsive layout is covered in Media Queries, and the behavior of the dashboard on smaller screens is explained in Mobile Layouts.

Colors

Color affects how a website feels and helps users understand what is important. A good color system should be consistent rather than using a different color for every element.

Scybud's Dark Foundation

Pure black is a signature of Scybud-developed interfaces. Using #000 as the main background creates a strong, minimal foundation that keeps the interface focused on the content and gives Scybud products a recognizable visual identity.

html,
body {
  background: #000;
  color: #f5f5f5;
}

From there, slightly lighter shades can be used to separate elements without breaking the dark visual system.

.sidebar {
  background: #111;
}

.statCard {
  background: #111;
}

.actionBtn {
  background: #222;
}

Text Colors

Text does not always need to be pure white. Using softer shades for secondary content creates a visual hierarchy while keeping the interface readable.

body {
  color: #f5f5f5;
}

.statCard {
  color: #d1d5db;
}

Accent Colors

Accent colors can be used to draw attention to important states or elements without overwhelming the interface.

.sidebar a.active {
  color: #afccff;
  background: #222;
}

Reference

The main dark color foundation was introduced in Your First CSS. The sidebar and component colors were then introduced throughout The Sidebar and Main Content.

Borders

Borders can separate elements, define their boundaries, and add structure to an interface. They can also be used subtly so that elements are separated without feeling visually heavy.

Adding a Border

The border property lets you define the width, style, and color of a border.

.statCard {
  border: 1px solid #2c2f36;
}

Rounded Borders

Use border-radius to round the corners of an element.

.statCard {
  border-radius: 8px;
}

Using Subtle Borders

In a dark interface, a bright border can become distracting. Using a darker shade creates separation while keeping the interface calm.

.sidebar {
  border-right: 1px solid #2a2a2a;
}

.mainContent {
  border-left: 1px solid #333;
}

Reference

Borders were introduced earlier when building the Sidebar and Main Content.

Shadows

The box-shadow property can create depth by making an element appear to sit above or below other elements. Shadows are commonly used around cards, buttons, menus, and other components.

Creating a Shadow

A basic shadow can be created by defining its horizontal offset, vertical offset, blur, and color.

.card {
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

Shadows on Dark Backgrounds

Shadows do not always make an element appear more separated. On a pure black background, a typical dark shadow has very little visible effect because there is already almost no darker color to display.

A lighter or gray shadow can create a visible glow-like effect, but that changes the visual character of the component. For this reason, shadows were intentionally not used in the dashboard. The dashboard instead relies on backgrounds, borders, and spacing to separate its elements.

Shadows in ScyLearn

Shadows are still useful when the design calls for them. For example, shadows are used on the ScyLearn website's home page to create depth and visual separation.

Reference

Compare the use of shadows on the Colors and Borders sections with the dashboard. The dashboard uses borders and different background shades instead of shadows to create separation.

Transitions

Transitions make changes between CSS states happen smoothly instead of changing instantly. They are especially useful for interactive elements such as buttons and navigation links.

Adding a Transition

The transition property tells the browser which changes should happen gradually and how long they should take.

.actionBtn {
  transition: 0.2s;
}

Now, when another state changes a property such as the background or text color, the change happens over 0.2 seconds.

Combining Transitions with States

Transitions are commonly used together with pseudo-classes such as :hover.

.actionBtn {
  background: #222;
  color: #fff;
  transition: 0.2s;
}

.actionBtn:hover {
  background: #fff;
  color: #000;
}

Without the transition, the colors would change immediately when the pointer moves over the button.

Reference

The dashboard already uses transitions on its buttons and other interactive elements. You can see these examples in Buttons and States.

.actionBtn {
  transition: 0.2s;
}

button:active {
  transform: scale(0.95);
}

Hover and Focus

Hover and focus deserve a closer look on their own, even though :hover and :focus were already introduced in States. Together they tell two different kinds of users what is interactive: a mouse user sees hover, a keyboard user sees focus.

Hover Is for Pointer Users Only

:hover only fires for someone using a mouse or trackpad. Someone navigating with a keyboard, a screen reader, or a touchscreen never triggers it. If a hover style is the only way an interactive element communicates its state, keyboard and touch users miss that information entirely.

Focus Is for Keyboard Users

:focus fires when an element receives keyboard focus, usually by tabbing to it. Every interactive element should have a visible focus style, not just a hover style.

.actionBtn:hover,
.actionBtn:focus-visible {
  background: #fff;
  color: #000;
}

:focus-visible applies a focus style only when the browser thinks it is relevant, such as during keyboard navigation, rather than every time an element is clicked.

Reference

The dashboard's hover and active button styles were introduced in Buttons, and the full set of interactive states is covered in States.

Selectors

A selector is how a CSS rule chooses which elements to style. Everything you have written so far, from body to .sidebar a.active, is a selector.

Type Selectors

A type selector targets every element of a given tag.

h1 {
  font-weight: 700;
}

Class Selectors

A class selector, written with a leading dot, targets any element carrying that class. Most of the dashboard's styling uses class selectors.

.statCard {
  background: #111;
}

ID Selectors

An ID selector, written with a leading #, targets a single element with that ID.

#notificationToggleBtn {
  position: relative;
}

Combining Selectors

Selectors can be combined to target an element based on where it sits in the document. A descendant selector, written as two selectors separated by a space, targets an element nested inside another.

.sidebar a {
  color: #f5f7fa;
}

This only targets <a> elements inside .sidebar, not every link on the page.

Reference

You have already used type, class, and descendant selectors throughout this documentation, including in The Sidebar.

Specificity

When more than one rule targets the same element, specificity is part of how the browser decides which one wins. It was first introduced in The Cascade; this section looks at it more closely.

Roughly, From Weakest to Strongest

  • Type selectors, such as h1 or a.
  • Class selectors, such as .statCard, and attribute or pseudo-class selectors.
  • ID selectors, such as #notificationToggleBtn.

A selector built from more of these, or from stronger ones, beats a selector built from fewer or weaker ones, regardless of the order the rules appear in the stylesheet.

.sidebar a {
  color: #f5f7fa;
}

.sidebar a.active {
  color: #fff;
}

.sidebar a.active combines two classes with a type selector, so it is more specific than .sidebar a and wins for the active link even if it were written first.

Keep Specificity Low When You Can

Selectors that are more specific than they need to be make a stylesheet harder to override later. Reaching for an ID selector or stacking several classes together should usually be a deliberate choice, not a default habit.

Reference

The cascading behaviour behind specificity was introduced in The Cascade.

Variables

CSS variables allow you to store values that can be reused throughout your stylesheet. They are useful when the same colors, spacing values, or other properties are used in multiple places.

Creating a Variable

CSS variables are usually defined inside :root so they can be accessed throughout the page.

:root {
  --background: #000;
  --surface: #111;
  --border: #2c2f36;
}

Using a Variable

Use the var() function to use a variable.

body {
  background: var(--background);
}

.statCard {
  background: var(--surface);
  border: 1px solid var(--border);
}

Why Use Variables?

Variables make it easier to keep a design consistent and change values later. Instead of finding every occurrence of a color and changing it individually, you can change the variable once.

:root {
  --surface: #111;
}

Every element using var(--surface) will then use the updated value.

Reference

The dashboard uses repeated values for its dark backgrounds, borders, spacing, and text colors. These are good candidates for CSS variables when developing a larger project.

For the spacing values already used in the project, see Spacing.

Variables in Scybud UI

Scybud UI uses CSS variables to define shared design values such as colors, spacing, typography, and other interface properties. This makes it possible for Scybud-developed products to share a similar visual language without every project having to define the same values from scratch.

:root {
  --color-background: #000;
  --color-surface: #111;
  --color-border: #2c2f36;
}

When Scybud-developed interfaces use the same variables and design values, different products can have their own layouts and components while still feeling like they belong to the same ecosystem. This makes development faster and keeps the design consistent projects.

This is one of the ideas behind Scybud UI: creating reusable design foundations that can be shared across Scybud projects.

Reusable Styles

As your CSS grows, you will often find yourself styling the same type of element more than once. Instead of writing the same CSS repeatedly, you can create reusable styles and apply them wherever they are needed.

Why Reuse Styles?

Reusable styles make your CSS easier to maintain and help keep your interface consistent. If several elements should look the same, they can share the same class instead of each having its own separate rules.

For example, the dashboard uses the .actionBtn class for buttons that share the same basic appearance:


 .actionBtn {
    background: #222;
    border: 1px solid #333; 
    width: 100%; 
    padding: 8px; 
    font-size: 0.756rem; 
    border-radius: 8px; 
    color: #fff; 
    cursor: pointer; 
    transition: 0.2s; 
    display: flex; 
    align-items: center; 
    gap: 4px; 
    font-weight: 600; 
  }

Any button with the actionBtn class can use these styles:


<button class="actionBtn">Create Workspace</button> 
<button class="actionBtn">Add Task</button>

Both buttons can share the same foundation while still having their own content or additional classes when needed.

Combining Reusable Styles

A reusable class does not mean every element must look exactly the same. You can combine a shared class with a more specific class to change only what is different.


      <button class="actionBtn notificationBtn"> Notifications </button>
          

The actionBtn class provides the shared button styling, while notificationBtn can add styles specific to the notification button.

You can also use a more specific selector when several elements share a class but need a different layout in one particular area. The dashboard uses this approach for its quick actions:

.quickActionsContainer .actionBtn { 
              width: 170px; 
              display: flex; 
              justify-content: center; 
              align-items: center; 
            }

The buttons keep the reusable .actionBtn foundation while the quick-action container changes how those buttons behave in that section.

Reusable Styles Across Scybud

Reusable styles become even more useful when building multiple products. Shared classes, variables, and design values can create a consistent foundation across Scybud-developed interfaces while allowing each product to have its own components and layout.

Again, Scybud UI reuses this idea: reusable design foundations can be shared instead of recreated for every project.

Organizing CSS

As a project grows, having reusable styles is useful, but you also need a clear way to organize those styles. Well-organized CSS makes it easier to find, understand, and update the rules you have already written.

Group Related Styles

Keep styles that belong to the same part of the interface together. For example, sidebar styles can be kept together instead of being scattered throughout the stylesheet.

.sidebar { 
   background: #111; 
   border-right: 1px solid #2a2a2a; 
   padding: 20px 8px; 
   } 

.sidebar a {
   background: none; 
   border: none; 
   width: 100%; 
   padding: 8px; 
   border-radius: 8px; 
  } 
.sidebar a.active { 
  color: #afccff; 
  background: #222; 
}

This makes it easier to understand how the sidebar itself, its links, and its active state are connected.

Keep a Clear Order

A stylesheet can become difficult to work with when rules are placed randomly. A useful approach is to move through the interface in a logical order: start with the page foundation, then layout, components, states, and responsive rules.

For example, the dashboard CSS can move from the main page layout to the sidebar, main content, dashboard sections, cards, search, and buttons. Related rules stay close together so you can find them quickly when making changes.

Organizing Larger Projects

As a project becomes larger, you can separate your CSS into different files based on their purpose. For example:

css/ 
  base.css 
  layout.css 
  components.css 
  responsive.css

The exact structure can change depending on the project. The important part is that you can quickly identify where a particular style belongs.

Good CSS organization is not about following one perfect structure. It is about making your stylesheet predictable, reusable, and easy to maintain as the project grows.

Choose Your Project

Every lesson so far has taught you one piece of CSS at a time. The Real Project is where those pieces come together. You will pick one page from a real Scybud product and rebuild it yourself, using only HTML and CSS.

This is not a copy exercise. You are not being asked to match the original page pixel for pixel. You are being asked to look at a real interface, understand what it needs to do, and make your own layout, spacing, and styling decisions to get there. Two students working from the same brief should end up with two different pages.

You will build one page, not the whole product.

Pick one of the three pages below to work from.

Screenshot placeholder of the CanvArt Collections page showing artwork grouped into collection cards

Screenshot: CanvArt, Abdulroqib Oladipo

CanvArt

Collections

Browse artwork collections, with image cards, a heading structure, and navigation that holds up on a phone.

Difficulty: Intermediate

View project brief Open live page
Screenshot placeholder of the ZeFeed Tech History page showing a sidebar, a featured history entry, and supporting entries

Screenshot: ZeFeed, Abdulroqib Oladipo

ZeFeed

Tech History

Rebuild a page that surfaces one featured history entry alongside a promotional products card, with a clear reading hierarchy.

Difficulty: Intermediate

View project brief Open live page
Screenshot placeholder of the ZeFeed Explore Tech page showing a grid of article cards with images and metadata

Screenshot: ZeFeed, Abdulroqib Oladipo

ZeFeed

Explore Tech

Design a scannable grid of tech articles, each with an image, a title, a description, and metadata like source and date.

Difficulty: Intermediate

View project brief Open live page

Before you start building

Open the real product and spend a few minutes with the actual page you picked. Scroll it, resize your browser window, notice what stays put and what moves. You are not studying it to copy it. You are studying it to understand what the page is for and what it needs to communicate. Your version can look completely different and still succeed at the same job.

Project Briefs

CanvArt, Collections

CanvArt is a dark mode art sharing platform. The Collections page groups artwork into named collections that a visitor can browse. Your job is to design a page that presents these collections clearly and invites someone to look closer.

What you're building

A page that displays a set of collections, each represented by artwork. It should include some form of navigation, a heading structure that makes the page easy to scan, and a layout that adapts from a wide screen down to a phone.

Requirements

  • The page must include a navigation element, even if it only links to a couple of other pages.
  • Collections must be presented as image based cards.
  • The card layout must be responsive: it should reflow sensibly at a smaller viewport width, not just shrink.
  • Each card needs at least one heading and enough supporting text to explain what the collection is.
  • At least one button or link must have a distinct hover and focus state.
  • Spacing between cards, between sections, and around text should feel deliberate, not accidental.
  • The page should read comfortably on both a small and a large screen without horizontal scrolling.

ZeFeed, Tech History

ZeFeed's Tech History page surfaces facts and moments from the history of technology. One entry is featured, and others are browsable by clicking the next or previous buttons plus, it contains a promotional panel that showcase some products. Your job is to design a page that makes one piece of content feel primary while keeping the rest easy to reach.

What you're building

A page with a sidebar area for browsing, a large featured entry that reads as the main content, and additional secondary content nearby. The featured entry should look and feel more important than the rest, through your layout and typography choices, not just a label that says so.

Requirements

  • The page must contain a sidebar or comparable secondary navigation area, separate from the main content.
  • One entry must be presented as a large, featured card that is clearly the visual focus of the page.
  • The page must use a heading hierarchy that reflects the actual structure of the content.
  • The layout must adapt for smaller screens. A sidebar sitting beside content on desktop should not stay side by side on a phone if it hurts readability.
  • Text content should have a clear reading order and comfortable line lengths.

ZeFeed, Explore Tech

ZeFeed's Explore Tech page is a feed of tech articles someone can browse before deciding what to read in full. Your job is to design a grid of articles that is easy to scan and pleasant to browse.

What you're building

A responsive grid of article cards. Each card should include an image, a title, a short description, and metadata such as a source or a date. The grid should hold up whether there are three articles on screen or thirty.

Requirements

  • Articles must be presented in a responsive grid, with the number of columns adjusting to the available width.
  • Every card needs an image, a title, a short description, and at least one piece of metadata.
  • Metadata should be visually distinct from the title and description, not just smaller text in the same style.
  • Cards need to stay readable and well spaced at both narrow and wide viewport widths.
  • Card titles or images should have a hover or focus state, since these are meant to be clickable in a real product.
  • Long titles or descriptions should not break the card's layout.

Make It Your Own

The requirements describe what the page needs to do. They do not tell you which CSS properties to use. Whether you choose Grid or Flexbox for the layout, how you handle breakpoints, what your spacing scale looks like, or how the page ultimately looks are all your decisions. Two students can meet every requirement above and produce pages that look completely different. That's the point.

Not every property or concept you'll need was covered in this lesson. Some things you'll have to discover on your own and that's part of being a developer. When you get stuck or need to learn how something works, you have a tool to help you. ScySearch is a developer-focused search engine that brings together development resources and a selection of verified, indexed domains to help you find the information you need.

Final Checklist

  • I explored the real page and understand what it's for, not just what it looks like.
  • My page meets every requirement in the brief I chose.
  • My layout adapts cleanly from a wide screen down to a phone width, with no horizontal scrolling or broken content.
  • My headings reflect the actual structure of the page, not just visual size.
  • Interactive elements have states for hover and focus, not just a default look.
  • My spacing is consistent across similar elements, not tweaked case by case.
  • The page still looks and works fine if I resize the browser slowly, not just at one or two fixed widths.

Conclusion

You started this documentation with a plain, unstyled HTML file. Since then, you have given it a layout, a color system, typography, spacing, components, and responsive behaviour, and then applied all of that again on a page you chose yourself.

What you've learned

  • How the cascade and specificity decide which CSS rule applies.
  • How to structure a page with Grid and Flexbox, and when to reach for each.
  • How to build components, cards, buttons, inputs, and navigation, that hold up on their own.
  • How to give interactive elements clear hover, focus, and active states.
  • How to make a layout and its components respond to different screen sizes.
  • How to keep a growing stylesheet organized with variables, reusable classes, and a predictable structure.

Where to go from here

The fastest way to keep improving is the same way you learned CSS in this documentation: find a real interface, and build it. Revisit your Real Project page in a few weeks and see what you would do differently now. Look at interfaces you use every day and ask what layout system, spacing, or states they're relying on.

If you want one more challenge before you go, the Design Challenge that follows this section is open ended and does not come with a reference design.

Design Challenge

You have been asked to build the dashboard for a productivity app. The page should help users quickly see what they need to work on, review their progress, and navigate between different parts of the application.

LogHue dashboard design draft

Visual reference to guide you

AI Generated

Design Instructions

  • Create a dark-themed dashboard with a sidebar for navigation and a main content area for the user's tasks.
  • The main area should include a page heading, a short description, task statistics, and a list of upcoming tasks.
  • Tasks should clearly communicate their title, status, priority, and due date.
  • Use different visual treatments to distinguish completed, pending, and overdue tasks.
  • The sidebar should remain easy to navigate and clearly indicate the currently selected section.
  • The layout must adapt to smaller screens without making the content difficult to use or read.
  • Maintain a consistent visual system for spacing, typography, borders, buttons, and interactive elements throughout the page.

Starter HTML


<main class="dashboard">

  <aside class="sidebar">
    <div class="logo">Taskly</div>

    <nav>
      <a href="#" class="active">Tasks</a>
      <a href="#">Calendar</a>
      <a href="#">Projects</a>
      <a href="#">Settings</a>
    </nav>
  </aside>

  <section class="content">
    <header class="page-header">
      <div>
        <h1>My Tasks</h1>
        <p>Keep track of what needs to get done.</p>
      </div>

      <button>+ New Task</button>
    </header>

    <section class="stats">
      <div class="stat-card">
        <span>Total Tasks</span>
        <strong>24</strong>
      </div>

      <div class="stat-card">
        <span>Completed</span>
        <strong>16</strong>
      </div>

      <div class="stat-card">
        <span>In Progress</span>
        <strong>5</strong>
      </div>

      <div class="stat-card">
        <span>Overdue</span>
        <strong>3</strong>
      </div>
    </section>

    <section class="tasks">
      <div class="section-header">
        <h2>Upcoming Tasks</h2>
        <button>View all</button>
      </div>

      <article class="task">
        <div>
          <h3>Finish landing page</h3>
          <p>Due today · High priority</p>
        </div>
        <span class="status">In Progress</span>
      </article>

      <article class="task">
        <div>
          <h3>Review project requirements</h3>
          <p>Due tomorrow · Medium priority</p>
        </div>
        <span class="status">Pending</span>
      </article>

      <article class="task completed">
        <div>
          <h3>Set up development environment</h3>
          <p>Completed yesterday</p>
        </div>
        <span class="status">Completed</span>
      </article>
    </section>
  </section>

</main>
    

Submit Your Work

Once you've finished the challenge, you're welcome to share your work with us. You don't need to create a perfect or production-ready website. We want to see how you interpreted the requirements and the design decisions you made along the way.

Include

  • Your name
  • Your email address
  • A link to your repository
  • A link to your live demo, if you have one
  • A short explanation of what you changed and any design decisions you'd like to highlight

A live demo is optional. If you don't have one, submitting your repository is completely fine. You can also send your submission or any questions about the challenge to student@scybud.com.

By submitting your work, you understand that Scybud may consider selected designs or ideas for potential use in future Scybud products or educational materials. You retain ownership of your work.

If your design is ever used in a Scybud product, Scybud will provide permanent credit to you as the original contributor. Even if the design is later replaced or removed, your contribution will remain recorded in Scybud's contributor history.