DEV Community

Omar
Omar

Posted on • Originally published at tinloof.com

How to build a stopwatch with HTML, CSS, and plain JavaScript (Part 1)

Stopwatch built with HTML, CSS, and JS


Build your own stopwatch with HTML, CSS, and JavaScript

This series of articles is made out of two parts:

In this first part, we build the stopwatch's user interface with HTML and CSS.

In the second part, we'll make the user interface functional with JavaScript (the stopwatch works).

Final result

This is what we will build:

Here's the link to the GitHub repo.

Here's the link to the stopwatch itself.

1- Folder structure and set-up

Our folder contains an HTML file, a CSS file, a JavaScript file, and a folder (called "icons") with 3 SVG icons:

├── icons
|  ├── pause-button.svg
|  ├── play-button.svg
|  └── reset-button.svg
├── index.html
├── script.js
└── style.css
Enter fullscreen mode Exit fullscreen mode

Here is a link to iconify to download the SVG icons.

HTML DOCTYPE declaration

In the index.html file, we include the HTML DOCTYPE declaration at the top of the page to inform the browser that the document being rendered is an HTML document:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

💡 Tip: you can easily generate the DOCTYPE declaration on VSCode by typing "!" and hitting ENTER in an HTML file.

Link HTML file with CSS file

Next, we link our HTML file with our CSS file by adding the following to our head:

<link rel="stylesheet" href="style.css" />
Enter fullscreen mode Exit fullscreen mode

💡 Tip: you can easily generate the link on VSCode by typing link:css .

We get:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css" />
</head>
<body>

</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Link HTML file with JS file

Lastly, we connect our HTML file with our JS file by adding the following script before our body closing tag:

<script src="script.js"></script>
Enter fullscreen mode Exit fullscreen mode

We get:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css" />
</head>
<body>
    <script src="script.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Great, we are now ready to code the stopwatch.

Note: the script.js file will be empty in this article since we only will implement the functionality in the next part of this series.

2- Create the HTML markup

First, we change the content wrapped by the title tags so the browser's tab's name is more relevant.

We write "Gold Stopwatch" instead of "Document":

Change the title of the document

Change the title of the page

In the body, add an h1 that says "GOLD STOPWATCH" and add a span that says "00:00:00".

This is the code:

<body>    
    <h1>GOLD STOPWATCH</h1>
    <span>00:00:00</span>
    <script src="script.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

We get:

H1 and span tags only

Only h1 and span

Next, we add buttons so we later can click on those and have a functional stopwatch. Our buttons have SVG images stored in our icons folder.

Add button s this way:

<body>
  <h1>GOLD STOPWATCH</h1>
  <span>00:00:00</span>

  <button>
    <img src="icons/play-button.svg" />

    <img src="icons/pause-button.svg" />
  </button>

  <button>
    <img src="icons/reset-button.svg" />
  </button>
    <script src="script.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

On purpose, we include two icons in the first button (both the Play and Pause icons) because we will configure this button to serve both the Play and Pause functions later in the JavaScript part.

When we'll click on the Play icon, it will disappear and the Pause icon will appear instead. Vice-versa, when we click on the Pause icon, it will disappear and the Play icon will appear instead.

This is what we get:

HTML skeleton of the page

The page structure is complete

Voilà! We are done with most of the HTML. We are now going to style it with CSS.

3- Style the HTML with CSS

Add Google Fonts

We want to use the Montserrat font for most of the text on the web page. For the numbers in the stopwatch, we want to use Roboto Mono.

To add these fonts, we search for them on Google Fonts and repeat the following steps for each one of them:

1- Click on + Select this style.

2- A window containing the font's link tag will pop up on the right. We copy the link tag and paste it in the head of the HTML document.

This is how it looks like:

Adding fonts from Google Fonts

Add fonts from Google Fonts

This is the result:

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Gold Stopwatch</title>
    <link rel="stylesheet" href="style.css" />
    <link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@200;900&display=swap"
    rel="stylesheet"/>
    <link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,300;1,300&display=swap"
    rel="stylesheet"/>
</head>
Enter fullscreen mode Exit fullscreen mode

Setting the first colors

Let's start by setting our page text and background colors. Our page text will be in white and background color in dark blue.

