Build the Adejumo Food Bank Website
Build and deploy a responsive food bank website with Netlify Forms.
Introduction
30 Second Summary
Every nonprofit needs a website that looks professional, works on any device, and makes it easy for visitors to get help, donate, or volunteer. Most small organizations pay a developer or settle for a clunky template that does not quite fit.
In this project, you will build a complete, responsive website for the Adejumo Food Bank from scratch using HTML, CSS, and JavaScript. You will deploy it to a live public URL using Netlify for free.
What You'll Build
When you open your finished site on your phone or laptop, you see a polished food bank homepage with a bold green hero section, scrollable content blocks for services and volunteer roles, a working contact form, and a hamburger menu that slides open on mobile.
By the end of this project, you'll have:
- A live, responsive website at a public Netlify URL that you can share with anyone, featuring a green and gold color palette, a full-height hero section, impact statistics, service cards built with CSS Grid, and a sticky navigation bar with smooth scrolling.
- A working contact form powered by Netlify Forms that collects real visitor submissions you can view in a dashboard, with no backend code required.
- A hamburger navigation menu built with JavaScript that appears on mobile screens, slides open on tap, and closes automatically when a link is selected or the page scrolls.
- Secret Mission: Add a scroll-triggered counting animation that makes the impact statistics count up from zero when visitors scroll to them.
Are there any prerequisites?
You should be comfortable with HTML, CSS, and JavaScript fundamentals. This project also uses VS Code as the code editor. If you do not have it installed yet, Step 1 walks you through setting everything up.
Before We Start
Before we dive in, let's lock in what you're about to build and why it matters.
Set Up Your Project and Create the HTML Structure
Every website starts with its skeleton. Before any colors, layouts, or interactions, you need the raw HTML structure that defines what content appears on the page and in what order.
In this step, you will create the project folder, set up three files, and write the complete HTML for every section of the Adejumo Food Bank website. By the end, you will have an ugly but content-complete page open in your browser.
In this step, get ready to:
- Create the project folder and files.
- Write the complete HTML structure for every section of the site.
- Preview the unstyled page in your browser.
Create the project folder and files
You need a dedicated folder to hold all three files that make up this website: one for HTML content, one for styles, and one for behavior.
- Open your terminal. Press Cmd+Space (macOS) or the Windows key (Windows) to open your search bar.
- Type Terminal (macOS) or PowerShell (Windows) and press Enter to open it.
- Move to your Desktop by running this command:
cd ~/Desktop
- Create your project folder and move into it by running these commands:
mkdir adejumo-food-bank
cd adejumo-food-bank
- Create the three project files by running this command:
touch index.html style.css script.js
- Confirm the files exist by running:
ls
- You should see index.html, style.css, and script.js listed in the output.
Don't see the three files?
Make sure you ran cd adejumo-food-bank before running touch. If you are in the wrong folder, the files were created elsewhere. Delete them and start again from the cd ~/Desktop step.
On Windows, if touch is not recognized, run New-Item index.html, style.css, script.js instead.
Need more help? Help me troubleshoot my project files
Now open the project folder in VS Code so you can start editing files.
- Switch to VS Code.
- Click File in the top menu bar.
- Click Open Folder.
- Navigate to your Desktop, select the adejumo-food-bank folder, and click Open.
- In the Explorer sidebar on the left, you should see all three files: index.html, style.css, and script.js.
Write the HTML structure
The HTML file defines all of the content and structure for the site. You will build it section by section, refreshing the browser after each piece to watch the page grow.
- Click on index.html in the Explorer sidebar to open the file.
- Start building the page by pasting the document head and header navigation into index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Adejumo Food Bank - Nourishing Our Community</title>
<meta name="description" content="Adejumo Food Bank provides food assistance, nutrition education, and emergency support to families in need. Get help, volunteer, or donate today.">
<link rel="stylesheet" href="style.css">
</head>
<body>
<header class="header" id="header">
<div class="container header-content">
<a href="#" class="logo">Adejumo<span>Food Bank</span></a>
<button class="hamburger" id="hamburger" aria-label="Toggle navigation menu" aria-expanded="false">
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
<span class="hamburger-line"></span>
</button>
<nav class="nav" id="nav">
<a href="#services" class="nav-link">Services</a>
<a href="#get-help" class="nav-link">Get Help</a>
<a href="#volunteer" class="nav-link">Volunteer</a>
<a href="#contact" class="nav-link">Contact</a>
<a href="#hero" class="nav-link nav-donate">Donate</a>
</nav>
</div>
</header>
What does this code do?
- The <meta name="viewport"> tag tells mobile browsers how to scale the page. Without it, phones render the desktop-width layout scaled down to a tiny size.
- The <button class="hamburger"> is a placeholder for the mobile menu toggle. It contains three <span> elements that will become the three horizontal lines of a hamburger icon once you add CSS in a later step.
- The aria-label and aria-expanded attributes on the button support accessibility. Screen readers use them to announce the button's purpose to visually impaired users.
- Each nav-link points to a section ID with href="#services" style anchors. Clicking a link will scroll directly to that section.
- Save index.html by pressing Cmd+S (macOS) or Ctrl+S (Windows).
- Open the file in your browser. In Finder (macOS) or File Explorer (Windows), navigate to the adejumo-food-bank folder on your Desktop and double-click index.html.
- You should see the navigation text (Adejumo Food Bank, Services, Get Help, Volunteer, Contact, and Donate) displayed as plain, unstyled text.
Seeing a blank page?
Check that you saved the file. Look for a white dot on the index.html tab in VS Code. A dot means unsaved changes.
Also confirm you opened index.html (not style.css or script.js) in the browser.
Still stuck? Help me figure out why my HTML page is blank
The header is in place. Now add the hero section and impact statistics below it.
- In index.html, place your cursor at the end of the </header> line and press Enter twice to leave a blank line.
- Paste the hero and stats sections below:
<main>
<section class="hero" id="hero">
<div class="container hero-content">
<h1>Nourishing Our Community,<br>One Meal at a Time</h1>
<p class="hero-subtitle">Adejumo Food Bank provides nutritious food, education, and support to families facing hunger. Together, we can make a difference.</p>
<a href="#contact" class="btn btn-primary">Donate Now</a>
</div>
</section>
<section class="stats" id="stats">
<div class="container stats-grid">
<div class="stat-card">
<span class="stat-number" data-target="50000">50,000</span>
<span class="stat-label">Meals Served</span>
</div>
<div class="stat-card">
<span class="stat-number" data-target="2500">2,500</span>
<span class="stat-label">Families Helped</span>
</div>
<div class="stat-card">
<span class="stat-number" data-target="300">300</span>
<span class="stat-label">Active Volunteers</span>
</div>
<div class="stat-card">
<span class="stat-number" data-target="15">15</span>
<span class="stat-label">Years of Service</span>
</div>
</div>
</section>
What's happening here?
- The <main> tag wraps all the primary content of the page. It is a semantic HTML5 element that tells browsers and screen readers where the main content begins.
- The hero section has a bold heading, a supporting paragraph, and a "Donate Now" call-to-action button that links to the contact form.
- Each .stat-number has a data-target attribute holding the final number (e.g. 50000). The displayed text shows the formatted version. These attributes will power a counting animation later.
- Save index.html and refresh your browser.
- You should see the hero heading "Nourishing Our Community, One Meal at a Time" and the four statistics (50,000 Meals Served, 2,500 Families Helped, 300 Active Volunteers, 15 Years of Service) below the nav links.
Next, add the three content sections that describe what the food bank does, how to get help, and how to volunteer.
- Below the closing </section> tag of the stats section, paste the services section:
<section class="services" id="services">
<div class="container">
<h2 class="section-title">Our Services</h2>
<p class="section-subtitle">We offer a range of programs to support individuals and families in our community.</p>
<div class="services-grid">
<div class="service-card">
<div class="service-icon">🍲</div>
<h3>Food Distribution</h3>
<p>Weekly distribution of fresh produce, pantry staples, and nutritious meals to individuals and families in need.</p>
</div>
<div class="service-card">
<div class="service-icon">📚</div>
<h3>Nutrition Education</h3>
<p>Free workshops on meal planning, healthy cooking on a budget, and making the most of the food you receive.</p>
</div>
<div class="service-card">
<div class="service-icon">❤</div>
<h3>Emergency Assistance</h3>
<p>Immediate food support for families facing crisis situations, including natural disasters and sudden income loss.</p>
</div>
</div>
</div>
</section>
What are those number codes?
The 🍲 values are HTML character entities. They render as emoji icons in the browser without needing image files. This keeps the site lightweight and fast.
- Save index.html and refresh your browser. You should see the "Our Services" heading and three service descriptions appear below the stats.
- Below the services section, paste the Get Help section:
<section class="get-help" id="get-help">
<div class="container">
<h2 class="section-title">Get Help</h2>
<p class="section-subtitle">Everyone is welcome. No documentation required for your first visit.</p>
<div class="help-grid">
<div class="help-card">
<h3>Visit Us</h3>
<p><strong>Address:</strong> 123 Community Drive, Springfield</p>
<p><strong>Phone:</strong> (555) 012-3456</p>
<p><strong>Email:</strong> help@adejumofoodbank.org</p>
</div>
<div class="help-card">
<h3>Hours of Operation</h3>
<p><strong>Monday - Friday:</strong> 9:00 AM - 5:00 PM</p>
<p><strong>Saturday:</strong> 10:00 AM - 2:00 PM</p>
<p><strong>Sunday:</strong> Closed</p>
</div>
<div class="help-card">
<h3>Your First Visit</h3>
<p>Walk in any time during our open hours. A volunteer will greet you and guide you through our pantry. You can shop for the food your family needs, just like a grocery store. Bring your own bags if you can.</p>
</div>
</div>
</div>
</section>
What's in the Get Help section?
This section is the most important one for people who need food. It answers the three questions every visitor has: where is it, when is it open, and what do I do when I get there. The "no documentation required" subtitle removes a common barrier that stops people from seeking help.
- Save index.html and refresh your browser. The address, phone number, hours of operation, and first visit information now appear below the services.
New content not appearing?
Make sure you pasted the new code BELOW the previous section's closing </section> tag, not inside it. Each section is a sibling, not nested inside another.
Need help? Help me fix my HTML structure
Two more content sections to go. The volunteer section and contact form are the final pieces of the page body.
- Below the Get Help section, paste the volunteer section and the contact section heading:
<section class="volunteer" id="volunteer">
<div class="container">
<h2 class="section-title">Volunteer With Us</h2>
<p class="section-subtitle">Join our team of dedicated volunteers making a real difference in our community.</p>
<div class="volunteer-grid">
<div class="volunteer-role">
<h3>Food Sorting</h3>
<p>Help sort and organize donated food items in our warehouse. Perfect for groups and first-time volunteers.</p>
</div>
<div class="volunteer-role">
<h3>Distribution Helper</h3>
<p>Assist families during food distribution days. Greet visitors, pack bags, and help carry items to vehicles.</p>
</div>
<div class="volunteer-role">
<h3>Community Outreach</h3>
<p>Help us spread the word about our services at local events, schools, and community centers.</p>
</div>
</div>
<a href="#contact" class="btn btn-secondary">Sign Up to Volunteer</a>
</div>
</section>
<section class="contact" id="contact">
<div class="container">
<h2 class="section-title">Contact Us</h2>
<p class="section-subtitle">Have questions, want to donate, or ready to volunteer? Reach out to us.</p>
What does this code do?
The volunteer section lists three roles (Food Sorting, Distribution Helper, Community Outreach) with a "Sign Up to Volunteer" button that links to the contact form below. The contact section heading opens the final content area, which you will fill with a form in the next chunk.
- Save index.html and refresh your browser. You should see the three volunteer roles, the "Sign Up to Volunteer" button, and the "Contact Us" heading.
Now add the contact form. This is the most complex piece of HTML because it includes special attributes that let Netlify Forms process submissions without any backend code.
- Directly below the section-subtitle paragraph you just pasted, add the contact form and section closings:
<form name="contact" method="POST" data-netlify="true" netlify-honeypot="bot-field" class="contact-form">
<input type="hidden" name="form-name" value="contact">
<p class="hidden">
<label>Do not fill this out: <input name="bot-field"></label>
</p>
<div class="form-group">
<label for="name">Your Name</label>
<input type="text" id="name" name="name" required>
</div>
<div class="form-group">
<label for="email">Your Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="subject">Subject</label>
<select id="subject" name="subject">
<option value="general">General Inquiry</option>
<option value="donate">I Want to Donate</option>
<option value="volunteer">I Want to Volunteer</option>
<option value="help">I Need Help</option>
</select>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea id="message" name="message" rows="5" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Send Message</button>
</form>
</div>
</section>
Why these special form attributes?
- data-netlify="true" tells Netlify to automatically detect this form and start collecting submissions when the site is deployed. No server-side code needed.
- netlify-honeypot="bot-field" is a spam filter. The hidden bot-field input is invisible to humans but bots fill it out. Any submission with that field filled is discarded as spam.
- The hidden <input type="hidden" name="form-name" value="contact"> helps Netlify reliably identify which form sent the data.
- Save index.html and refresh your browser. You should see a form with fields for name, email, a subject dropdown, a message textarea, and a "Send Message" button.
Form fields not visible?
Check that you pasted the form code inside the <section class="contact"> wrapper, directly below the section-subtitle paragraph. If the form appears above the contact heading, you pasted it in the wrong location.
Need help? Help me fix my contact form placement
One last piece. The footer closes out the page and links back to the CSS and JavaScript files.
- Below the closing </section> tag of the contact section, paste the footer and closing tags:
</main>
<footer class="footer">
<div class="container footer-content">
<div class="footer-section">
<h4>Adejumo Food Bank</h4>
<p>Nourishing our community, one meal at a time. Together, we can end hunger.</p>
</div>
<div class="footer-section">
<h4>Quick Links</h4>
<a href="#services">Services</a>
<a href="#get-help">Get Help</a>
<a href="#volunteer">Volunteer</a>
<a href="#contact">Contact</a>
</div>
<div class="footer-section">
<h4>Contact Info</h4>
<p>123 Community Drive, Springfield</p>
<p>(555) 012-3456</p>
<p>help@adejumofoodbank.org</p>
</div>
</div>
<div class="footer-bottom">
<div class="container">
<p>© 2026 Adejumo Food Bank. All rights reserved.</p>
</div>
</div>
</footer>
<script src="script.js"></script>
</body>
</html>
What does this code do?
- </main> closes the main content area you opened with the hero section.
- The footer has three columns: a tagline, quick links that mirror the nav bar, and the contact info repeated for easy reference.
- <script src="script.js"></script> links the JavaScript file. It sits at the bottom of <body> so the HTML elements load before the script tries to interact with them.
- Save index.html and refresh your browser. Scroll to the bottom of the page. You should see the footer with three columns (tagline, Quick Links, Contact Info) and the copyright line.
Page looks incomplete or has missing content?
Right-click the page in your browser and select View Page Source. Scroll through the source and look for any line that appears cut off or missing a closing tag. A missing </div> or </section> can cause entire sections to disappear.
Need help? Help me find the missing HTML in my page
✔️ Awesome, I've got everything!
Great. Double check you have saved index.html and move on to the final preview below.
ⓧ I'd like to double check the full code
Your index.html should contain these sections in order. Scroll up and confirm each one is present:
- Document head (<head>) with meta tags and the style.css link.
- Header with .logo, .hamburger button, and five .nav-link anchors.
- Hero section (#hero) with heading, subtitle, and Donate Now button.
- Stats section (#stats) with four .stat-card elements, each with a data-target attribute.
- Services section (#services) with three .service-card elements.
- Get Help section (#get-help) with three .help-card elements.
- Volunteer section (#volunteer) with three .volunteer-role elements and a Sign Up button.
- Contact section (#contact) with a form containing data-netlify="true", a hidden bot-field input, and four form fields.
- Footer with three .footer-section columns and a .footer-bottom copyright bar.
- A <script src="script.js"> tag just before </body>.
Preview the unstyled page
You have been watching the page grow section by section. Before you move on, scroll through the entire page one final time to confirm everything is there.
- Before you scroll, predict: how many distinct content sections should you be able to count between the header and the footer?
- Refresh the browser and scroll from top to bottom.
You should count six sections: Hero, Stats, Our Services, Get Help, Volunteer With Us, and Contact Us. All the Adejumo Food Bank content is on the page, displayed as plain unstyled text. The page looks like a raw document with no colors, no layout, and no spacing. That is exactly right.
Why does it look so plain?
HTML defines the content and structure of a page. CSS defines how it looks. You linked style.css in the <head>, but the file is still empty. Once you add styles in the next step, this wall of text transforms into a professional-looking website.
Your HTML skeleton is complete. All six sections, the navigation, the form, and the footer are in place. Next up, you will transform this plain text into a polished, professional website by adding the green and beige color palette and full desktop styling with CSS.
Style the Desktop Layout with CSS
In the last step, you built the complete HTML structure for the Adejumo Food Bank website. Every section is in place, from the hero all the way down to the footer.
Right now though, it looks like a plain text document with no styling at all. You need to transform it into a polished, professional site using the food bank's green, beige, and gold color palette. You'll build the entire desktop layout in style.css using CSS custom properties for consistent theming and CSS Grid for the multi-column layouts.
In this step, get ready to:
- Define CSS custom properties and base styles for the site's color palette and typography.
- Style the hero section, content areas, and card layouts for the desktop view.
- Style the contact form inputs and the footer.
Define CSS custom properties and base styles
CSS custom properties let you define your color palette once and reuse those values everywhere. This keeps the entire site visually consistent without remembering hex codes.
- Open style.css in VS Code and add the color palette, reset, and body styles by pasting this code:
/* Color palette and design tokens */
:root {
--color-primary: #2D5F2D;
--color-primary-dark: #1E3F1E;
--color-primary-light: #4A8B4A;
--color-secondary: #F5F0E8;
--color-accent: #C8963E;
--color-accent-hover: #B07D2E;
--color-text: #2C2C2C;
--color-text-light: #6B6B6B;
--color-white: #FFFFFF;
--color-border: #E0D8CC;
--font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
--container-width: 1100px;
--header-height: 70px;
}
/* Reset default browser spacing */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: var(--font-family);
color: var(--color-text);
line-height: 1.6;
background-color: var(--color-secondary);
}
What does this code do?
- :root defines CSS custom properties (variables) for the entire site. Deep green (#2D5F2D) is the primary color, beige (#F5F0E8) is the background, and warm gold (#C8963E) draws attention to buttons and call-to-action elements.
- The * reset removes default margins and padding so every browser starts from the same baseline.
- The body rule applies the warm beige background and sets the site-wide font using var(--font-family) so you reference the variable instead of repeating the font stack.
- Save style.css and refresh your browser.
- The page background changes from white to a warm beige, and the text font shifts to Segoe UI.
Page still looks the same?
- Open index.html and confirm the <link rel="stylesheet" href="style.css"> tag is in the <head>. Without it, the browser cannot find your CSS file.
- Make sure you saved style.css (look for the dot on the tab in VS Code) and that the file sits in the same folder as index.html.
- Try a hard refresh with Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows) to clear the browser cache.
Help me debug why my CSS file is not loading in the browser.
- Below the body rule, add the layout helpers and sticky header styles:
html {
scroll-behavior: smooth;
}
/* Centered content wrapper */
.container {
max-width: var(--container-width);
margin: 0 auto;
padding: 0 20px;
}
.hidden {
display: none;
}
/* Sticky header pinned to the top */
.header {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: var(--color-primary);
z-index: 1000;
height: var(--header-height);
display: flex;
align-items: center;
}
.header-content {
display: flex;
justify-content: space-between;
align-items: center;
}
What does this code do?
- scroll-behavior: smooth makes anchor links (like clicking "Services" in the nav) scroll smoothly instead of jumping.
- .container centers content and caps it at 1100px wide so text lines stay readable on large monitors.
- position: fixed on .header locks the navigation bar to the top of the viewport so it stays visible as visitors scroll.
- Save style.css and refresh your browser.
- A deep green header bar now sits at the very top of the page. It stays fixed as you scroll.
- Below the .header-content rule, add the logo and navigation link styles:
/* Logo and navigation links */
.logo {
font-size: 1.5rem;
font-weight: 700;
color: var(--color-white);
text-decoration: none;
}
.logo span {
color: var(--color-accent);
margin-left: 6px;
}
.nav {
display: flex;
align-items: center;
gap: 24px;
}
.nav-link {
color: var(--color-secondary);
text-decoration: none;
font-size: 0.95rem;
font-weight: 500;
transition: color 0.3s;
}
.nav-link:hover {
color: var(--color-accent);
}
What does this code do?
- .logo span targets the "Food Bank" text inside the logo and colors it gold, creating a two-tone brand name.
- .nav uses Flexbox with gap: 24px to evenly space the links in a horizontal row without margins.
- Save style.css and refresh. The header now shows "Adejumo" in white and "Food Bank" in gold on the left, with beige navigation links on the right.
- Add the donate button and hamburger menu icon styles below .nav-link:hover:
/* Gold donate button in the nav */
.nav-donate {
background-color: var(--color-accent);
color: var(--color-white);
padding: 8px 20px;
border-radius: 25px;
font-weight: 600;
transition: background-color 0.3s;
}
.nav-donate:hover {
background-color: var(--color-accent-hover);
color: var(--color-white);
}
/* Hamburger icon, hidden on desktop */
.hamburger {
display: none;
background: none;
border: none;
cursor: pointer;
padding: 4px;
flex-direction: column;
gap: 5px;
}
.hamburger-line {
display: block;
width: 25px;
height: 3px;
background-color: var(--color-white);
border-radius: 3px;
transition: transform 0.3s, opacity 0.3s;
}
What does this code do?
- .nav-donate turns the Donate link into a rounded gold pill-shaped button that stands out from the other nav links.
- .hamburger is set to display: none so it is invisible on desktop. You will make it appear on mobile screens in a later step.
- Save and refresh. The Donate link in the header is now a rounded gold button. The hamburger icon is hidden on desktop, which is exactly what you want.
Style the hero and content sections
The header looks great. Now you need to transform the main content areas into a polished layout with a full-viewport hero, impact stats, and organized card grids.
- Add the hero section styles below the .hamburger-line rule:
/* Full-viewport hero with green gradient */
.hero {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
text-align: center;
background: linear-gradient(135deg, var(--color-primary-dark) 0%, var(--color-primary) 50%, var(--color-primary-light) 100%);
padding: 120px 20px 80px;
}
.hero-content {
max-width: 700px;
}
.hero h1 {
font-size: 3rem;
color: var(--color-white);
margin-bottom: 20px;
line-height: 1.2;
}
.hero-subtitle {
font-size: 1.15rem;
color: var(--color-secondary);
margin-bottom: 32px;
line-height: 1.7;
}
What does this code do?
- min-height: 100vh makes the hero fill the entire browser viewport so the mission statement commands the screen before visitors scroll.
- The linear-gradient blends three shades of green at a 135-degree angle, giving the hero visual depth instead of a flat color.
- Save and refresh. The hero section now fills the entire screen with a rich green gradient, large white heading text, and the mission statement in beige.
- Add the reusable button styles that apply to both the "Donate Now" and "Sign Up to Volunteer" buttons:
/* Reusable button styles */
.btn {
display: inline-block;
padding: 14px 36px;
font-size: 1rem;
font-weight: 600;
border-radius: 30px;
text-decoration: none;
cursor: pointer;
border: none;
transition: background-color 0.3s, transform 0.2s;
}
.btn:hover {
transform: translateY(-2px);
}
.btn-primary {
background-color: var(--color-accent);
color: var(--color-white);
}
.btn-primary:hover {
background-color: var(--color-accent-hover);
}
.btn-secondary {
background-color: var(--color-primary);
color: var(--color-white);
}
.btn-secondary:hover {
background-color: var(--color-primary-dark);
}
What does this code do?
- .btn is the shared base style. All buttons get rounded corners, padding, and a subtle lift on hover from translateY(-2px).
- .btn-primary uses the warm gold accent for high-priority actions like donating. .btn-secondary uses the primary green for lower-priority actions like volunteering.
- Save and refresh. The "Donate Now" button in the hero is now a large gold pill shape. Scroll down and the "Sign Up to Volunteer" button appears in green.
- Add the impact stats bar and section heading styles:
/* Impact stats bar */
.stats {
background-color: var(--color-primary-dark);
padding: 50px 20px;
}
.stats-grid {
display: flex;
justify-content: space-around;
gap: 20px;
}
.stat-card {
text-align: center;
}
.stat-number {
display: block;
font-size: 2.5rem;
font-weight: 700;
color: var(--color-accent);
}
.stat-label {
display: block;
font-size: 0.95rem;
color: var(--color-secondary);
margin-top: 6px;
}
/* Reusable section headings */
.section-title {
font-size: 2rem;
color: var(--color-primary-dark);
text-align: center;
margin-bottom: 10px;
}
What does this code do?
- The stats bar uses the darkest green background with gold numbers to create visual contrast that draws the eye to the food bank's impact.
- .section-title is a reusable class that styles every section heading the same way, keeping the page visually consistent.
- Save and refresh. A dark green bar with large gold numbers (50,000 meals, 2,500 families, etc.) appears below the hero. Section headings like "Our Services" are now centered and styled.
- Add the section subtitle styling, the services section layout, and the service card structure:
.section-subtitle {
text-align: center;
color: var(--color-text-light);
margin-bottom: 40px;
max-width: 600px;
margin-left: auto;
margin-right: auto;
}
/* Services 3-column card grid */
.services {
padding: 80px 20px;
background-color: var(--color-white);
}
.services-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
}
.service-card {
background-color: var(--color-secondary);
padding: 30px;
border-radius: 12px;
text-align: center;
border: 1px solid var(--color-border);
transition: transform 0.3s;
}
.service-card:hover {
transform: translateY(-4px);
}
.service-icon {
font-size: 2.5rem;
margin-bottom: 16px;
}
What does this code do?
- grid-template-columns: repeat(3, 1fr) creates three equal-width columns. CSS Grid handles the math so each card gets exactly one-third of the available space.
- The transition on .service-card pairs with the :hover lift effect so cards smoothly rise when the visitor hovers over them.
- Save and refresh. The services section now has a white background with three beige cards in a row. Hover over a card and watch it lift slightly.
Cards stacking vertically instead of side by side?
Double check that .services-grid has display: grid and grid-template-columns: repeat(3, 1fr). A missing or misspelled property causes the grid to fall back to a single column.
Help me debug why my CSS Grid cards are stacking instead of displaying in a row.
- Add the service card text styles and the entire Get Help section:
/* Service card text and Get Help section */
.service-card h3 {
font-size: 1.25rem;
color: var(--color-primary-dark);
margin-bottom: 10px;
}
.service-card p {
color: var(--color-text-light);
font-size: 0.95rem;
}
.get-help {
padding: 80px 20px;
background-color: var(--color-secondary);
}
.help-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
}
.help-card {
background-color: var(--color-white);
padding: 30px;
border-radius: 12px;
border-left: 4px solid var(--color-primary);
}
.help-card h3 {
font-size: 1.2rem;
color: var(--color-primary-dark);
margin-bottom: 12px;
}
.help-card p {
color: var(--color-text);
margin-bottom: 8px;
font-size: 0.95rem;
}
What does this code do?
- The service card headings get dark green text to match the site's branding. The description text uses the lighter gray for comfortable readability.
- Each .help-card has a border-left: 4px solid green accent stripe that visually groups each block of info (location, hours, first visit) as a distinct card.
- Save and refresh. Service card headings and descriptions are now properly styled. Scroll to the Get Help section to see three white info cards with green left borders showing address, hours, and first visit details.
- Add the volunteer section styles:
/* Volunteer section */
.volunteer {
padding: 80px 20px;
background-color: var(--color-white);
text-align: center;
}
.volunteer-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 30px;
margin-bottom: 40px;
}
.volunteer-role {
padding: 24px;
background-color: var(--color-secondary);
border-radius: 12px;
text-align: left;
border: 1px solid var(--color-border);
}
.volunteer-role h3 {
color: var(--color-primary-dark);
margin-bottom: 8px;
}
.volunteer-role p {
color: var(--color-text-light);
font-size: 0.95rem;
}
What does this code do?
The volunteer section uses the same 3-column grid pattern as the services section. The section itself is center-aligned, but each role card switches to text-align: left so the role descriptions read naturally.
- Save and refresh. Three volunteer role cards (Food Sorting, Distribution Helper, Community Outreach) appear in a row with a green "Sign Up to Volunteer" button below them.
Style the contact form and footer
The content sections are looking great. The last two pieces are the contact form and the footer.
- Add the contact section container and label styles:
/* Contact section and form container */
.contact {
padding: 80px 20px;
background-color: var(--color-secondary);
}
.contact-form {
max-width: 600px;
margin: 0 auto;
background-color: var(--color-white);
padding: 40px;
border-radius: 12px;
border: 1px solid var(--color-border);
}
.form-group {
margin-bottom: 20px;
}
.form-group label {
display: block;
font-weight: 600;
margin-bottom: 6px;
color: var(--color-primary-dark);
}
What does this code do?
.contact-form wraps the form in a centered white card with rounded corners, making it stand out from the beige background. The labels are bold and dark green to match the site's branding.
- Save and refresh. The contact form now sits inside a white card with dark green labels above each field.
- Add the form input and focus state styles:
/* Form field appearance and focus highlight */
.form-group input,
.form-group select,
.form-group textarea {
width: 100%;
padding: 12px 16px;
border: 1px solid var(--color-border);
border-radius: 8px;
font-family: var(--font-family);
font-size: 1rem;
color: var(--color-text);
background-color: var(--color-secondary);
transition: border-color 0.3s;
}
.form-group input:focus,
.form-group select:focus,
.form-group textarea:focus {
outline: none;
border-color: var(--color-primary);
}
What does this code do?
- The multi-selector targets all three input types (input, select, textarea) at once so they share the same rounded, beige styling.
- The :focus rules replace the browser's default blue outline with a green border that matches the site's color palette.
- Save and refresh. The form inputs now have rounded corners and beige backgrounds.
- Click inside one of the input fields. The border turns green to show focus.
- Add the footer layout and text styles:
/* Footer with 3-column layout */
.footer {
background-color: var(--color-primary-dark);
padding: 60px 20px 0;
color: var(--color-secondary);
}
.footer-content {
display: grid;
grid-template-columns: 2fr 1fr 1fr;
gap: 40px;
padding-bottom: 40px;
border-bottom: 1px solid var(--color-primary);
}
.footer-section h4 {
color: var(--color-white);
margin-bottom: 16px;
font-size: 1.1rem;
}
.footer-section p {
font-size: 0.9rem;
margin-bottom: 8px;
color: var(--color-secondary);
}
What does this code do?
grid-template-columns: 2fr 1fr 1fr gives the first column (the food bank description) twice the width of the Quick Links and Contact Info columns. This mirrors common footer layouts where the brand statement gets the most space.
- Save and refresh. Scroll to the bottom to see a dark green footer with three columns for the description, quick links, and contact info.
- Add the footer link and copyright bar styles to complete the stylesheet:
/* Footer links and copyright bar */
.footer-section a {
display: block;
color: var(--color-secondary);
text-decoration: none;
font-size: 0.9rem;
margin-bottom: 8px;
transition: color 0.3s;
}
.footer-section a:hover {
color: var(--color-accent);
}
.footer-bottom {
padding: 20px 0;
text-align: center;
}
.footer-bottom p {
font-size: 0.85rem;
color: var(--color-primary-light);
}
What does this code do?
Footer links are styled as block elements so they stack vertically in the Quick Links column. On hover, they turn gold to match the accent color. The copyright bar sits below a subtle green divider line.
- Save style.css and refresh. Hover over a footer link and it turns gold. The "2026 Adejumo Food Bank" copyright text sits at the bottom.
Some sections still look unstyled?
- Open DevTools (F12) and inspect the unstyled element. If you see the correct class name in the HTML but no matching CSS rule, you may have a typo in the selector name in style.css.
- Check that every code block you pasted went below the previous one. CSS rules that accidentally land inside another rule's curly braces will not work.
Help me figure out why some of my CSS styles are not applying.
✔️ Awesome, I've got everything!
Great. Make sure you have saved style.css before moving on.
ⓧ I'd like to double check the full code
Your style.css is too long to show in one block. Scroll up through this step and confirm each code block is present in your file, in this order:
- :root custom properties, * reset, and body styles.
- html, .container, .hidden, .header, and .header-content.
- .logo, .nav, .nav-link, and .nav-link:hover.
- .nav-donate, .hamburger, and .hamburger-line.
- .hero, .hero-content, .hero h1, and .hero-subtitle.
- All .btn styles (primary, secondary, and hover variants).
- .stats bar styles and .section-title.
- .section-subtitle, .services layout, and .service-card structure.
- .service-card text styles and the entire .get-help section.
- .volunteer section styles.
- .contact section, .contact-form, and .form-group label.
- .form-group input/select/textarea and :focus styles.
- .footer layout and .footer-section text styles.
- .footer-section a links and .footer-bottom copyright bar.
Before you scroll through the whole page, what do you expect the site to look like from top to bottom?
Scroll through the entire page at full desktop width. You should see a green sticky header with a gold Donate button, a full-viewport hero with a green gradient, a dark stats bar with gold numbers, three service cards in a row, three Get Help info cards with green left borders, three volunteer role cards, a styled contact form in a white card, and a dark green footer with three columns.
The desktop layout is looking polished and professional. Next up, you will check what happens when someone visits this site on a phone.
Check Mobile and Discover It's Broken
Your food bank site is styled and looking professional at full desktop width. But there is one critical audience you have not tested for yet.
Most food bank visitors browse on their phones, not on a wide desktop monitor. In this step, you will use your browser's Developer Tools to preview the site on a phone-sized screen and discover what breaks.
In this step, get ready to:
- Open Developer Tools and switch to a mobile device view.
- Scroll through the entire site and identify every layout issue.
Open DevTools and switch to mobile view
What are Developer Tools?
Developer Tools (DevTools) is a panel built into Chrome and Edge that lets you inspect and debug web pages. It includes a device toolbar that simulates different screen sizes, so you can test how your site looks on phones and tablets without needing a physical device.
Think about what you built so far. The services, get help, and volunteer sections all use three-column grids. The stats section lays four cards in a horizontal row. What do you think these layouts will look like when the screen shrinks to just 375 pixels wide?
- Switch back to your browser tab with the Adejumo Food Bank site.
- Press F12 to open the Developer Tools panel.
- Click the device toggle toolbar button in the top-left area of the DevTools panel (it looks like a phone next to a tablet icon). You can also press Cmd+Shift+M (macOS) or Ctrl+Shift+M (Windows).
- In the device dropdown at the top of the viewport, select iPhone 14 (or manually set the width to 375).
Don't see the device toolbar?
- Look for the small phone-and-tablet icon in the toolbar at the very top of the DevTools panel, between the inspect-element arrow and the Elements tab. When active, the icon turns blue.
- If F12 did not open DevTools, try pressing Fn+F12. Some keyboards require the Fn key for function keys.
- Help me open the device toolbar in Chrome DevTools.
Identify what is broken
The viewport is now simulating a phone screen. Look at the header and hero area visible on screen right now. Something is already wrong.
- Scroll slowly from the very top of the page to the bottom, paying attention to how each section handles the narrow screen.
What should I see?
The site is broken. Here is what you should notice as you scroll down:
- The header navigation links are crammed together or overflowing off the right side of the screen. On a real phone, visitors would not be able to tap the correct link.
- The hero heading is far too large for 375px. The text wraps awkwardly or gets cut off because the font size (3rem) was designed for a wide screen.
- The impact stats row tries to fit all four cards side by side in a narrow horizontal line, squishing the numbers together.
- The services, get help, and volunteer sections are still rendering as three-column grids. Each card is unreadably narrow or pushed off-screen.
- The contact form padding takes up too much of the narrow viewport, leaving very little room for the actual input fields.
- The footer's three-column grid collapses into a jumbled layout.
This is the gap. Your CSS has detailed rules for how every section should look, but zero instructions for what to do when the screen gets small.
Why does this happen?
CSS Grid and Flexbox lay content out exactly as you tell them to. When you write grid-template-columns: repeat(3, 1fr), the browser creates three columns no matter how wide the screen is.
Without media queries telling the browser to switch to a single column on small screens, the layout stays locked to the desktop design. That is exactly what you will fix in the next step.
Now you know exactly what is broken and why. In the next step, you will add responsive CSS and a JavaScript-powered hamburger menu to make every section look polished on phones, tablets, and desktops.
Fix the Layout with Responsive CSS and a Hamburger Menu
In the last step, you saw firsthand how the desktop layout falls apart on a phone-sized screen. Navigation links overflow, the hero text is far too large, and three-column grids jam together into an unreadable mess.
The fix is responsive CSS. A media query lets you write CSS rules that only kick in when the screen is below a certain width. In this step, you will add a media query to fix every broken section, then write JavaScript for a hamburger menu that replaces the desktop navigation on mobile.
In this step, get ready to:
- Add a CSS media query to stack layouts and scale text for mobile screens.
- Build a JavaScript-powered hamburger menu for mobile navigation.
- Test the responsive design across screen sizes from 320px to 1440px.
Add responsive CSS for the navigation
The @media (max-width: 768px) block you are about to write tells the browser: only apply these styles when the screen is 768 pixels wide or narrower. Every rule inside it overrides the desktop version on smaller screens.
- In style.css, scroll to the very bottom of the file.
- Add the start of a media query with the navigation rules by pasting this code at the end of the file:
/* Responsive */
@media (max-width: 768px) {
.hamburger {
display: flex;
}
/* Hide desktop nav, reposition as vertical dropdown */
.nav {
display: none;
position: fixed;
top: var(--header-height);
left: 0;
width: 100%;
background-color: var(--color-primary);
flex-direction: column;
padding: 20px;
gap: 16px;
border-top: 1px solid var(--color-primary-light);
}
/* JavaScript will toggle this class to show/hide */
.nav.nav-open {
display: flex;
}
.nav-link {
font-size: 1.1rem;
padding: 8px 0;
}
What does this code do?
- .hamburger { display: flex; } makes the hamburger button visible. It was hidden with display: none in the desktop styles.
- The .nav block hides the navigation links and repositions them as a full-width vertical panel that drops down from the header.
- .nav.nav-open is the class that JavaScript will add to reveal the menu. When both classes are present, the nav becomes visible.
- Save style.css.
- Refresh the page in your browser with DevTools still set to 375px mobile view.
- You should see three horizontal white lines (the hamburger icon) in the top right of the header. The desktop navigation links have disappeared.
Don't see the hamburger icon?
- Make sure your code is inside the @media (max-width: 768px) block and that you saved the file.
- Confirm your DevTools responsive view is set to 768px or narrower. At wider widths the desktop nav shows instead.
- Check that your .hamburger rule says display: flex, not display: block.
Still stuck? Ask for help.
Add the hamburger animation and hero scaling
The hamburger icon needs to animate into an X when the menu is open. The hero heading also needs to shrink so it fits a phone screen.
- Still inside the @media block in style.css, add the following rules directly below the .nav-link rule you just pasted:
.nav-donate {
text-align: center;
}
/* Animate hamburger lines into X when menu is open */
.hamburger.active .hamburger-line:nth-child(1) {
transform: translateY(8px) rotate(45deg);
}
.hamburger.active .hamburger-line:nth-child(2) {
opacity: 0;
}
.hamburger.active .hamburger-line:nth-child(3) {
transform: translateY(-8px) rotate(-45deg);
}
/* Scale down hero text for smaller screens */
.hero h1 {
font-size: 2rem;
}
.hero-subtitle {
font-size: 1rem;
}
What does this code do?
- The three .hamburger.active rules transform the three horizontal lines into an X shape. The top line rotates 45 degrees down, the middle line disappears, and the bottom line rotates 45 degrees up.
- The hero heading drops from 3rem to 2rem so it fits comfortably on a narrow screen without overflowing.
- Save style.css and refresh the mobile view.
- The hero heading is noticeably smaller now and fits on the screen without overflowing. The hamburger X animation will not work yet because you have not added the JavaScript.
Hero text still looks huge?
- Make sure the .hero h1 and .hero-subtitle rules are inside the @media block, not outside it.
- Verify that the DevTools responsive width is still set to 375px or narrower.
Still seeing oversized text? Ask for help.
Make the content sections stack on mobile
The three-column grids for services, help, and volunteers still overflow on mobile. You need to collapse them into a single column and adjust spacing for the stats, contact form, and footer.
- Continue adding rules inside the same @media block, directly below the .hero-subtitle rule. This chunk closes the @media block with a final } at the end:
/* Stack stats vertically */
.stats-grid {
flex-direction: column;
align-items: center;
gap: 24px;
}
.stat-number {
font-size: 2rem;
}
/* Collapse all content grids to single column */
.services-grid,
.help-grid,
.volunteer-grid {
grid-template-columns: 1fr;
}
.section-title {
font-size: 1.6rem;
}
/* Reduce padding for tighter mobile layout */
.contact-form {
padding: 24px;
}
.footer-content {
grid-template-columns: 1fr;
gap: 30px;
}
}
What does this code do?
- .stats-grid switches from a horizontal Flexbox row to a vertical column, stacking each stat card on top of the next.
- The combined .services-grid, .help-grid, .volunteer-grid rule collapses all three CSS Grid layouts from three columns to one column with a single declaration.
- The footer grid also goes to one column so the three footer sections stack vertically.
- Save style.css and refresh the mobile view.
- Scroll through the page at 375px. The impact statistics now stack vertically. Service cards, help cards, and volunteer roles each display in a single column. The contact form has tighter padding. The footer columns stack on top of each other.
Grids still showing three columns?
- Check for a missing closing } at the very end of your @media block. The block needs its own closing brace after all the responsive rules.
- Make sure the grid rule uses grid-template-columns: 1fr (with a lowercase fr), not 1FR or 1 alone.
Need more help? Ask here.
That covers all the responsive CSS. Let's double-check the new code you added.
✔️ Awesome, I've got everything!
Great. Make sure you have saved style.css before moving on.
ⓧ I'd like to double check the full code
The full style.css file is long, so scroll up and confirm the three code blocks you just added are present at the bottom of the file, in order:
- The @media (max-width: 768px) { opening with .hamburger, .nav, .nav.nav-open, and .nav-link rules.
- The .nav-donate, .hamburger.active animation rules, and .hero scaling rules.
- The .stats-grid, .services-grid/.help-grid/.volunteer-grid, .contact-form, and .footer-content rules, ending with a closing } for the @media block.
Build the hamburger menu with JavaScript
The CSS is ready, but the hamburger button does nothing when you click it. You need JavaScript to toggle the nav-open and active classes that your CSS is already watching for.
- Switch to script.js in VS Code. The file is currently empty.
- Add the hamburger toggle logic by pasting this code:
// Hamburger menu toggle
const hamburger = document.getElementById('hamburger');
const nav = document.getElementById('nav');
hamburger.addEventListener('click', function () {
const isOpen = nav.classList.toggle('nav-open');
hamburger.classList.toggle('active');
hamburger.setAttribute('aria-expanded', isOpen);
});
What does this code do?
- getElementById grabs references to the hamburger button and the nav element using the IDs you set in your HTML.
- On click, classList.toggle adds nav-open to the nav (making it visible) and active to the hamburger (triggering the X animation). Clicking again removes both classes, closing the menu.
- aria-expanded updates the accessibility attribute so screen readers know whether the menu is open or closed.
- Save script.js and refresh the mobile view at 375px.
- Click the hamburger icon. A vertical menu drops down from the header with all five navigation links (Services, Get Help, Volunteer, Contact, Donate).
- Click the hamburger again. The menu closes and the three lines return.
Hamburger click does nothing?
- Open the browser console (press F12 then click the Console tab) and check for red error messages. A typo in an element ID like hamburger or nav will cause a null reference error.
- Make sure the <script src="script.js"></script> tag is at the bottom of your index.html, just before </body>.
Still stuck? Ask for help.
The menu opens and closes, but there is a problem. If you tap a link like Services, the page scrolls to that section but the menu stays open, covering the content. You need handlers that close the menu automatically.
- In script.js, add the menu-closing handlers below the existing click handler:
// Close menu when a nav link is clicked
const navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(function (link) {
link.addEventListener('click', function () {
nav.classList.remove('nav-open');
hamburger.classList.remove('active');
hamburger.setAttribute('aria-expanded', 'false');
});
});
// Close menu on scroll
window.addEventListener('scroll', function () {
if (nav.classList.contains('nav-open')) {
nav.classList.remove('nav-open');
hamburger.classList.remove('active');
hamburger.setAttribute('aria-expanded', 'false');
}
});
What does this code do?
- The first handler loops through every .nav-link and attaches a click listener. When the user taps a link, it removes both nav-open and active, closing the menu before the page scrolls to the section.
- The scroll listener closes the menu whenever the user scrolls the page. This prevents the dropdown from staying open and blocking content while the user browses.
- Save script.js and refresh the mobile view.
- Open the hamburger menu and click Services. The menu closes and the page smooth-scrolls to the Services section.
Menu stays open after clicking a link?
- Make sure the class name in classList.remove('nav-open') matches the class name in your CSS exactly. A mismatch like navOpen versus nav-open will silently fail.
- Check that querySelectorAll('.nav-link') uses a dot before nav-link. Without the dot, no elements are selected.
Still stuck? Ask for help.
That completes the hamburger menu. Let's double-check the full script.js file.
✔️ Awesome, I've got everything!
Great. Make sure you have saved script.js before moving on.
ⓧ I'd like to double check the full code
Here is the complete script.js file. Yours should match exactly.
// Hamburger menu toggle
const hamburger = document.getElementById('hamburger');
const nav = document.getElementById('nav');
hamburger.addEventListener('click', function () {
const isOpen = nav.classList.toggle('nav-open');
hamburger.classList.toggle('active');
hamburger.setAttribute('aria-expanded', isOpen);
});
// Close menu when a nav link is clicked
const navLinks = document.querySelectorAll('.nav-link');
navLinks.forEach(function (link) {
link.addEventListener('click', function () {
nav.classList.remove('nav-open');
hamburger.classList.remove('active');
hamburger.setAttribute('aria-expanded', 'false');
});
});
// Close menu on scroll
window.addEventListener('scroll', function () {
if (nav.classList.contains('nav-open')) {
nav.classList.remove('nav-open');
hamburger.classList.remove('active');
hamburger.setAttribute('aria-expanded', 'false');
}
});
Test across screen sizes
The responsive CSS and hamburger menu are in place. Time to verify the site works at every width, not just 375px.
Before you start dragging, predict: what do you expect to see at 375px versus 1440px? At what point should the hamburger icon disappear and the desktop navigation return?
- In DevTools, drag the responsive width handle from 320px slowly up to 1440px.
- Watch for the breakpoint at 768px where the layout switches between mobile and desktop.
- At 375px, confirm the hamburger icon is visible, the menu opens and closes, all sections stack vertically, and text is readable.
- At 1440px, confirm the desktop navigation links are visible, the hamburger icon is hidden, and the three-column grids display side by side.
At 768px and below, the hamburger appears and all sections stack. Above 768px, the desktop layout returns smoothly. The site is fully responsive.
Your site now looks polished on every screen size, from a narrow phone to a wide desktop monitor. Next up, you will deploy it to a live URL so anyone in the world can visit it.
Deploy to Netlify and Test the Live Site
Your site is fully responsive and looks polished on every screen size. But right now, only you can see it on your own computer.
The whole point of building a food bank website is for real people to find and use it. In this step, you will deploy the site to Netlify, a free hosting platform that turns your local files into a live website in seconds. You will also test that the contact form collects real submissions without any backend code.
In this step, get ready to:
- Deploy the Adejumo Food Bank site to a live URL using Netlify's drag-and-drop.
- Verify that the contact form collects real submissions in the Netlify dashboard.
- Customize the site URL to a clean, memorable subdomain.
Create a Netlify account and deploy
Netlify lets you publish a static website by dragging a folder onto a web page. No terminal commands, no build tools, no server setup.
- Open your browser and go to the Netlify login page:
https://app.netlify.com/login
- Sign up for a free account if you do not have one. You can sign up with your email or with a GitHub, GitLab, or Bitbucket account.
- After signing in, go to the Netlify Drop page:
https://app.netlify.com/drop
- Open Finder (macOS) or File Explorer (Windows) and locate the adejumo-food-bank folder on your Desktop.
- Drag the entire adejumo-food-bank folder onto the Drop zone on the Netlify page.
- Wait for the deploy to finish. This typically takes 10 to 30 seconds.
Once the deploy completes, Netlify shows your project dashboard with a Preview URL ending in .netlify.app.
- Click the Preview URL to open your live site in a new tab.
You should see the full Adejumo Food Bank website loading. The green hero, styled sections, and footer should all appear just like they did locally.
What just happened?
Netlify uploaded your three files (index.html, style.css, script.js), assigned a random subdomain, and published the site to a live URL. Each production deploy costs 15 credits from your free monthly allowance of 300 credits.
Form submissions are free and unlimited on all credit-based plans, so testing the contact form costs nothing extra.
Site not loading?
- Make sure you dragged the adejumo-food-bank folder itself, not the individual files. Netlify needs the folder containing index.html at the top level.
- Check that your folder is under 50MB. Static HTML/CSS/JS sites are typically well under this limit.
- If your site appears but looks unstyled, confirm that style.css is in the same folder as index.html, not in a subfolder.
Why isn't my Netlify deployment loading?
Is your site showing as private?
On Netlify's credit-based plans, new projects may default to private. If you want others to access your site, check your project's visibility settings in the Netlify dashboard and set the project to public.
Confirm form detection and test the contact form
The data-netlify="true" attribute you added to the contact form tells Netlify to automatically detect and process submissions. No server or backend code is needed.
- In the Netlify dashboard, click on your deployed project to open its project dashboard.
- Click the Forms tab in the project navigation.
- Confirm that a form named contact appears in the Active forms list.
This confirms Netlify detected the data-netlify="true" attribute and the hidden form-name input in your HTML.
Form not detected?
- Confirm your <form> tag has name="contact", data-netlify="true", and netlify-honeypot="bot-field".
- Confirm your form includes a hidden input with name="form-name" and value="contact".
- Ensure form detection is enabled for your project, then redeploy by dragging the folder onto the Deploys page again.
Why isn't Netlify detecting my contact form?
Now test the form by submitting real data from the live site.
- Open your live site URL in a new browser tab.
- Scroll down to the Contact Us section.
- Enter Test User in the Your Name field.
- Enter test@example.com in the Your Email field.
- Select General Inquiry from the Subject dropdown.
- Enter This is a test submission. in the Message field.
- Click Send Message.
Netlify processes the submission. You may see a brief confirmation page.
- Go back to the Netlify dashboard.
- Click the Forms tab.
- Click the contact form.
- Look under Verified submissions for your test entry.
You should see a submission from Test User with the message you typed. This proves the contact form is working on the live site with zero backend code.
Customize the site URL
Netlify assigns a random subdomain when you first deploy. You can change this to something clean and memorable that matches the food bank name.
- Go to your project's Project Overview dashboard in Netlify.
- Select Customize, then choose Manage project name and cover image.
- Change the project name to something like adejumo-food-bank. This sets your site URL to adejumo-food-bank.netlify.app.
Name already taken?
If the subdomain is already in use by someone else, try adding your name or a number. For example, adejumo-food-bank-jane or adejumo-food-bank-2026.
- Note your new custom URL. It follows the pattern your-project-name.netlify.app.
Before you visit the new URL, do you think the site will look identical to how it looked locally? Think about whether anything might display differently on the live version.
- Open the new custom URL in your browser at full desktop width.
- Resize the browser window to a narrow width (or open DevTools mobile view) to check the mobile layout.
The site loads at your custom URL. The hero section, navigation, stats, services, get help, volunteer, contact form, and footer all display correctly. The hamburger menu works on mobile. The site looks identical to your local version because Netlify serves the same static files you built.
Site looks different from your local version?
- Try a hard refresh with Cmd+Shift+R (macOS) or Ctrl+Shift+R (Windows) to clear cached styles.
- Make sure all three files (index.html, style.css, script.js) are in the same folder you deployed. Missing files cause broken styles or scripts.
- If you changed the project name but the old URL still loads, wait a moment for the DNS to update and try again.
Why does my deployed Netlify site look different from my local version?
Secret mission
Add a Scroll-Triggered Counting Animation to Impact Stats
The impact statistics on your food bank site show impressive numbers, but they sit on the page like any other text. In this mission, you will make those numbers count up from zero when a visitor scrolls to them, using the Intersection Observer API and requestAnimationFrame to create a polished, professional effect.
Clean Up Your Resources
Clean Up Your Resources
Decide whether to keep your resources running, pause them to come back later, or delete them entirely. This project runs on the Netlify Free plan, so your site stays live at no cost as long as you stay within 300 credits per month.
Resources you used:
- Netlify project (your live site at .netlify.app).
- Local adejumo-food-bank folder containing index.html, style.css, and script.js.
Keep everything running
No action needed. Choose this if you are still actively building or want your site to stay live.
- Your site stays live at your Netlify URL for free indefinitely.
- Form submissions remain free and unlimited on the Free plan.
- Each time you re-deploy an update, it costs 15 credits out of your 300 monthly credits.
- Your local adejumo-food-bank folder stays on your Desktop for future edits.
Pause - I'll come back to this later
Take your site offline while keeping the project configuration intact so you can re-enable it later.
- In your Netlify dashboard, open your project.
- Go to Project configuration, then General, then scroll down to Danger zone.
- Select Disable project. This takes the site offline but keeps your configuration saved.
- When you are ready to resume, return to the same Danger zone section and select Enable project.
- Keep your local adejumo-food-bank folder on your Desktop so you can re-deploy later.
Delete - I don't want to use this again
Remove all project resources and start fresh. This is permanent and cannot be undone.
- In your Netlify dashboard, open your project.
- Go to Project configuration, then General, then scroll down to Danger zone.
- Look for the option to permanently delete the project and confirm the deletion when prompted.
- Delete your local project folder by running this command on macOS or Linux:
rm -rf ~/Desktop/adejumo-food-bank
- On Windows, run this command instead:
Remove-Item -Recurse -Force ~\Desktop\adejumo-food-bank
Nice Work!
Nice Work!
You just built and deployed a professional food bank website from scratch using HTML, CSS, and vanilla JavaScript. Anyone with the link can visit it on their phone or laptop and see a polished, real-world site that you designed and shipped.
You've learned how to:
- Build a complete, multi-section website with semantic HTML5, a cohesive CSS custom properties color palette, and layouts powered by CSS Grid and Flexbox.
- Experience first-hand how a desktop layout breaks on mobile, then fix it with responsive design using media queries and a JavaScript-powered hamburger menu.
- Deploy a live site to a public URL with Netlify's drag-and-drop deployment, and set up a working contact form using Netlify Forms that collects real submissions with no backend code.
- Secret Mission: Completed an optional Secret Mission to push your front-end skills further.
Ready to quiz yourself?