In 2026, the web continues to prioritize speed, accessibility, and device‑agnostic design. This guide walks you through creating a fully responsive, mobile‑first landing page using only Flexbox for layout and vanilla JavaScript for interactivity. No heavy frameworks, no bloat. By the end, you’ll have a clean, accessible site that looks great on phones, tablets, and desktops.
1. Project Setup & Folder Structure
Start with a clear project structure that keeps your files organized. It also makes future maintenance easier.
my-landing-page/
├─ index.html
├─ css/
│ └─ main.css
├─ js/
│ └─ main.js
└─ assets/
├─ images/
└─ fonts/
Use a lightweight local server like live-server or http-server to preview changes in real time.
2. Basic HTML Skeleton
Write semantic HTML from the start. It improves accessibility and SEO.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Landing Page – Mobile First</title>
<link rel="stylesheet" href="css/main.css">
</head>
<body>
<header>
<nav>
<button id="navToggle" aria-label="Open navigation menu">☰</button>
<ul id="navMenu">
<li><a href="#hero">Home</a></li>
<li><a href="#features">Features</a></li>
<li><a href="#cta">Get Started</a></li>
</ul>
</nav>
</header>
<section id="hero" class="hero">
<div class="hero-content">
<h1>Welcome to Your Future Site</h1>
<p>Build fast, responsive, and accessible landing pages with zero frameworks.</p>
<a href="#cta" class="btn">Learn More</a>
</div>
</section>
<section id="features" class="features">
<h2>Key Features</h2>
<div class="cards">
<article class="card">
<h3>Flexbox Layout</h3>
<p>Arrange elements effortlessly with CSS Flexbox…</p>
</article>
<article class="card">
<h3>Vanilla JS Interactivity</h3>
<p>Add dynamic behavior without any libraries…</p>
</article>
<article class="card">
<h3>Accessibility First</h3>
<p>Make your site usable for everyone…</p>
</article>
</div>
</section>
<section id="cta" class="cta">
<h2>Ready to Get Started?</h2>
<button class="btn">Get Started Now</button>
</section>
<footer>
<p>© 2026 My Landing Page. All rights reserved.</p>
</footer>
<script src="js/main.js" defer></script>
</body>
</html>
3. Mobile‑First CSS with Flexbox
Begin with a small‑screen style sheet. Gradually add breakpoints as needed.
/* css/main.css */
/* Reset & Base Styles */
*, *::before, *::after { box-sizing: border-box; }
html { font-size: 100%; }
body {
margin: 0;
font-family: system-ui, sans-serif;
line-height: 1.6;
color: #222;
}
/* Typography – responsive with clamp() */
h1, h2, h3 { line-height: 1.2; }
h1 { font-size: clamp(2.5rem, 5vw, 3.5rem); }
h2 { font-size: clamp(2rem, 4vw, 3rem); }
h3 { font-size: clamp(1.5rem, 3vw, 2.5rem); }
p { font-size: clamp(1rem, 2.5vw, 1.25rem); }
/* Flexbox Layout */
header, .hero, .features, .cta, footer { display: flex; flex-direction: column; align-items: center; }
header { padding: 1rem; background: #fff; position: sticky; top: 0; z-index: 10; }
header nav { width: 100%; display: flex; justify-content: space-between; align-items: center; }
#navMenu { list-style: none; display: flex; gap: 1rem; margin: 0; }
#navMenu li a { text-decoration: none; color: #333; }
/* Hero Section */
.hero { background: url('assets/images/hero.jpg') center/cover no-repeat; height: 80vh; justify-content: center; color: #fff; text-align: center; }
.hero-content { background: rgba(0,0,0,0.5); padding: 2rem; border-radius: 0.5rem; }
/* Feature Cards */
.cards { display: flex; flex-wrap: wrap; gap: 1.5rem; justify-content: center; width: 100%; max-width: 1200px; padding: 2rem; }
.card { flex: 1 1 250px; background: #f9f9f9; padding: 1.5rem; border-radius: 0.5rem; text-align: center; }
/* Call‑to‑Action */
.cta { background: #0044cc; color: #fff; width: 100%; padding: 3rem 1rem; text-align: center; }
.cta .btn { background: #fff; color: #0044cc; padding: 0.75rem 1.5rem; border-radius: 0.3rem; text-decoration: none; }
/* Footer */
footer { background: #eee; width: 100%; padding: 1rem; text-align: center; }
/* Mobile Navigation Toggle */
#navToggle { background: none; border: none; font-size: 1.5rem; display: none; }
@media (max-width: 600px) {
#navMenu { position: absolute; top: 100%; left: 0; right: 0; background: #fff; flex-direction: column; display: none; }
#navMenu li { padding: 1rem; border-top: 1px solid #ddd; }
#navToggle { display: block; }
}
Notice how the CSS uses clamp() for fluid typography and keeps the layout mobile‑first. Flexbox handles the alignment, and the @media query only changes the navigation for small screens.
4. JavaScript: Hamburger Toggle & Smooth Scrolling
Vanilla JS keeps the file lightweight while adding useful interactivity.
// js/main.js
document.addEventListener('DOMContentLoaded', () => {
const navToggle = document.getElementById('navToggle');
const navMenu = document.getElementById('navMenu');
// Toggle mobile menu
navToggle.addEventListener('click', () => {
navMenu.classList.toggle('open');
});
// Smooth scroll for internal links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', e => {
e.preventDefault();
const target = document.querySelector(anchor.getAttribute('href'));
target.scrollIntoView({ behavior: 'smooth' });
if (navMenu.classList.contains('open')) {
navMenu.classList.remove('open');
}
});
});
});
To complete the mobile navigation, add this CSS snippet inside the @media block:
#navMenu.open { display: flex; }
5. Intersection Observer for Section Animations
Use the Intersection Observer API to fade in feature cards when they enter the viewport. This technique improves perceived performance and looks polished.
// Add to js/main.js
const observerOptions = {
threshold: 0.15,
rootMargin: '0px 0px -50px 0px',
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
observer.unobserve(entry.target);
}
});
}, observerOptions);
document.querySelectorAll('.card').forEach(card => {
card.classList.add('hidden');
observer.observe(card);
});
And the accompanying CSS:
.hidden { opacity: 0; transform: translateY(20px); transition: opacity 0.6s ease-out, transform 0.6s ease-out; }
.visible { opacity: 1; transform: translateY(0); }
6. Accessibility Checklist
Accessibility isn’t optional. Even a simple landing page should follow these guidelines.
- Use
aria-labelon the navigation toggle button. - Ensure focus states are visible by default.
- Provide alt text for images, e.g.,
alt="Hero background showing a clean workspace". - Maintain sufficient color contrast (WCAG AA minimum).
- Make the navigation keyboard‑friendly by managing focus when the menu opens.
7. Performance Optimizations
- Inline critical CSS for the hero section to avoid render‑blocking.
- Load
main.jswithdeferto keep parsing fast. - Serve images in WebP or AVIF format for reduced file size.
- Use
preloadfor key resources like the hero image. - Implement lazy‑loading for non‑critical images with the
loading="lazy"attribute.
8. Testing Across Devices
After building, test the page on real devices or emulators. Key aspects to verify:
- Navigation toggles correctly on touch screens.
- Content scales gracefully at various widths (320px to 1920px).
- Animations trigger only when visible.
- No console errors in JavaScript.
- Keyboard navigation works throughout the page.
9. Deployment and CDN Use
Host your static assets on a CDN to reduce latency. Set appropriate cache headers:
- Cache HTML for 5 minutes (freshness for updates).
- Cache CSS and JS for 30 days.
- Leverage HTTP/2 to bundle requests.
Conclusion
By combining mobile‑first Flexbox layouts with vanilla JavaScript, Intersection Observer animations, and strict accessibility rules, you can craft a modern, responsive landing page that feels fast and polished on any device. The result is a lightweight, framework‑free solution that’s easy to maintain and extend as your project grows.
