2.3 JavaScript: Making It Interactive
Your pages have real structure (HTML) and now look like an actual site (CSS) — but they still just sit there. JavaScript is the language that makes a page respond: click a button and something happens, without you ever reloading the page. This week you're connecting a script file to your site and using it to make your About Me page genuinely interactive. Work through the tasks below in order — each one builds on the last.
Before You Start
- Open your
2_web_developmentfolder in VS Code — the same one from the last two weeks, in your H: drive. No new download this week; you're building on what you already made. - Check that it still has
index.html,about.html,work.html, and a/jsfolder with a file calledscript.jsinside it. Ifscript.jsis missing, create it now: right-click thejsfolder → New File → name it exactlyscript.js. - Open
script.jsand leave it open in a tab alongside your HTML files — you'll be jumping between them all week.
VS Code reminders
- Auto Save should still be on — check
File > Auto Savehas a checkmark. - Keep Live Preview open, and keep the browser's Console open too (right-click the page → Inspect → Console tab) — that's where you'll see whether your JavaScript is actually running.
- JavaScript is picky about spelling and capitalization — an
idin your HTML has to match the one in your JavaScript exactly, or nothing will happen.
script.js and proving it's running before anyone tries to build anything
with it. That walkthrough is Tasks 1–2. Once it's done, you keep going independently through
Tasks 3 and 4.
How JavaScript Connects to Your Page (quick reference)
Everything you do this week follows the same three-step pattern:
- Select something on the page — find an element using its
id. - Listen for something to happen — usually a click.
- React — change something about the page when that click happens.
const thing = document.querySelector("#thing-id");
thing.addEventListener("click", function () {
// what happens when it's clicked
});
You'll use this exact select → listen → react shape in Tasks 2 through 4 — only the details change.
Task 1 — Connect JavaScript and prove it's working
A JavaScript file that isn't linked to your page does absolutely nothing — the exact same trap as an unlinked stylesheet in 2.2. Before you build anything, you need to see proof that your script is actually running.
- Add this line just before the closing
</body>tag — on all three pages (index.html,about.html,work.html):<script src="js/script.js"></script> - In
script.js, add:console.log("script.js is connected!"); - Save everything, then open any of your three pages, right-click → Inspect → Console tab.
<script> tag goes right before </body>,
not up in <head> like your stylesheet link. If it's in <head>, your
script tries to run before the rest of the page exists, and Task 2 will break in a confusing way.
script.js is connected! on all three pages.
js/script.js must match your actual folder), then check for typos.
Task 2 — Select an element and prove you can grab it
Before JavaScript can change anything on your page, it has to be able to find it first.
document.querySelector is how your script reaches into your HTML and grabs a specific
element.
- On
about.html, give one element anid— your bio heading works well:<h1 id="bio-heading">About Me</h1> - In
script.js, select it and log it to prove the connection:const bioHeading = document.querySelector("#bio-heading"); console.log(bioHeading); - Save, then check the Console again.
about.html — it doesn't
have to be the bio heading, just something you'll want to reference again in Task 3.
<h2> element — not null.
null — this almost always means either the id doesn't match exactly (check spelling and capitalization) or your <script> tag isn't right before </body>.
Task 3 — Add a click event that changes the page
This is the actual "interactive" part of the week — your page responds to the person using it, instead of just sitting there.
Worked example — a button that reveals a hidden fact
<button id="fact-btn">Show a fun fact about me</button>
<p id="fun-fact" style="display: none;">I once built a robot out of LEGO that could actually walk.</p>
const factBtn = document.querySelector("#fact-btn");
const funFact = document.querySelector("#fun-fact");
factBtn.addEventListener("click", function () {
funFact.style.display = "block";
});
Your turn — same pattern, your own content
Fill in the blanks using your own idea — a favourite games list, your avatar's backstory, a hidden skills list — the pattern is identical:
<button id="___-btn">___</button>
<p id="___" style="display: none;">___</p>
const ___Btn = document.querySelector("#___");
const ___ = document.querySelector("#___");
___.addEventListener("click", function () {
___.style.display = "block";
});
ids in your JavaScript exactly match the ids in your HTML. This is the #1 bug this week.
Task 4 — Apply the pattern to several things at once
Task 3 changed one thing when you clicked one button. Real interactivity usually means the same behaviour applied across a group of elements — this is the step from "a button" to "a pattern." Turn a list on your page (skills, interests, favourite games) into individually-expandable items: clicking any one of several elements reveals more detail about that one, using a loop instead of writing the same code five times.
Starter code
<ul class="skills-list">
<li class="skill-pill">HTML <span class="skill-detail" style="display: none;">Building semantic page structure since Unit 2, Week 1.</span></li>
<li class="skill-pill">CSS <span class="skill-detail" style="display: none;">Learned flexbox nav and box-model spacing.</span></li>
<li class="skill-pill">Problem solving <span class="skill-detail" style="display: none;">Debugged my own null-selector bug in Task 2!</span></li>
</ul>
const skillPills = document.querySelectorAll(".skill-pill");
skillPills.forEach(function (pill) {
pill.addEventListener("click", function () {
const detail = pill.querySelector(".skill-detail");
detail.style.display = "inline";
});
});
querySelectorAll grabs every
matching element as a list, not just one. .forEach then runs the same code once for each
item in that list — so instead of writing the click logic three separate times, you write it once and it
applies to all of them.
skill-pill and
skill-detail, or rename them consistently in both your HTML and your JavaScript.
querySelector was used instead of querySelectorAll + .forEach, so double-check that.
Pick one or two, not all eight
This is where you make the site genuinely yours — pick whichever sound the most fun.
Dark mode toggle that remembers your choice
You may have already built a CSS-only dark mode switch in 2.2. This version goes further: use
JavaScript's localStorage to remember the person's choice, so it's still dark mode the
next time they open your site.
Typewriter effect
Your homepage tagline types itself out letter by letter instead of just appearing all at once.
Random fun-fact generator
A button that shows a different random fact from a list each time you click it, using Math.random().
Image lightbox
Clicking a thumbnail on your Work page opens it bigger in an overlay.
Mini self-quiz
A 2–3 question quiz about you ("guess my favourite game") with right/wrong feedback when someone answers.
Scroll reveal
Sections fade in as you scroll down the page instead of all being visible at once. (Stretch — uses IntersectionObserver.)
Contact form with validation
A form that checks the fields aren't empty and gives feedback — without actually sending anything anywhere.
Console easter egg
A styled message in the browser console for anyone curious enough to open DevTools.
Checkpoint for any Black task: does it actually work when someone else clicks or tries it — not just when you do (since you already know where the bugs are)?