How to Build a Responsive Website with HTML and CSS (Beginner’s Guide)

Learn how to make a responsive website with HTML and CSS step by step: viewport tag, Flexbox, media queries and mobile nav, with a complete portfolio project.

Learning how to make a responsive website with HTML and CSS is the essential first step in web development. A responsive site looks great on a phone, tablet, and desktop without you building three separate versions. In this guide you will build one complete landing page from scratch — HTML structure first, then styling, then the responsive techniques (viewport meta tag, fluid layouts, flexbox, and media queries) that make it adapt to any screen.

No frameworks, no build tools — just a text editor and a browser. If you are completely new to coding, start with our guide to learning coding from scratch, and when you are ready for interactivity, try our JavaScript projects for beginners.

Stage 1: The HTML Skeleton

Every page needs the same skeleton: a header with navigation, a hero section, a features area with cards, and a footer. Create a file called index.html:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Brew & Bean — Coffee, Perfected</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <header class="site-header">
    <nav class="nav">
      <a href="#" class="logo">Brew &amp; Bean</a>
      <ul class="nav-links">
        <li><a href="#features">Menu</a></li>
        <li><a href="#about">About</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </nav>
  </header>

  <main>
    <section class="hero">
      <h2>Great coffee, brewed with care</h2>
      <p>Single-origin beans roasted in small batches, delivered fresh to your door.</p>
      <a href="#features" class="btn">Explore the Menu</a>
    </section>

    <section id="features" class="features">
      <h2>Why Brew &amp; Bean?</h2>
      <div class="cards">
        <article class="card">
          <h3>Fresh Roasts</h3>
          <p>Beans roasted every Tuesday and shipped within 24 hours.</p>
        </article>
        <article class="card">
          <h3>Fair Trade</h3>
          <p>Sourced directly from family farms at above-market prices.</p>
        </article>
        <article class="card">
          <h3>Brew Guides</h3>
          <p>Free step-by-step guides for pour-over, French press, and espresso.</p>
        </article>
      </div>
    </section>

    <section id="about" class="about">
      <h2>Our Story</h2>
      <p>We started in a garage in 2021 with one roaster and a big idea: coffee should taste like where it comes from. Today we partner with twelve farms across three continents.</p>
    </section>
  </main>

  <footer id="contact" class="site-footer">
    <p>Visit us: 123 Roast Lane, Portland, OR · hello@brewandbean.example</p>
    <p><small>© 2026 Brew &amp; Bean. All rights reserved.</small></p>
  </footer>
</body>
</html>

Two things to notice. First, the viewport meta tag — <meta name="viewport" content="width=device-width, initial-scale=1.0"> — tells mobile browsers to render the page at the device’s actual width instead of zooming out to a fake desktop width. Without it, no responsive CSS will work on phones. Second, semantic tags (header, nav, main, section, article, footer) describe the page’s structure, which helps both SEO and screen readers. The MDN HTML documentation covers every element in depth.

Stage 2: Base CSS Styling

Create styles.css in the same folder. Start with a reset, readable typography, and the desktop layout:

/* --- Reset & base --- */
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

body {
  font-family: system-ui, -apple-system, "Segoe UI", sans-serif;
  line-height: 1.6;
  color: #2d2d2d;
  background: #faf7f2;
}

/* --- Header & nav --- */
.site-header {
  background: #3b2314;
  padding: 1rem 2rem;
}

