Enhancing the App

Our app works and has basic styling, but it is missing features. Let’s add images, better structure, and navigation buttons.

Adding Static Assets

Your project should include two image files in the starter assets: moon.png and favicon.png. These are static assets: files that the browser serves exactly as they are, without any processing. Images, fonts, and other media files are all static assets.

Make sure these files are in your project folder alongside index.html.

Adding a Favicon

A favicon is the small icon that appears in the browser tab. Add this to your <head> section, before the title:

    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+   <link rel="icon" type="image/x-icon" href="favicon.png" />
    <title>WakeUp Times</title>

Refresh. You should see a small icon in the browser tab.

Adding a Web Font

The default Arial font works, but let’s use a different font. Google Fonts provides free fonts you can use on any website.

Add these <link> tags in your HTML <head>, before the stylesheet link:

<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
  href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;600&display=swap"
  rel="stylesheet"
/>

The preconnect hints tell the browser to establish the connections early, so the font loads faster.

Now update the font-family in index.css:

body {
  font-size: 16px;
  font-family: "Poppins", Arial, sans-serif;
  background-color: #f5f5f5;
  text-align: center;
  color: #333;
}

The browser loads the Poppins font from Google’s servers. The fallback fonts (Arial, sans-serif) are used while the custom font loads or if it fails.

Restructuring the HTML

Right now everything is directly in the <body>. Let’s organize it into sections. Update the body section of the index.html:

  <body>
    <div id="app">
      <section id="prompt-section">
        <h1>WakeUp Times</h1>
        <p>
          A sleep cycle lasts about 90 minutes, and a good night's sleep
          consists of 5-6 sleep cycles.
        </p>
        <p>If you go to bed now, when should you wake up?</p>
        <button id="calc-btn">Calculate</button>
      </section>

      <div id="img-container">
        <img src="moon.png" alt="moon" />
      </div>

      <section id="result-section" class="hidden">
        <div class="button-group">
          <button id="return-btn"></button>
          <button id="refresh-btn">Refresh</button>
        </div>

        <p>Try to wake up at one of these times:</p>
        <div id="wakeup-hours-div"></div>
        <p><small>* It takes ~14 minutes to fall asleep.</small></p>
      </section>
    </div>

    <script src="index.js"></script>
  </body>

Here is what we added:

  • <div id="app"> wraps everything for consistent styling
  • <section id="prompt-section"> groups the initial prompt
  • <div id="img-container"> holds the moon image
  • <section id="result-section" class="hidden"> wraps results with a hidden class
  • Navigation buttons (return and refresh) to switch between the prompt and the results

Refresh the browser. You should see the moon image (probably very large), and notice the result section is not visible.

The Hidden Class

The result section has class="hidden", but it does not do anything yet. Let’s define it in index.css:

.hidden {
  display: none;
}

The display: none hides the element completely. It will not take up any space on the page.

Styling the Moon Image

Refresh the browser. You will see the moon image is too large. Let’s fix that. Add this to index.css:

img {
  max-width: 80%;
  height: auto;
}

The max-width: 80% means the image never gets wider than 80% of its container. Setting height: auto keeps the aspect ratio.

Showing the Result Section

Right now, clicking Calculate computes the wake-up times but the result section stays hidden. Let’s fix that.

First, we need a reference to the result section. Add this to the index.js:

  const calcBtn = document.getElementById("calc-btn");
  const wakeUpHoursDiv = document.getElementById("wakeup-hours-div");
+ const resultSection = document.getElementById("result-section");
  calcBtn.onclick = calcWakeUpTimes;

Now add this line at the end of the calcWakeUpTimes function, after the loop:

resultSection.classList.remove("hidden");

The classList property provides methods to manipulate an element’s CSS classes. The remove method removes a class. In this case, removing hidden makes the element visible.

Click Calculate. The results now appear below the prompt.

Toggling Between Sections

We want the app to switch views: when Calculate is clicked, hide the prompt and show the results. When the back button is clicked, do the opposite.

We need references to the prompt section and the return button. Add these to index.js:

  const resultSection = document.getElementById("result-section");
+ const promptSection = document.getElementById("prompt-section");
+ const returnBtn = document.getElementById("return-btn");
  calcBtn.onclick = calcWakeUpTimes;

Now update the end of calcWakeUpTimes to also hide the prompt:

promptSection.classList.add("hidden");
resultSection.classList.remove("hidden");

The classList.add method adds a class to an element. Adding hidden makes it disappear.

Next, create a function to go back and wire it to the return button:

function goBack() {
  promptSection.classList.remove("hidden");
  resultSection.classList.add("hidden");
}

returnBtn.onclick = goBack;

Test it. Click Calculate to see results, then click the back arrow to return to the prompt.

The Refresh Button

Finally, let’s wire up the refresh button. It should recalculate the wake-up times (useful if you have been on the page for a while and the current time has changed).

Add this to index.js:

  const returnBtn = document.getElementById("return-btn");
  const refreshBtn = document.getElementById("refresh-btn");
+ calcBtn.onclick = calcWakeUpTimes;

  returnBtn.onclick = goBack;
  returnBtn.onclick = goBack;
+ refreshBtn.onclick = calcWakeUpTimes;

The refresh button calls the same calcWakeUpTimes function. It recalculates based on the current time.

The app is now fully functional. But the styling from the previous section does not match our new structure. In the next section, we will polish the CSS.

Checkpoint: Commit your progress.

git add .
git commit -m "wakeup-05: Enhance app with new features"
git push