Fonts And Styling

Section overview

In this lesson, we will style our running tracker app to make it more visually appealing and user-friendly using CSS. We'll add a custom Google Font, create a dark theme with modern colors, and style all the interface elements for a professional look.

paint splash image

CSS stands for Cascading Style Sheets, and is used for styling your web pages by controlling the look and feel of the elements. Including fonts, spacing, layout, colors, animations, responsive design, and much more.

Setting up the CSS file

First, create a new file called styles.css alongside the index.html inside your project folder:

running-tracker/
├── index.html
├── styles.css

Adding Google fonts

Begin by linking to a custom Google Font in the HTML. Update the <head> section of your HTML to include the font:

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <link
    href="https://fonts.googleapis.com/css2?family=MuseoModerno:wght@300;400;600&display=swap"
    rel="stylesheet"
  />
  <link rel="stylesheet" href="styles.css" />
  <title>Running tracker</title>
</head>
  • The <link> element with rel="stylesheet" links to a stylesheet, in this case it links to the Google Font.
  • family=MuseoModerno specifies the font family name.
  • wght@300;400;600 requests three font weights: light (300), regular (400), and semi-bold (600).
  • display=swap ensures text is visible while the font loads.
  • The second <link> tag connects our local CSS file (styles.css).

The order of stylesheets are important. Earlier stylesheets with equal values will override earlier links. It is common to place your own custome CSS file at the end of external stlyesheets to have full control.

Linking the CSS file

The CSS file is already linked in the HTML above. The <link rel="stylesheet" href="styles.css" /> tells the browser to load and apply our stylesheet to this HTML document. This CSS file can be linked in multiple HTML documents for a consistent theme.

Setting base styles

Let's start with the foundational styles for the HTML and body:

html {
  font-size: 10px;
  font-family: 'MuseoModerno', cursive;
  background: #2d3740;
}

body {
  padding: 1rem;
  background: #1c262f;
  color: rgb(230, 225, 225);
  width: 90%;
  margin: 0 auto;
}
  • html sets the root font size to 10px (making rem calculations easier: 1.6rem = 16px).
  • font-family: 'MuseoModerno', cursive applies our custom Google font with a fallback of cursive if unable to load.
  • background: #2d3740 sets a dark blue-gray background color.
  • body styles create a darker content area with padding and a centered layout.
  • width: 90% makes the body responsive, using 90% of the viewport width.
  • margin: 0 auto centers the body horizontally. Applying zero spacing on the top/bottom, and auto will equally divide the remaining space on the left/right.
  • color: rgb(230, 225, 225) sets a light gray text color for good contrast.

Let's center the logo and make it responsive:

.logo {
  text-align: center;
}

svg {
  max-width: 80%;
}
  • .logo selects the element with the class=logo, centering the logo container using text-align: center.
  • svg sets a maximum width of any svg element to be 80% of the available width.

Form styling

Now let's style the input form. This is the are where we add a daily entry:

form {
  text-align: center;
}

label {
  font-size: 1.8rem;
}

input[type='number'] {
  font-family: inherit;
  background: rgb(230, 225, 225);
  width: 80%;
  margin: 1rem 0;
  padding: 0.8rem;
  border: none;
  font-size: 1.2rem;
  text-align: center;
}
  • Target the form wrapper to center all form content.
  • label sets a readable font size (18px based on our 10px root).
  • input[type='number'] uses an attribute selector to target only number inputs.
  • font-family: inherit makes the input use the same font as the body.
  • background: rgb(230, 225, 225) gives the input a light background for contrast.
  • width: 80% makes the input width 80% of the container.
  • text-align: center centers the text inside the input.

Button styling

Update the add button to convert into a circular button:

button {
  font-family: inherit;
  font-size: 1.4rem;
  font-weight: bolder;
  width: 80px;
  height: 80px;
  border: none;
  border-radius: 50%;
  background: #0ad9ff;
  margin-bottom: 1rem;
  margin-top: 0.5rem;
}
  • width: 80px; height: 80px sets the size of the button.
  • border-radius: 50% makes it perfectly circular by rounding half of each side.
  • background: #0ad9ff uses a bright cyan color to make the button stand out.
  • border: none removes the default browser border.
  • font-weight: bolder makes the button text more prominent.

Styling the entries list

Let's style the list of running entries next for the previous 7 days. This was contained in a list:

ul {
  padding: 0;
  display: flex;
  list-style: none;
  justify-content: space-around;
}