.nav {
  max-width: 1100px;
  margin: 0 auto;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.logo {
  color: #fff;
  font-size: 1.4rem;
  font-weight: bold;
  text-decoration: none;
}

.nav-links {
  list-style: none;
  display: flex;
  gap: 1.5rem;
}

.nav-links a {
  color: #f5e6d3;
  text-decoration: none;
}

.nav-links a:hover {
  text-decoration: underline;
}

/* --- Hero --- */
.hero {
  text-align: center;
  padding: 5rem 2rem;
  background: linear-gradient(135deg, #6f4e37, #3b2314);
  color: #fff;
}

.hero h2 {
  font-size: 2.5rem;
  margin-bottom: 1rem;
}

.hero p {
  font-size: 1.2rem;
  max-width: 600px;
  margin: 0 auto 2rem;
}

.btn {
  display: inline-block;
  background: #e8a04c;
  color: #3b2314;
  padding: 0.8rem 2rem;
  border-radius: 6px;
  text-decoration: none;
  font-weight: bold;
}

.btn:hover {
  background: #f0b266;
}

/* --- Features & cards --- */
.features {
  max-width: 1100px;
  margin: 0 auto;
  padding: 4rem 2rem;
}

.features h2 {
  text-align: center;
  margin-bottom: 2rem;
}

.cards {
  display: flex;
  gap: 1.5rem;
}

.card {
  background: #fff;
  border-radius: 8px;
  padding: 1.5rem;
  flex: 1;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.card h3 {
  margin-bottom: 0.5rem;
  color: #6f4e37;
}

/* --- About & footer --- */
.about {
  max-width: 700px;
  margin: 0 auto;
  padding: 2rem 2rem 4rem;
  text-align: center;
}

.site-footer {
  background: #3b2314;
  color: #f5e6d3;
  text-align: center;
  padding: 2rem;
}

Key techniques here: box-sizing: border-box makes widths include padding (no surprise overflow), max-width with margin: 0 auto centers content on wide screens, and flexbox (display: flex) lays the three cards out in a row. The MDN CSS reference explains every property used here.

Stage 3: Fluid Layouts — Percentages and max-width

Before media queries, make the layout fluid so it bends instead of breaking. The rules:

  • Use relative units (%, rem) instead of fixed pixels for widths and spacing.
  • Constrain images with max-width: 100%; height: auto; so they never overflow their container.
  • Prefer max-width over width for content columns, so narrow screens shrink naturally.

Add this to your CSS — it future-proofs any images you add later:

img {
  max-width: 100%;
  height: auto;
  display: block;
}

Stage 4: Flexbox and Grid Basics

Flexbox arranges items in one direction (our card row); CSS Grid arranges them in two dimensions (rows and columns). For the card section, Grid often gives cleaner responsive behavior — switch .cards to this:

.cards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.5rem;
}

repeat(3, 1fr) creates three equal columns, each taking one fraction of the available space. Even better, this one-liner makes the grid automatically responsive without any media query:

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 1.5rem;
}

auto-fit with minmax(250px, 1fr) means: fit as many 250px-minimum columns as the screen allows, and stretch them to fill the row. On a phone you get one column; on a desktop, three — automatically.

Stage 5: Media Queries — Targeted Adjustments

Media queries apply CSS only when the screen meets a condition. Add these at the bottom of styles.css to polish the tablet and phone experience:

/* Tablets and smaller: stack nav, shrink hero */
@media (max-width: 768px) {
  .nav {
    flex-direction: column;
    gap: 1rem;
  }

  .hero {
    padding: 3rem 1.5rem;
  }

  .hero h2 {
    font-size: 1.8rem;
  }

  .features {
    padding: 2.5rem 1.5rem;
  }
}

/* Small phones: tighter spacing, full-width button */
@media (max-width: 480px) {
  .hero h2 {
    font-size: 1.5rem;
  }

  .btn {
    display: block;
    text-align: center;
  }

  .site-header {
    padding: 1rem;
  }
}

The mobile-first alternative: many developers write the phone styles as the default CSS, then use @media (min-width: 768px) to add desktop enhancements. Either direction works — pick one and stay consistent. Google’s responsive web design basics guide recommends mobile-first, and it is worth reading once you finish this tutorial.

Testing Your Responsive Website

You do not need a phone to test. In Chrome or Edge, press F12, then click the device toolbar icon (or press Ctrl+Shift+M) to simulate phones and tablets. Check these breakpoints:

  1. Desktop (1200px+): three cards in a row, centered content, full nav.
  2. Tablet (768px): nav stacks vertically, hero text shrinks, cards still fit or wrap.
  3. Phone (375px): single-column cards, full-width button, no horizontal scrolling.

The most common bug is horizontal scrolling on mobile — usually caused by a fixed-width element or an image without max-width: 100%. If you see it, inspect elements until you find the culprit.

How to Make a Responsive Website with HTML and CSS: Checklist

  • Viewport meta tag present in <head>.
  • Fluid widths (%, max-width) instead of fixed pixels.
  • Images constrained with max-width: 100%.
  • Flexbox or Grid for layout, not floats or tables.
  • Media queries for at least one tablet and one phone breakpoint.
  • Tested with browser dev tools at 375px, 768px, and 1200px.

Responsive Typography with clamp()

Fixed font sizes look tiny on phones or huge on desktops. The CSS clamp() function sets a size that scales fluidly between a minimum and maximum based on the viewport width:

.hero h2 {
  /* min 1.5rem, preferred 4vw + 1rem, max 2.5rem */
  font-size: clamp(1.5rem, 4vw + 1rem, 2.5rem);
}

body {
  font-size: clamp(1rem, 1.5vw + 0.5rem, 1.125rem);
}

How it works: clamp(MIN, PREFERRED, MAX) picks the preferred value but never goes below the minimum or above the maximum. The vw unit is 1% of the viewport width, so text grows smoothly as the screen widens. This single technique can replace several font-size media queries.

Responsive Navigation: Collapsing the Menu on Mobile

On narrow screens, a horizontal nav list gets cramped. A common pattern is stacking the links vertically — which our 768px media query already does. For sites with many links, the hamburger menu is the standard solution. Here is a CSS-only approach using a checkbox toggle (no JavaScript needed):

<nav class="nav">
  <a href="#" class="logo">Brew &amp; Bean</a>
  <input type="checkbox" id="menu-toggle" class="menu-toggle">
  <label for="menu-toggle" class="hamburger">☰</label>
  <ul class="nav-links">
    <li><a href="#features">Menu</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#contact">Contact</a></li>
  </ul>
</nav>
/* Hide the checkbox and hamburger on desktop */
.menu-toggle,
.hamburger {
  display: none;
}

@media (max-width: 768px) {
  .hamburger {
    display: block;
    font-size: 1.8rem;
    color: #fff;
    cursor: pointer;
  }

  .nav-links {
    display: none;
    flex-direction: column;
    width: 100%;
    text-align: center;
    gap: 0.8rem;
    padding: 1rem 0;
  }

  /* Show the menu when the checkbox is checked */
  .menu-toggle:checked ~ .nav-links {
    display: flex;
  }
}

How it works: the hidden checkbox stores the open/closed state. Tapping the hamburger label toggles it, and the :checked ~ .nav-links selector shows the menu only when checked. It is a neat trick for a first project; production sites usually add a small JavaScript toggle instead, which you will learn in our JavaScript projects for beginners.

Common Responsive Design Mistakes

  • Missing viewport meta tag: without it, phones render a shrunken desktop layout and all your media queries are ignored.
  • Fixed pixel widths on containers: width: 960px overflows a 375px phone. Use max-width: 960px; width: 100%.
  • Too many breakpoints: you rarely need more than two or three. Design for content, not specific devices.
  • Forgetting touch targets: buttons and links should be at least 44px tall on mobile so fingers can tap them reliably.
  • Testing only in one browser: check Chrome, Safari, and Firefox — flexbox and grid gaps have subtle historical differences.

What’s Next

Make your landing page interactive with JavaScript projects for beginners, level up to component-based UI with our React tutorial for beginners, and review how to learn coding from scratch to plan your web development roadmap.

Leave a Reply

Your email address will not be published. Required fields are marked *