We target the body selector in style.css:

body {
  background-color: #31394c;
  color: #ffffff;
}
Enter fullscreen mode Exit fullscreen mode

This is what we get:

Changing the backaground color and color of the page

background-color and color styled

Style the h1

Next, we want to give more importance to "GOLD STOPWATCH". Let's style it:

h1 {
    font-size: 48px;
    font-family: "Montserrat", sans-serif;
    font-weight: 200;

    text-align: center;
    line-height: 59px;

    padding: 0;
    margin: 0;
  }
Enter fullscreen mode Exit fullscreen mode

Note: the h1 tag has some built-in margins in the browsers. We override them using margin: 0.

We get:

Center the H1 tag

Centered h1

Style one single world in the h1

If we recall, our h1 is not uniform, "GOLD" appears in yellow with a glow effect while "STOPWATCH" appears in white.

To achieve that, we wrap GOLD around a span and give it a class that we name gold:

  <h1>
    <span class="gold">GOLD</span> STOPWATCH
  </h1>

  <span>00:00:00</span>
Enter fullscreen mode Exit fullscreen mode

Now let's style this new class:

.gold {
    font-weight: 900;

    color: #f2c94c;
    text-shadow: 0 0 0px #fff, 0 0 50px #f2c94c;
  }
Enter fullscreen mode Exit fullscreen mode

We get:

Styling one word

Styling "GOLD"

We use text-shadow to create a glow effect. To understand how it works, here's a w3schools explanation on how to achieve that.

Style the position of elements

If we look at our final result, we can think of the stopwatch app as a column of three blocks:

If we inspect the final result, we can see three blocks:

  • The h1 block
  • The time span block
  • The buttons block (which we will wrap in a div)

The blocks are separated by a gap of 23px and centred horizontally in the page.

To center the elements horizontally, the column should occupy the whole page width.

We create this column div and give name its class stopwatch, and wrap our buttons with a div:

<div class="stopwatch">
  <h1>
    <span class="gold">GOLD</span> STOPWATCH
  </h1>
  <span>
    00:00:00
  </span>

  <div>
    <button>
      <img src="icons/play-button.svg" />

      <img src="icons/pause-button.svg" />
    </button>

    <button>
      <img src="icons/reset-button.svg" />
    </button>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Let's style it as a column:

.stopwatch {
    display: grid;
    justify-items: center;
    grid-row-gap: 23px;
    width: 100%;
    padding-top: 25px;
  }
Enter fullscreen mode Exit fullscreen mode

Our stopwatch class is a grid that stretches the whole page (width of 100%) and separates its blocks with 23px with grid-row-gap.

We also added 25px padding on the top to have some space above the title.

Using CSS grids for a structured layout

Separating the stopwatch app in three blocks

We add a class to the span containing "00:00:00" and name it time:

<div class="stopwatch">
  <h1>
    <span class="gold">GOLD</span> STOPWATCH
  </h1>

  <span class="time">00:00:00</span>
</div>
Enter fullscreen mode Exit fullscreen mode

Now let's style "00:00:00" to make it larger and with the right font:

.time {
  font-family: "Roboto Mono", monospace;
  font-weight: 300;
  font-size: 48px;
}
Enter fullscreen mode Exit fullscreen mode

Here's the result:

Styling the span that wraps time
Style the time span

Create a circle with CSS

To get a circle around "00:00:00", we wrap it around another div that we call circle:

<div class="stopwatch">
  <h1>
    <span class="gold">GOLD</span> STOPWATCH
  </h1>
  <div class="circle">
    <span class="time">00:00:00</span>
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

To make a div look like a circle, we give it border and add a 50% border-radius.

We get:

Use border and border-radius to create a circle

We use border and border-radius to create a circle

To make it look like a circle, we give it exact proportions. We will set both the height and width to 270px:

Give the exact width and height to the circle

Give the circle the exact width and height

To center the time inside it both horizontally and vertically, we use Flexbox.

We give a display of flex to the circle div.

To center the time vertically, we use align-items: center:

And to center the time span horizontally, we use justify-content: center:

Here is the code:

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

    height: 270px;
    width: 270px;

    border: 2px solid white;
    border-radius: 50%;
  }