li {
  padding: 1rem 1.5rem;
  overflow: hidden;
  text-align: center;
  border: 1px solid;
  border-radius: 3px;
}
  • ul is the list container, these styles remove default padding and list bullets, then uses flexbox for layout and spacing.
  • display: flex enables flexbox layout.
  • justify-content: space-around distributes list items evenly with space around them.
  • list-style: none removes the default bullet points.
  • li styles each entry with padding, border, and rounded corners.
  • border: 1px solid creates a 1px wide border using the current text color.
  • border-radius: 3px adds slightly rounded corners.

Entries wrapper section

Next, let's apply some styling to the section containing the entries:

.entriesWrapper {
  padding: 1rem 0;
  font-size: 1.6rem;
}

.entriesWrapper h3 {
  margin: 0;
  text-align: center;
  font-size: 1.6rem;
  font-weight: lighter;
}
  • .entriesWrapper adds 1rem padding to top/bottom and sets a base font size.
  • .entriesWrapper h3 styles the heading with no margin, centered text, and a lighter font weight.

Stats section

This section is focused on the data/statistics area:

.data {
  display: flex;
  flex-direction: column;
  font-size: 1.4rem;
}

.data div {
  background: #141c22;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0.5rem 0;
  padding: 0 1rem;
}

.progress {
  text-align: center;
  padding-bottom: 1rem;
}
  • .data uses flexbox in a column layout for vertical stacking.
  • flex-direction: column stacks the statistic div's vertically.
  • .data div styles each statistic row with a darker background.
  • justify-content: space-between places the label on the left and value on the right by distributing available space between.
  • align-items: center vertically centers the content.
  • .progress area is used to center the target/goal content and add spacing.

Responsive design

Responsive design is used to adjust the styling and layout to suit different media or screen sizes, using the @media rule. Add a media query for larger screens:

@media screen and (min-width: 800px) {
  body {
    width: 60%;
  }

  svg {
    max-width: 50%;
  }

  input[type='number'] {
    width: 40%;
  }
}
  • @media screen and (min-width: 800px) applies styles only on screens 800px or wider.
  • On larger screens, the body width is reduced to 60% to avoid over streting the content.
  • The logo and input are also sized down proportionally.

Other CSS rules are still applied outisde of this media query, these rules are just added to the original styling when the 800px screen width is met.

Complete CSS file

Here's the complete styles.css file:

html {
  font-size: 10px;
  font-family: 'MuseoModerno', cursive;
  background: #2d3740;
}

body {
  padding: 1rem;
  background: #1c262f;
  color: rgb(230, 225, 225);
  width: 90%;
  margin: 0 auto;
}

.logo {
  text-align: center;
}

svg {
  max-width: 80%;
}

form {
  text-align: center;
}

label {
  font-size: 1.8rem;
}

input[type='number'] {
  font-family: inherit;
  background: rgb(230, 225, 225);
  width: 80%;
  margin: 1rem 0;
  padding: 0.8rem;
  border: none;
  font-size: 1.2rem;
  text-align: center;
}

button {
  font-family: inherit;
  font-size: 1.4rem;
  font-weight: bolder;
  width: 80px;
  height: 80px;
  border: none;
  border-radius: 50%;
  background: #0ad9ff;
  margin-bottom: 1rem;
  margin-top: 0.5rem;
}

ul {
  padding: 0;
  display: flex;
  list-style: none;
  justify-content: space-around;
}

li {
  padding: 1rem 1.5rem;
  overflow: hidden;
  text-align: center;
  border: 1px solid;
  border-radius: 3px;
}

.entriesWrapper {
  padding: 1rem 0;
  font-size: 1.6rem;
}

.entriesWrapper h3 {
  margin: 0;
  text-align: center;
  font-size: 1.6rem;
  font-weight: lighter;
}

.data {
  display: flex;
  flex-direction: column;
  font-size: 1.4rem;
}

.data div {
  background: #141c22;
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 0.5rem 0;
  padding: 0 1rem;
}

.progress {
  text-align: center;
}

@media screen and (min-width: 800px) {
  body {
    width: 60%;
  }

  svg {
    max-width: 50%;
  }

  input[type='number'] {
    width: 40%;
  }
}

Summary

In this lesson, you've:

  • Added Google Fonts: Integrated the MuseoModerno font family
  • Created a dark theme: Used dark blue-gray colors for a modern look
  • Styled the form: Made inputs and buttons visually appealing
  • Created a flexbox layout: Used flexbox for responsive list and statistics layouts
  • Added responsive design: Made the layout adapt to different screen sizes

In the next lesson, we'll add JavaScript functionality to make the form interactive and start tracking running entries.