Series Build a Website from Scratch Bonus Part 2

A Little JavaScript —
Add Interaction to Your Site

Now that the café SOEL site is complete, let’s add small moments of interaction. We’ll build a mobile menu, update ARIA attributes, close the menu after navigation, and activate the scroll animation from the previous bonus lesson.

Quick Recap

📖 Quick Recap
  • Across the main 10 parts, we built and published the café SOEL website from scratch.
  • In Bonus Part 1, we added CSS animation and prepared the fade-in-up class.
  • To make that scroll animation actually run, we still need JavaScript to add the is-visible class.

Your site is already in a finished, publishable state. In the previous bonus lesson, we prepared how things should move with CSS. Today, we’ll give that preparation a little spark.

JavaScript is the language that lets a page respond. A button is clicked, so a menu opens. An element enters the viewport, so it fades in. Those small responses are what make a static page feel alive.

🎯 Goals for This Part
  • Create js/main.js and load it from your HTML.
  • Make the hamburger menu open and close when clicked.
  • Update aria-expanded so the menu state is communicated correctly.
  • Close the mobile menu after a navigation link is clicked.
  • Activate the scroll-triggered animation we prepared in the previous bonus lesson.
👀 Final Demo
Here is the completed café SOEL demo from the main series. Today’s JavaScript adds small interactions on top of this finished site.
View the final demo →

First, let’s understand JavaScript’s role

HTML is structure. CSS is visual design. So what is JavaScript? I often think of it as a light switch.

HTML builds the room. CSS chooses the wall color, furniture, and atmosphere. JavaScript is the switch that reacts when someone presses it.

JavaScript gives instructions to the page. The secret is not to start too big.

We’ll use only three ideas today.

1

Find an element

Use document.querySelector() to find the element you want to control.

2

Listen for an event

Use addEventListener() to wait for actions like clicks.

3

Change a class or attribute

Use classList.toggle() or setAttribute() to change the page state.

🔰 Beginner Note
JavaScript can feel intimidating at first. But today’s flow is simple: find something, wait for an action, then change something. If you understand that pattern, you’re already on your way.

Create js/main.js and load it

First, create a place for our JavaScript. Inside your project folder, create a js folder, then create main.js inside it.

📁 File we’ll add today
my-website/
├── index.html
├── css/
│   └── style.css
├── img/
│   └── ...
└── js/
    └── main.js

Next, load this JavaScript file from index.html. A script tag right before </body> can work, but today I recommend using defer in the head.

index.html — add inside <head>
<!-- Add this near your CSS link -->
<script src="js/main.js" defer></script>

defer means: “Load this file now, but run it after the HTML has been read.” That prevents JavaScript from trying to find elements before they exist.

💡 KANON’s Tip
Older tutorials often place scripts right before the closing body tag. That still works. But loading an external file with defer keeps the HTML tidy and is a common pattern in real projects.

Open and close the hamburger menu

Now let’s write JavaScript. We need to control two things: the menu button and the navigation.

js/main.js — find the elements
// Get the hamburger menu elements
const menuToggle = document.querySelector('.menu-toggle');
const nav = document.querySelector('.nav');

querySelector() uses CSS selector syntax. '.menu-toggle' finds the element with the class menu-toggle. '.nav' finds the element with the class nav.

⚠️ Common Mistake
If your <nav> does not have class="nav", add it now. The responsive CSS from the main series expects that class.
index.html — check the nav class
<nav class="nav" aria-label="Main navigation">
  <!-- nav-list goes here -->
</nav>

When the button is clicked, we’ll toggle the is-open class. Our CSS already knows what to do when .nav.is-open or .menu-toggle.is-open appears.

js/main.js — toggle the menu
menuToggle.addEventListener('click', () => {
  menuToggle.classList.toggle('is-open');
  nav.classList.toggle('is-open');
});

Save the file and refresh your browser. Narrow the browser width, click the hamburger button, and the mobile menu should open and close.

▶ Live Demo — Mobile menu toggle
café SOEL

Update aria-expanded too

The menu now opens visually. But we also need to communicate its state to assistive technology. This is where aria-expanded comes in.