Enter fullscreen mode Exit fullscreen mode

If you need a refreshment on what flexbox and CSS grid are, this great YouTube channel Layout Land by Jen Simmons will help.

If instead of border-radius 50% we make it 0%, we would get a square instead of a circle:

Create a square border with CSS

Square border

Style the buttons

Let's now focus on styling the buttons:

button {
    background: transparent;
    padding: 0;
    border: none;
    margin: 0;
    outline: none;
}
Enter fullscreen mode Exit fullscreen mode

We get:

Now let's place them in the center by targeting the div controls we just created:

We want our Pause icon to overlap with the Play icon, and create a space between the Pause/Play button and the Reset button. We wrap our buttons around a div we call controls:

<body>
  <div class="stopwatch">
    <h1>
      <span class="gold">GOLD</span> STOPWATCH
    </h1>
    <div class="circle">
      <span class="time" id="display">
        00:00:00
      </span>
    </div>

    <div class="controls">
      <button class="buttonPlay">
        <img src="icons/play-button.svg" />

        <img src="icons/pause-button.svg" />
      </button>

      <button class="buttonReset">
        <img src="icons/reset-button.svg" />
      </button>
    </div>
  </div>
  <script src="script.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

This new div controls will be given a display flex , give it a fixed width and use justify-content: space-between to properly distribute the space:

.controls {
    display: flex;
    justify-content: space-between;

    width: 187px;
  }
Enter fullscreen mode Exit fullscreen mode

We get:

Spacing two buttons with CSS

We create a space between our first and second button

Recall both the Play and Button SVGs are in the same button. For now, we only want to show the Play button and hide the Pause button.

Let's give ids to those SVGs (and to the Reset Button too, since we'll use it later):

<body>
  <div class="stopwatch">
    <h1>
      <span class="gold">GOLD</span> STOPWATCH
    </h1>
    <div class="circle">
      <span class="time" id="display">
        00:00:00
      </span>
    </div>

    <div class="controls">
      <button class="buttonPlay">
        <img id="playButton" src="icons/play-button.svg" />

        <img id="pauseButton" src="icons/pause-button.svg" />
      </button>

      <button class="buttonReset">
        <img id="resetButton" src="icons/reset-button.svg" />
      </button>
    </div>
  </div>
  <script src="script.js"></script>
</body>
Enter fullscreen mode Exit fullscreen mode

And use the display property to show the Play icon and hide the Pause icon:

#playButton {
  display: block;
}

#pauseButton {
  display: none;
}
Enter fullscreen mode Exit fullscreen mode

We get:

Hide buttons with CSS

We successfully hide the Pause button

Note: we could use classes for playButton and pauseButton, but we use ids because it will be helpful in the second part of this series.

Style the cursor

Let's make our buttons have a hand/pointer cursor:

button {
  cursor: pointer;
  background: transparent;
  padding: 0;
  border: none;
  margin: 0;
  outline: none;
}
Enter fullscreen mode Exit fullscreen mode

Here is the result:

(Bonus) Add a favicon

As a final touch, let's add a favicon, so our page has a proper tab icon in the browser:

We can do this by adding a link tag to the HTML head that points to our icon svg:

<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⏳</text></svg>">
Enter fullscreen mode Exit fullscreen mode

The head looks like this now:

<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Gold Stopwatch</title>
    <link rel="stylesheet" href="style.css" />
    <link
      href="https://fonts.googleapis.com/css2?family=Montserrat:wght@200;900&display=swap"
      rel="stylesheet"/>
    <link
      href="https://fonts.googleapis.com/css2?family=Roboto+Mono:ital,wght@0,300;1,300&display=swap"
      rel="stylesheet"/>
    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⏳</text></svg>">
  </head>
Enter fullscreen mode Exit fullscreen mode

Test responsiveness

Our stopwatch is also responsive. This is because we relied on CSS layouts like grid and flexbox to style the positioning of our elements.

Let's test it.

If we are on Chrome, we open the console (⌘+SHIFT+C for Mac or Ctrl+SHIFT+J on Windows) and select iPhone 5 SE (which is a small display size):

Great, it works.

Functionality (JavaScript)

In the next part of this series, we'll focus on the functionality of the stopwatch with JavaScript.

Top comments (0)