Let's build a "Meet the Team" page entirely from data. The HTML is almost empty. JavaScript does all the work.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Meet the Team</title>
<style>
body { font-family: sans-serif; background: #f6f7fb; max-width: 720px; margin: 40px auto; }
h1 { color: #22304a; }
#team { display: grid; grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); gap: 16px; }
.card { background: white; border-radius: 16px; padding: 16px; box-shadow: 0 2px 6px rgba(0,0,0,.1); }
.card h2 { margin: 8px 0 4px; font-size: 20px; }
.role { color: #666; margin: 0 0 8px; }
.emoji { font-size: 40px; }
.tag { display: inline-block; background: #f7df1e; border-radius: 10px; padding: 2px 8px; margin: 2px; font-size: 12px; }
.lead { border: 3px solid #2ec4b6; }
</style>
</head>
<body>
<h1 id="heading">Meet the Team</h1>
<div id="team"></div>
<script src="script.js"></script>
</body>
</html>
const team = [
{ name: "Mia", role: "Team Lead", emoji: "🦁", skills: ["planning", "JavaScript"], isLead: true },
{ name: "Omar", role: "Designer", emoji: "🎨", skills: ["CSS", "drawing"], isLead: false },
{ name: "Zoe", role: "Developer", emoji: "💻", skills: ["JavaScript", "Node.js", "testing"], isLead: false },
{ name: "Sam", role: "Tester", emoji: "🔍", skills: ["debugging", "coffee"], isLead: false },
];
function createCard(member) {
const card = document.createElement("div");
card.classList.add("card");
if (member.isLead) {
card.classList.add("lead");
}
const emoji = document.createElement("div");
emoji.classList.add("emoji");
emoji.textContent = member.emoji;
const name = document.createElement("h2");
name.textContent = member.name;
const role = document.createElement("p");
role.classList.add("role");
role.textContent = member.role;
card.append(emoji, name, role);
member.skills.forEach((skill) => {
const tag = document.createElement("span");
tag.classList.add("tag");
tag.textContent = skill;
card.append(tag);
});
return card;
}
const teamContainer = document.querySelector("#team");
team.forEach((member) => {
teamContainer.append(createCard(member));
});
// Update the heading with a count
const jsFans = team.filter((m) => m.skills.includes("JavaScript")).length;
document.querySelector("#heading").textContent =
`Meet the Team (${team.length} people, ${jsFans} JavaScript fans)`;
Open it in the browser and you'll see a neat grid of four profile cards, each with an emoji, a name, a role and some skill tags. The team lead's card has a special teal border. And the heading says "Meet the Team (4 people, 2 JavaScript fans)."
Notice how everything you've learned is working together: an array of objects (Grade 8) holds the data, a function (Grade 6) builds one card, forEach and filter (Grade 10) process the array, an if (Grade 4) decides on the border, and the DOM puts it all on the screen.
Want to add a new team member? Just add one more object to the array. You don't need to touch the HTML at all. This idea, data in, page out, is exactly how modern web frameworks like React work (you'll hear about those in College).
- Add yourself to the team!
- Add a
"location"property to each member and show it on their card. - Sort the team alphabetically by name before building the cards.
- Only show members who have the skill
"JavaScript". (Hint:filterbeforeforEach.)
You can now reach into any web page and rearrange it however you like. That's real power!
But right now, all your changes happen the moment the page loads. A truly interactive page responds to the user: clicks, typing, scrolling. That's what Grade 12 is all about: events.