Build and Publish a Mood Picker
Build and publish an interactive Mood Picker with HTML, CSS, and JavaScript.
Introduction
30 Second Summary
Your energy changes throughout the day. Choosing one small activity that fits your mood can make the next few minutes easier to use well.
In this project, you will build a colorful Mood Picker with HTML, CSS, and JavaScript. You will publish it with GitHub Pages so anyone can open your finished site from a public link.
What You'll Build
You will click any mood to see a matching activity appear instantly inside a polished card that works on a computer or phone.
By the end of this project, you'll have:
- A responsive mood card where you can compare four choices on a computer or phone.
- An interactive picker that shows a matching activity immediately after you click a mood.
- A shareable GitHub Pages link that lets anyone open your finished Mood Picker.
- Secret Mission: Add a Surprise me button that chooses a random mood and activity.
Are there any prerequisites?
You need access to your GitHub account in a web browser. No prior coding knowledge is required.
Before We Start
This step is your moment to commit to the Mood Picker before any hands-on work begins. A clear reason for seeing it online gives the build a purpose.
Set Up a Live Starter Page
A website needs a public home before anyone else can open it. It also needs an entry file for the browser to load.
GitHub gives the project a public repository. GitHub Pages publishes your HTML from that repository as a website.
In this step, get ready to:
- Create a public GitHub repository with a README.
- Add a minimal index.html entry file.
- Publish the default branch's root folder with GitHub Pages.
Create the public repository
A repository holds your website files in one place. The README gives the new repository an initial file on its default branch.
Keep Public Files Safe
This repository is public. Its website is public too.
Keep personal or sensitive information out of every file.
- Return to GitHub in your browser.
- Confirm your profile image is visible in the page header.
- Select New repository from GitHub's repository menu.
- Enter mood-picker as the repository name.
- Select Public under the visibility options.
- Switch Add README to On.
- Click Create repository.
Your public project home is ready. The mood-picker repository now has a README on its default branch.
Cannot Create the Repository?
- Check that mood-picker is entered without spaces.
- Confirm your profile image is still visible in the page header.
Help me troubleshoot creating my public GitHub repository.
Add the starter HTML file
GitHub Pages looks for an entry file at the top level of its publishing source. Your index.html file gives the browser the first version of the Mood Picker to display.
- Select Add file above the repository file list.
- Click Create new file.
- Enter index.html in the file name field.
- Add the starter document by copying the code below into the editor:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mood Picker</title>
</head>
<body>
<h1>Mood Picker</h1>
</body>
</html>
What Does This Code Do?
- The document declaration tells the browser to use modern HTML.
- The head stores the page title plus browser display settings.
- The title names the browser tab.
- The body displays the Mood Picker heading on the page.
- Select Commit changes... beneath the editor.
- Confirm the commit in the dialog.
- Verify that index.html appears beside the README in the repository file list.
Cannot See the Starter File?
- Check that the file name is exactly index.html.
- Confirm that you completed the commit dialog.
Help me find my committed index.html file.
✔️ Awesome, I've got everything!
Your starter file now contains the heading required for the first live check.
ⓧ I'd like to double check the full code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mood Picker</title>
</head>
<body>
<h1>Mood Picker</h1>
</body>
</html>
Publish with GitHub Pages
A publishing source tells GitHub Pages where the website files live. The default branch's root folder contains index.html.
- Select Settings in the mood-picker repository.
- Select Pages in the sidebar.
- Set Source to Deploy from a branch under Build and deployment.
- Select the repository's default branch in the branch menu.
- Select / in the folder menu.
- Click Save.
GitHub now starts publishing the files from your selected source.
The first publication can take up to 10 minutes, so a short wait here is normal.
Before you open the site, what heading do you expect the browser to show?
- Click Visit site under GitHub Pages after the publication finishes.
Your published page shows the heading Mood Picker. That first live result proves your repository can publish changes to the web.
Site Not Ready?
- Wait up to 10 minutes for the first publication to finish.
- Confirm Source shows Deploy from a branch.
- Confirm the folder menu shows /.
Help me troubleshoot my GitHub Pages deployment.
Your starter page now has a public address plus a working deployment path. Next, you will turn the single heading into the visible controls for your Mood Picker.
Build the Mood Picker Structure
Your live starter page proves that GitHub Pages can publish your work. Now the page needs an interface that lets a visitor share how they feel.
The starter heading cannot collect a mood. You will add semantic HTML controls. You will also add a result region for the activity suggestion.
In this step, get ready to:
- Replace the starter heading with a semantic mood-selection card.
- Add four accessible mood controls.
- Add a live recommendation panel.
Add the page controls and result
A main element groups the page's primary content. Each button carries a mood value that the finished picker can use when someone makes a choice.
- Return to the mood-picker repository from earlier.
- Select index.html from the repository file list.
- Select the pencil icon in the upper-right corner of the file view.
- Select the existing <h1>Mood Picker</h1> line inside <body>.
- Replace the selected line by pasting this structure:
<main>
<p class="eyebrow">Quick reset</p>
<h1>How are you feeling?</h1>
<p class="intro">Choose a mood and get one small activity you can try right now.</p>
<div class="mood-grid" aria-label="Mood choices">
<button class="mood-button" type="button" data-mood="energized" aria-pressed="false">Energized</button>
<button class="mood-button" type="button" data-mood="calm" aria-pressed="false">Calm</button>
<button class="mood-button" type="button" data-mood="curious" aria-pressed="false">Curious</button>
<button class="mood-button" type="button" data-mood="tired" aria-pressed="false">Tired</button>
</div>
<section class="result" aria-live="polite">
<p class="result-label">Your activity</p>
<p id="recommendation">Pick a mood to see a suggestion.</p>
</section>
</main>
What does this structure do?
- The main element identifies the page's primary content.
- The mood-grid group contains the four mood choices.
- Each mood-button shares one class for consistent styling later.
- Each data-mood value identifies the activity that belongs to its button.
- The ARIA attributes give assistive technology useful state information.
- The aria-live="polite" value prepares the result region to announce future updates without interrupting the visitor.
- Select Commit changes... in the upper-right corner.
- Keep the default option that commits directly to the current branch.
- Select Commit changes in the dialog.
That is a meaningful jump. Your one-line page now has a complete set of mood controls in the repository.
Still seeing the old heading in the file?
- Confirm that you replaced the original <h1>Mood Picker</h1> line.
- Check that the opening <main> tag has a matching </main> tag.
- Confirm that the new structure remains between <body> and </body>.
Help me compare my Mood Picker HTML with the expected structure.
The completed index.html file should now match this reference.
✔️ Awesome, I've got everything!
Your committed file now contains the mood controls plus the recommendation panel.
ⓧ I'd like to double check the full code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mood Picker</title>
</head>
<body>
<main>
<p class="eyebrow">Quick reset</p>
<h1>How are you feeling?</h1>
<p class="intro">Choose a mood and get one small activity you can try right now.</p>
<div class="mood-grid" aria-label="Mood choices">
<button class="mood-button" type="button" data-mood="energized" aria-pressed="false">Energized</button>
<button class="mood-button" type="button" data-mood="calm" aria-pressed="false">Calm</button>
<button class="mood-button" type="button" data-mood="curious" aria-pressed="false">Curious</button>
<button class="mood-button" type="button" data-mood="tired" aria-pressed="false">Tired</button>
</div>
<section class="result" aria-live="polite">
<p class="result-label">Your activity</p>
<p id="recommendation">Pick a mood to see a suggestion.</p>
</section>
</main>
</body>
</html>
Test the published controls
The live page now lets you test what this structure can do. Your published site provides the visible evidence.
GitHub Pages updates can take up to 10 minutes after a commit. A short wait here means the deployment is still catching up.
Before you refresh, do you think choosing a mood will change the recommendation? The live page is about to test your prediction.
- Return to the repository's Settings area.
- Select Pages in the sidebar.
- Select Visit site under GitHub Pages.
- Refresh the published site.
You will see the heading How are you feeling?. Four mood buttons appear below it. The Your activity panel shows the starter recommendation.
- Select the Energized button.
The recommendation still reads Pick a mood to see a suggestion. This shortfall is intentional.
Why did the button stay quiet?
HTML gives the page meaningful controls. It does not define what happens after a click.
A later JavaScript layer will connect each mood to its activity. You have now seen the exact behavior gap that layer needs to close.
Your Mood Picker now presents every choice clearly. Next, you will use CSS to turn this plain structure into a responsive card.
Style the Mood Picker
Your GitHub Pages site now shows the complete HTML structure for the Mood Picker. The four mood buttons sit above a result panel that is ready for an activity.
The structure still looks like plain browser controls. CSS turns it into an inviting card with clear feedback for pointer or keyboard use.
In this step, get ready to:
- Create a purple page canvas with a centered white card.
- Style the mood grid with clear interaction states.
- Finish the result panel with a narrow-screen layout.
Style the page canvas
CSS custom properties give repeated colors memorable names. The page styles can then reuse one palette across the background and card.
- Return to your mood-picker repository.
- Select index.html from the file list.
- Select the pencil icon in the file toolbar.
- Find the line containing <title>Mood Picker</title>.
- Place your cursor directly after that line.
- Build the page palette and canvas by pasting this code:
<style>
:root {
color-scheme: light;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--ink: #24133d;
--muted: #695a7d;
--accent: #6d3dd1;
--accent-dark: #4e25a8;
--surface: #ffffff;
--soft: #f3edff;
}
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
padding: 24px;
display: grid;
place-items: center;
color: var(--ink);
background: linear-gradient(135deg, #4b1d83, #9258d8);
}
</style>
What does this code do?
- The :root rules store the page font and six reusable colors.
- The universal * selector keeps element dimensions predictable when padding or borders are added.
- The body rules create the purple background and center the page content.
GitHub Pages updates can take up to 10 minutes to publish. A short wait after each commit is normal.
- Select Commit changes... in the top-right corner.
- Complete the commit dialog.
- Return to the published site from earlier.
- Refresh the page.
You'll see the plain white page replaced by a purple gradient. The existing content sits in the center of the browser.
That first visual shift confirms your stylesheet is loading on the live site.
Still seeing a white background?
- Wait for the latest GitHub Pages deployment to finish.
- Refresh the published site after the deployment completes.
- Check that the opening <style> tag appears below the page title.
Help me find why the new page background is missing.
The canvas is ready. The next styles turn the existing main element into the white card that holds the Mood Picker.
- Return to the editing view for index.html.
- Place your cursor directly above the closing </style> tag.
- Create the card and its opening typography by pasting this code:
main {
width: min(100%, 720px);
padding: clamp(28px, 6vw, 56px);
border-radius: 28px;
background: var(--surface);
box-shadow: 0 24px 70px rgba(31, 11, 61, 0.3);
}
.eyebrow {
margin: 0 0 8px;
color: var(--accent);
font-size: 0.8rem;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
}
h1 {
margin: 0;
font-size: clamp(2rem, 7vw, 3.75rem);
line-height: 1.05;
}
.intro {
max-width: 55ch;
margin: 16px 0 28px;
color: var(--muted);
font-size: 1.05rem;
line-height: 1.6;
}
How does the card take shape?
- The main rules limit the card width and add responsive inner spacing.
- The .eyebrow rules turn the opening label into a compact purple accent.
- The heading and introduction rules create a clear reading order inside the card.
- Select Commit changes....
- Complete the commit dialog.
- Return to the published site.
- Refresh the page after the deployment completes.
You'll see a centered white card with rounded corners. The heading grows while the introduction becomes softer and easier to read.
The Mood Picker now has a clear visual home instead of floating directly on the page.
Card still missing?
- Check that the new rules sit inside the existing <style> element.
- Check that the selector is written as main.
- Confirm that the latest change appears in the repository commit history.
Help me troubleshoot the missing white card.
Build the mood controls
A grid controls how the four choices share the available space. Shared button styles keep every mood equally prominent.
- Return to the editing view for index.html.
- Place your cursor directly above the closing </style> tag.
- Turn the mood choices into a two-column button grid by pasting this code:
.mood-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.mood-button {
min-height: 58px;
padding: 14px 18px;
border: 2px solid transparent;
border-radius: 16px;
color: var(--ink);
background: var(--soft);
font: inherit;
font-weight: 750;
cursor: pointer;
transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}
What styles the mood choices?
- The .mood-grid selector places the four choices in two equal columns.
- The .mood-button selector gives every choice the same size and soft background.
- The transition smooths later changes to position and color.
- Select Commit changes....
- Complete the commit dialog.
- Return to the published site.
- Refresh the page after the deployment completes.
You'll see four rounded mood buttons arranged in two columns. Each choice has a pale purple background with consistent spacing.
Your controls now read as one coordinated picker instead of four unrelated browser buttons.
Buttons still look plain?
- Check that .mood-button begins with a period.
- Check that the selector matches the class on all four buttons.
- Confirm that the latest commit contains both new selector blocks.
Help me find why the mood button styles are missing.
Visual states show which control the visitor is pointing at or using from the keyboard. A selected state also prepares the page for the interaction logic added next.
- Return to the editing view for index.html.
- Place your cursor directly above the closing </style> tag.
- Add the hover, keyboard-focus, and selected states by pasting this code:
.mood-button:hover {
transform: translateY(-2px);
border-color: #c8b2f3;
}
.mood-button:focus-visible {
outline: 3px solid #f0b429;
outline-offset: 3px;
}
.mood-button.active {
border-color: var(--accent-dark);
color: #ffffff;
background: var(--accent);
}
How does each state help?
- The :hover state lifts a button when a pointer rests over it.
- The :focus-visible state draws a gold outline for keyboard navigation.
- The .active state provides the purple selected style used by the finished interaction.
- Select Commit changes....
- Complete the commit dialog.
- Refresh the published site after the deployment completes.
- Hover your pointer over a mood button.
- Press Tab until a mood button receives keyboard focus.
You'll see a hovered button lift slightly and gain a border. A keyboard-focused button shows a gold outline.
Both pointer and keyboard visitors now receive visible feedback from the same controls.
Interaction feedback missing?
- Move the pointer directly over the colored area of a mood button.
- Check that :hover and :focus-visible include their leading colons.
- Press Tab again if the browser focus is still outside the page controls.
Help me troubleshoot the missing hover or focus state.
Finish the result and responsive layout
The result panel needs enough contrast to separate the recommendation from the choices. A small-screen rule then stacks the mood buttons when two columns become cramped.
- Return to the editing view for index.html.
- Place your cursor directly above the closing </style> tag.
- Finish the result panel and narrow-screen layout by pasting this code:
.result {
margin-top: 24px;
padding: 20px;
border-left: 5px solid var(--accent);
border-radius: 14px;
background: #faf8ff;
}
.result-label {
margin: 0 0 6px;
color: var(--accent-dark);
font-size: 0.78rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}
#recommendation {
margin: 0;
font-size: 1.1rem;
line-height: 1.55;
}
@media (max-width: 520px) {
.mood-grid {
grid-template-columns: 1fr;
}
}
How does the layout adapt?
- The .result selector gives the recommendation its own tinted panel.
- The label and recommendation rules create a clear visual order inside that panel.
- The media query changes the mood grid to one column when the page width reaches 520px or less.
- Select Commit changes....
- Complete the commit dialog.
- Return to the published site.
- Refresh the page after the deployment completes.
You'll see a pale result panel with a purple left border. The recommendation text has more room to breathe.
The full visual design is now live and ready for its final responsive check.
Result panel still unstyled?
- Check that the class selector is written as .result.
- Check that the ID selector is written as #recommendation.
- Confirm that the media query closes before the </style> tag.
Help me troubleshoot the result panel or responsive grid.
Your completed index.html should now match one of the outcomes below.
✔️ Awesome, I've got everything!
Your CSS is in place. The final check below confirms the card, interaction feedback, and responsive layout.
ⓧ I'd like to double check the full code
- Compare your index.html with this complete version.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mood Picker</title>
<style>
:root {
color-scheme: light;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--ink: #24133d;
--muted: #695a7d;
--accent: #6d3dd1;
--accent-dark: #4e25a8;
--surface: #ffffff;
--soft: #f3edff;
}
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
padding: 24px;
display: grid;
place-items: center;
color: var(--ink);
background: linear-gradient(135deg, #4b1d83, #9258d8);
}
main {
width: min(100%, 720px);
padding: clamp(28px, 6vw, 56px);
border-radius: 28px;
background: var(--surface);
box-shadow: 0 24px 70px rgba(31, 11, 61, 0.3);
}
.eyebrow {
margin: 0 0 8px;
color: var(--accent);
font-size: 0.8rem;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
}
h1 {
margin: 0;
font-size: clamp(2rem, 7vw, 3.75rem);
line-height: 1.05;
}
.intro {
max-width: 55ch;
margin: 16px 0 28px;
color: var(--muted);
font-size: 1.05rem;
line-height: 1.6;
}
.mood-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.mood-button {
min-height: 58px;
padding: 14px 18px;
border: 2px solid transparent;
border-radius: 16px;
color: var(--ink);
background: var(--soft);
font: inherit;
font-weight: 750;
cursor: pointer;
transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}
.mood-button:hover {
transform: translateY(-2px);
border-color: #c8b2f3;
}
.mood-button:focus-visible {
outline: 3px solid #f0b429;
outline-offset: 3px;
}
.mood-button.active {
border-color: var(--accent-dark);
color: #ffffff;
background: var(--accent);
}
.result {
margin-top: 24px;
padding: 20px;
border-left: 5px solid var(--accent);
border-radius: 14px;
background: #faf8ff;
}
.result-label {
margin: 0 0 6px;
color: var(--accent-dark);
font-size: 0.78rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}
#recommendation {
margin: 0;
font-size: 1.1rem;
line-height: 1.55;
}
@media (max-width: 520px) {
.mood-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<main>
<p class="eyebrow">Quick reset</p>
<h1>How are you feeling?</h1>
<p class="intro">Choose a mood and get one small activity you can try right now.</p>
<div class="mood-grid" aria-label="Mood choices">
<button class="mood-button" type="button" data-mood="energized" aria-pressed="false">Energized</button>
<button class="mood-button" type="button" data-mood="calm" aria-pressed="false">Calm</button>
<button class="mood-button" type="button" data-mood="curious" aria-pressed="false">Curious</button>
<button class="mood-button" type="button" data-mood="tired" aria-pressed="false">Tired</button>
</div>
<section class="result" aria-live="polite">
<p class="result-label">Your activity</p>
<p id="recommendation">Pick a mood to see a suggestion.</p>
</section>
</main>
</body>
</html>
Before you run the final check, which visual details do you expect to respond to pointer use, keyboard use, and a narrow browser window?
- Return to the published Mood Picker.
- Refresh the page.
- Hover your pointer over each mood button.
- Press Tab until a mood button receives focus.
- Drag the browser edge inward until the mood grid changes to one column.
You'll see a purple background around a centered white card. The mood choices sit in two columns at wider sizes.
A hovered button lifts and gains a border. A keyboard-focused button shows a gold outline.
At a narrow width, the buttons stack into one column. The result panel remains readable beneath them.
Well done. Your live Mood Picker now looks polished across pointer, keyboard, and narrow-screen use.
Your interface is ready. Next, you'll connect every mood button to its matching activity and selected state.
Make Every Mood Button Work
Your polished Mood Picker is live on GitHub Pages. The responsive card now gives every mood a clear visual control.
The mood buttons still stop at visual feedback because no JavaScript responds to a click. Click events will connect each button to a matching activity while the DOM keeps its selected state synchronized.
In this step, get ready to:
- Store each activity under its matching mood.
- Add a reusable function that keeps the recommendation synchronized with the selected button.
- Connect every mood button to the shared function.
Connect the mood buttons to activities
The script needs a reliable link between each button and its activity. Each data-mood value becomes a key in the activities object.
- Return to the mood-picker repository from earlier.
- Select index.html from the repository file list.
- Use the file toolbar's edit control to enter editing mode.
- Find the blank line between </main> and </body>.
- Add the complete interaction by pasting this script into that blank line:
<script>
const activities = {
energized: "Put on one song and take a brisk walk.",
calm: "Make a warm drink and write down one thing you appreciate.",
curious: "Spend ten minutes learning one surprising fact.",
tired: "Step away from the screen, stretch, and take five slow breaths."
};
const recommendation = document.querySelector("#recommendation");
const moodButtons = document.querySelectorAll(".mood-button");
function chooseMood(button) {
const mood = button.dataset.mood;
recommendation.textContent = activities[mood];
for (const moodButton of moodButtons) {
const isSelected = moodButton === button;
moodButton.classList.toggle("active", isSelected);
moodButton.setAttribute("aria-pressed", String(isSelected));
}
}
for (const button of moodButtons) {
button.addEventListener("click", () => chooseMood(button));
}
</script>
What does this code do?
- The activities object pairs each mood with the activity shown after a click.
- The recommendation variable targets the result text.
- The moodButtons variable collects all four mood controls.
- The chooseMood(button) function reads the selected button's mood. It replaces the starter recommendation with the matching activity.
- The selection loop applies the active class to one button. It sets that button's aria-pressed value to true.
- Each click listener passes its button into chooseMood(button).
A commit saves this browser edit to the default branch. The active Pages deployment can then publish the new script.
- Click Commit changes....
- Enter Make mood buttons interactive in the commit message field.
- Keep the default branch option selected.
- Click Commit changes.
You return to index.html with the new script visible below </main>.
Commit not available?
- Confirm the script sits before the closing </body> tag.
- Compare every brace and parenthesis with the full-file reference below.
Ask for help if the editor still blocks the commit: Help me check the JavaScript added to my Mood Picker index.html file for a missing brace or parenthesis.
✔️ Awesome, I've got everything!
Great. Your committed index.html now contains the complete Mood Picker interaction.
ⓧ I'd like to double check the full code
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Mood Picker</title>
<style>
:root {
color-scheme: light;
font-family: system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
--ink: #24133d;
--muted: #695a7d;
--accent: #6d3dd1;
--accent-dark: #4e25a8;
--surface: #ffffff;
--soft: #f3edff;
}
* {
box-sizing: border-box;
}
body {
min-height: 100vh;
margin: 0;
padding: 24px;
display: grid;
place-items: center;
color: var(--ink);
background: linear-gradient(135deg, #4b1d83, #9258d8);
}
main {
width: min(100%, 720px);
padding: clamp(28px, 6vw, 56px);
border-radius: 28px;
background: var(--surface);
box-shadow: 0 24px 70px rgba(31, 11, 61, 0.3);
}
.eyebrow {
margin: 0 0 8px;
color: var(--accent);
font-size: 0.8rem;
font-weight: 800;
letter-spacing: 0.12em;
text-transform: uppercase;
}
h1 {
margin: 0;
font-size: clamp(2rem, 7vw, 3.75rem);
line-height: 1.05;
}
.intro {
max-width: 55ch;
margin: 16px 0 28px;
color: var(--muted);
font-size: 1.05rem;
line-height: 1.6;
}
.mood-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
}
.mood-button {
min-height: 58px;
padding: 14px 18px;
border: 2px solid transparent;
border-radius: 16px;
color: var(--ink);
background: var(--soft);
font: inherit;
font-weight: 750;
cursor: pointer;
transition: transform 160ms ease, border-color 160ms ease, background 160ms ease;
}
.mood-button:hover {
transform: translateY(-2px);
border-color: #c8b2f3;
}
.mood-button:focus-visible {
outline: 3px solid #f0b429;
outline-offset: 3px;
}
.mood-button.active {
border-color: var(--accent-dark);
color: #ffffff;
background: var(--accent);
}
.result {
margin-top: 24px;
padding: 20px;
border-left: 5px solid var(--accent);
border-radius: 14px;
background: #faf8ff;
}
.result-label {
margin: 0 0 6px;
color: var(--accent-dark);
font-size: 0.78rem;
font-weight: 800;
letter-spacing: 0.08em;
text-transform: uppercase;
}
#recommendation {
margin: 0;
font-size: 1.1rem;
line-height: 1.55;
}
@media (max-width: 520px) {
.mood-grid {
grid-template-columns: 1fr;
}
}
</style>
</head>
<body>
<main>
<p class="eyebrow">Quick reset</p>
<h1>How are you feeling?</h1>
<p class="intro">Choose a mood and get one small activity you can try right now.</p>
<div class="mood-grid" aria-label="Mood choices">
<button class="mood-button" type="button" data-mood="energized" aria-pressed="false">Energized</button>
<button class="mood-button" type="button" data-mood="calm" aria-pressed="false">Calm</button>
<button class="mood-button" type="button" data-mood="curious" aria-pressed="false">Curious</button>
<button class="mood-button" type="button" data-mood="tired" aria-pressed="false">Tired</button>
</div>
<section class="result" aria-live="polite">
<p class="result-label">Your activity</p>
<p id="recommendation">Pick a mood to see a suggestion.</p>
</section>
</main>
<script>
const activities = {
energized: "Put on one song and take a brisk walk.",
calm: "Make a warm drink and write down one thing you appreciate.",
curious: "Spend ten minutes learning one surprising fact.",
tired: "Step away from the screen, stretch, and take five slow breaths."
};
const recommendation = document.querySelector("#recommendation");
const moodButtons = document.querySelectorAll(".mood-button");
function chooseMood(button) {
const mood = button.dataset.mood;
recommendation.textContent = activities[mood];
for (const moodButton of moodButtons) {
const isSelected = moodButton === button;
moodButton.classList.toggle("active", isSelected);
moodButton.setAttribute("aria-pressed", String(isSelected));
}
}
for (const button of moodButtons) {
button.addEventListener("click", () => chooseMood(button));
}
</script>
</body>
</html>
Use this full-file reference to compare the placement and spelling of every project identifier.
Test every mood on the live site
The Pages deployment publishes the latest static file from your default branch. A fresh commit can take up to 10 minutes to reach the public site.
- Return to the repository's Settings page.
- Select Pages.
- Click Visit site.
Before you click a mood, do you expect the recommendation and selected color to update together?
- Click Energized.
- Click Calm.
- Click Curious.
- Click Tired.
What should I see?
- Energized shows Put on one song and take a brisk walk..
- Calm shows Make a warm drink and write down one thing you appreciate..
- Curious shows Spend ten minutes learning one surprising fact..
- Tired shows Step away from the screen, stretch, and take five slow breaths..
- The most recently clicked button has the purple selected style. Every other mood returns to its soft background.
🙋♀️ Still seeing the starter recommendation?
- Wait up to 10 minutes for the latest commit to publish.
- Reload the live site after the publishing delay.
- Return to index.html if the buttons remain inert.
- Compare the script with the full-file reference above.
Ask for help with the live interaction: Help me find why my published Mood Picker buttons do not update the recommendation.
Confirm the accessible selected state
The visible purple style shows sighted visitors which mood is selected. The aria-pressed value exposes the same state to assistive technology.
- Keep one mood selected on the live site.
- Open your browser's inspector for the selected mood button.
- Confirm the selected button contains aria-pressed="true".
- Inspect any unselected mood button.
- Confirm the unselected button contains aria-pressed="false".
That completes the interaction. Your Mood Picker now changes activities while keeping exactly one visible and accessible selection.
Seeing more than one selected state?
- Confirm the for loop sits inside chooseMood(button).
- Check that const isSelected = moodButton === button; matches the full-file reference.
- Confirm both state updates use isSelected.
Ask for help with the selected state: Help me debug why more than one Mood Picker button appears selected.
Secret mission
Add a Surprise Me Button
Give visitors a way to receive an activity without choosing a mood first. You will add a Surprise me button that selects a random mood through the picker's existing logic.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause the website, or delete everything. Keeping this public project on GitHub Free costs $0.
Resources you used:
- A public GitHub repository named mood-picker.
- A public GitHub Pages deployment from the default branch root folder /.
Keep everything running
No action is needed. Choose this option if you want the Mood Picker to remain available through its public link.
- Leave the public mood-picker repository in place.
- Leave its GitHub Pages deployment published.
- Use the live link whenever you want to share your completed Mood Picker.
Pause - I'll come back to this later
Unpublish the GitHub Pages deployment to take the website offline. Your repository stays available for a later return.
- Return to the mood-picker repository on GitHub.
- Select Settings.
- Select Pages.
- Open the menu beside Your site is live at.
- Select Unpublish site.
You now have a clean pause. The public link is offline while index.html remains in mood-picker.
Delete - I don't want to use this again
Deleting the repository removes your public code and its Pages deployment. GitHub asks you to confirm the repository name before the final action.
- Return to the mood-picker repository on GitHub.
- Select Settings.
- Stay on General.
- Scroll to Danger Zone.
- Click Delete this repository.
- Confirm each warning shown by GitHub.
- Type mood-picker when GitHub asks for the repository name.
- Click Delete this repository to complete the deletion.
The mood-picker repository is no longer available. Its GitHub Pages deployment no longer serves the website.
Nice Work!
Nice Work!
You did it! Your responsive Mood Picker now recommends activities for four moods and highlights each selection. The finished site is live at a public link you can share.
You've learned how to:
- Built a one-page website with semantic HTML controls. Added an accessible result region for activity recommendations.
- Styled a responsive card with CSS. Added clear hover states. Added selected states. Added visible keyboard-focus feedback.
- Connected JavaScript click events to activity data. Updated the recommendation without reloading the page. Published the finished site through GitHub Pages.
- Secret Mission: Added a visually distinct Surprise me button. Reused chooseMood() to select a random mood while preserving the visible and accessible selected state.
Ready to quiz yourself?