DriversRecommendedOutdated drivers can make a good PC feel brokenScan driver issues before chasing fixes manually.Scan NowOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan Now×
Skip to content
ThatPainter
accessibility

Web Design Tutorial: Build a Responsive Website from Scratch

A beginner-friendly walkthrough for planning, building, testing, and publishing a responsive website with HTML and CSS.

By ThatPainter Team 12 min read

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

ThatPainter is reader-supported. When you buy through links on our site, we may earn an affiliate commission. Learn More

Build a small, working website by planning its content, writing semantic HTML, styling it with CSS, and testing it across screen sizes. This beginner tutorial walks through a personal portfolio example from project folder to publishing, with accessibility and performance considered along the way. You do not need JavaScript or a framework to make the first version.

What web design includes

Web design shapes how information is organized, how a page looks, and how people navigate and use it. Front-end development turns that design into HTML, CSS, and sometimes JavaScript. Hosting and publishing make the finished files available online. You can build a useful first site without learning back-end development, which covers server-side logic, databases, and services such as accounts or payments.

A browser requests a page’s files, reads the HTML structure, applies CSS, runs JavaScript when present, and displays the result. In this tutorial, those layers are kept separate in index.html, styles.css, and an optional script.js.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
HTML and CSS: Design and Build Websites
  • HTML CSS Design and Build Web Sites
  • Comes with secure packaging
  • It can be a gift option

Plan a small website before coding

Start with a focused project such as a portfolio, event page, or local-business homepage. A shop, social network, or account-based application brings in payment, data, security, and other requirements that are beyond a first static site.

  • Who is the site for, and what should visitors do?
  • What information matters most? Which pages are genuinely needed?
  • What text and images do you already have?
  • What should the visitor’s main action be?
  • What must remain usable if JavaScript does not load?

Planning the audience, content, and structure before writing code is also the sequence in MDN’s first-website tutorial.

Create the project files

You need a code editor, a modern browser, and a folder for the project. Test in at least one additional browser; a page working in one browser is not proof that it works everywhere. For a first static site, this folder is enough:

web-design-tutorial/
├── index.html
├── styles.css
├── script.js
└── images/

The JavaScript file is optional. You can omit it until there is a specific interaction to add. Git is also optional, though version history is useful as a project grows.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To preview files through a local web server, open a terminal in the project folder and run python3 -m http.server 8000, then visit http://localhost:8000. On some Windows installations, use py -m http.server 8000. This is a local preview, not online hosting.

Build the page structure with HTML

HTML describes the meaning and order of content; CSS will handle its appearance. Save this as index.html. Replace the sample name, text, image, and project details with real content before publishing.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="A portfolio for Alex Morgan, freelance web designer.">
    <title>Alex Morgan — Web Designer</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <header class="site-header">
      <a class="logo" href="/">Alex Morgan</a>
      <nav aria-label="Primary navigation">
        <ul>
          <li><a href="#work">Work</a></li>
          <li><a href="#about">About</a></li>
          <li><a href="#contact">Contact</a></li>
        </ul>
      </nav>
    </header>
    <main>
      <section class="hero" aria-labelledby="hero-title">
        <div>
          <p class="eyebrow">Independent web designer</p>
          <h1 id="hero-title">Websites that make complex ideas clear.</h1>
          <p>I design and build fast, accessible websites for small teams.</p>
          <a class="button" href="#contact">Start a project</a>
        </div>
        <img src="images/workspace.jpg"
          alt="Laptop showing a website design beside a sketchbook"
          width="800" height="600">
      </section>
      <section id="work" aria-labelledby="work-title">
        <h2 id="work-title">Selected work</h2>
        <div class="project-grid">
          <article class="card">
            <h3>Local food guide</h3>
            <p>A responsive guide for independent restaurants.</p>
            <a href="projects/food-guide.html">View the food guide project</a>
          </article>
          <article class="card">
            <h3>Studio portfolio</h3>
            <p>A clear portfolio for a small creative studio.</p>
            <a href="projects/studio.html">View the studio portfolio project</a>
          </article>
        </div>
      </section>
      <section id="about" aria-labelledby="about-title">
        <h2 id="about-title">About</h2>
        <p>I help organizations turn useful information into usable websites.</p>
      </section>
      <section id="contact" aria-labelledby="contact-title">
        <h2 id="contact-title">Contact</h2>
        <form action="/contact" method="post">
          <label for="email">Email address</label>
          <input id="email" name="email" type="email" required>
          <label for="message">Message</label>
          <textarea id="message" name="message" rows="5"></textarea>
          <button type="submit">Send message</button>
        </form>
      </section>
    </main>
    <footer><p>© 2026 Alex Morgan</p></footer>
  </body>
</html>

The lang attribute identifies the page language, and the viewport setting helps mobile browsers size the page to the device width. Landmarks such as header, nav, main, and footer give the document useful structure. Headings should follow content hierarchy, not be chosen just for their default size.

Use links for destinations and buttons for actions. Give informative images useful alternative text; use alt="" for purely decorative images. A visible label associated with each form field is more reliable than placeholder text. The example form will not send messages until its action points to a real form-handling service or server endpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Style the page with CSS

Create styles.css. This starter uses custom properties for shared colors and sizing, Flexbox for the header, and Grid for the hero and project cards. Flexbox is useful for arranging items along one axis; Grid handles rows and columns together.

:root {
  --color-text: #172033;
  --color-muted: #536074;
  --color-background: #f7f8fb;
  --color-surface: #fff;
  --color-accent: #3157d5;
  --color-accent-dark: #203b9c;
  --content-width: 70rem;
  --radius: 0.75rem;
}

*,
*::before,
*::after {
  box-sizing: border-box;
}

body {
  margin: 0;
  color: var(--color-text);
  background: var(--color-background);
  font-family: system-ui, sans-serif;
  line-height: 1.6;
}

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

a {
  color: var(--color-accent);
}

a:focus-visible,
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
  outline: 3px solid #f4b400;
  outline-offset: 3px;
}

.site-header,
main,
footer {
  width: min(100% - 2rem, var(--content-width));
  margin-inline: auto;
}

.site-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1.25rem;
}

nav ul {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.hero {
  display: grid;
  align-items: center;
  gap: 2rem;
  padding-block: 4rem;
}

.hero h1 {
  max-width: 12ch;
  margin-block: 0.25rem 1rem;
  font-size: clamp(2.5rem, 8vw, 5.5rem);
  line-height: 1;
}

.eyebrow {
  color: var(--color-accent);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}

.button,
button {
  display: inline-block;
  border: 0;
  border-radius: 999px;
  padding: 0.75rem 1rem;
  color: white;
  background: var(--color-accent);
  font: inherit;
  font-weight: 700;
  cursor: pointer;
}

.button:hover,
button:hover {
  background: var(--color-accent-dark);
}

section {
  padding-block: 3rem;
}

.project-grid {
  display: grid;
  gap: 1rem;
}

.card {
  padding: 1.25rem;
  border-radius: var(--radius);
  background: var(--color-surface);
}

form {
  display: grid;
  gap: 0.5rem;
  max-width: 35rem;
}

input,
textarea {
  width: 100%;
  margin-bottom: 1rem;
  padding: 0.75rem;
  border: 1px solid #9aa4b2;
  border-radius: 0.4rem;
  color: inherit;
  background: white;
  font: inherit;
}

@media (min-width: 45rem) {
  .hero {
    grid-template-columns: 1fr 1fr;
  }

  .project-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}

@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    scroll-behavior: auto !important;
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}

box-sizing: border-box makes declared widths include padding and borders. The clamp() heading size scales between limits instead of staying fixed. Relative units such as rem, flexible tracks, and gap help a layout adapt without a maze of fixed pixel values. Keep visible focus styling: keyboard users need to see which control is active.

Make the layout responsive

Responsive design means making content work across available space, not assigning a separate layout to every phone model. The example starts with a single-column hero and project list, then moves to two columns when the viewport reaches 45rem. Treat that as a content-driven starting point: change the breakpoint if the layout becomes cramped or overly wide at another width.

  • Keep containers and images flexible; the CSS above prevents images from exceeding their container.
  • Check both narrow and wide screens, including landscape, zoom, and larger text.
  • Avoid horizontal scrolling for ordinary page content and long lines that are hard to read.
  • Keep the HTML reading order sensible; visual rearrangement should not leave keyboard or screen-reader users with a confusing sequence.

For pages with large image files, offer multiple source sizes so a small screen need not download the largest image:

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
<img
  src="images/hero-800.jpg"
  srcset="images/hero-400.jpg 400w,
          images/hero-800.jpg 800w,
          images/hero-1400.jpg 1400w"
  sizes="(min-width: 45rem) 50vw, 100vw"
  width="1400" height="1050"
  alt="Laptop showing a website design beside a sketchbook">

Use <picture> when the image crop or composition needs to change, not just its resolution. MDN’s responsive design guide covers flexible layouts, media queries, viewport handling, typography, and responsive images.

Add JavaScript only for a real interaction

A static portfolio can work with HTML and CSS alone. Add JavaScript when it improves a particular task, such as opening a compact navigation menu. Keep the document useful without the enhancement, and make the control’s state understandable to assistive technology.

Place this button and navigation inside the page header, replacing the existing navigation if you are building a collapsible menu:

Rank #4
Sale
Web Design with HTML, CSS, JavaScript and jQuery Set
  • Brand: Wiley
  • Set of 2 Volumes
  • A handy two-book set that uniquely combines related technologies Highly visual format and accessible language makes these books highly effective learning tools Perfect for beginning web designers and front-end developers
<button class="menu-button" type="button"
  aria-expanded="false" aria-controls="primary-menu">
  Menu
</button>
<nav id="primary-menu" hidden aria-label="Primary navigation">
  <ul>
    <li><a href="#work">Work</a></li>
    <li><a href="#about">About</a></li>
    <li><a href="#contact">Contact</a></li>
  </ul>
</nav>

Add this script to script.js, then load it in the document head with <script src="script.js" defer></script>. The defer attribute lets the browser parse the HTML before running the file.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const button = document.querySelector(".menu-button");
const menu = document.querySelector("#primary-menu");

button.addEventListener("click", () => {
  const isOpen = button.getAttribute("aria-expanded") === "true";
  button.setAttribute("aria-expanded", String(!isOpen));
  menu.hidden = isOpen;
});

The button exposes whether the menu is open through aria-expanded; aria-controls identifies the menu it affects. Verify that the closed state is genuinely hidden, the control has visible keyboard focus, and the page still offers a sensible navigation fallback if JavaScript is unavailable. Use ARIA to communicate behavior that native HTML does not already provide; the W3C WAI tutorials cover common accessible components and their relationship to WCAG guidance.

Check accessibility, performance, and search basics

Accessibility

  • Use headings in a logical order and landmarks for page regions.
  • Ensure links, buttons, menus, and form fields are reachable and usable by keyboard.
  • Keep a visible focus indicator and make sure color is not the only way information is conveyed.
  • Use useful alt text for informative images, empty alt text for decorative images, and nearby explanation for complex charts.
  • Give form controls visible labels. Identify required fields and provide errors that explain how to fix them.
  • Respect reduced-motion preferences when adding animation.

These practices improve access, but they do not by themselves establish that a complete page conforms to a particular WCAG level. Automated audits can find some issues, not prove full accessibility; combine them with keyboard checks and human review.

Performance

  • Resize and compress images before uploading, and choose an appropriate modern format when your workflow supports it.
  • Keep image dimensions in the markup to help the browser reserve space.
  • Avoid large video backgrounds, unnecessary third-party scripts, and excessive font weights.
  • Use browser developer tools to inspect network requests and console errors; try the page on a mobile device or slower connection.

Search basics

Give each page a useful, unique title and description, use a clear main heading, write descriptive link text, and make important destinations reachable through ordinary links. Write for visitors first; metadata alone cannot guarantee crawling, indexing, ranking, or traffic. Google’s Search Essentials explains that appearing in Search is not guaranteed, even when a site follows its guidance.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Test the finished page

Before publishing, check behavior rather than relying on how the page looks in the editor.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • Follow every navigation link; check buttons, images, and form validation. Confirm that a form has a real destination.
  • Inspect the browser console for errors and confirm that the page has useful content when JavaScript is disabled.
  • Test narrow and wide mobile, tablet, desktop, and very wide viewports, plus portrait and landscape orientation.
  • Zoom to 200% and check longer headings, button labels, and larger text settings where available.
  • Navigate with the keyboard, check focus order and visibility, inspect headings and landmarks, and verify form labels and error states.
  • Test current Chromium-based and Firefox browsers, and Safari where available. A check in one browser is not a guarantee for all.

Publish the site

Your local files are not yet public. Hosting serves the files online; a domain is the human-readable address; DNS connects that address to the host; HTTPS encrypts the browser-to-server connection. Deployment is the process of putting the site on its host.

  1. Check that index.html is at the publishing root, alongside the CSS file and any other assets.
  2. Upload or deploy the project to a static hosting service that serves HTML, CSS, and JavaScript files.
  3. Open the host-provided URL and test navigation, images, and styles on the published version.
  4. If needed, connect a custom domain by following the host’s DNS instructions, then verify the site loads over HTTPS.
  5. Repeat the functional and responsive checks after deployment; hosting paths and filename handling may differ from your local setup.

If styles or images disappear online, check that filenames match exactly, including capitalization, and that relative asset paths point to the correct locations. A leading slash can refer to the domain root rather than the folder containing your page. A static host will not run PHP or database code, and a form needs a server-side endpoint or form service to receive submissions. A published page also may not appear in search immediately.

Choose code, a builder, or a CMS

Approach Good fit Trade-off
Code a static site A learning project, portfolio, or small site where you want control over HTML and CSS. You handle layout, accessibility, updates, hosting, and any added features; forms and commerce need additional services or development.
Website builder A brochure site, portfolio, or small business that needs templates, visual editing, and managed hosting. Customization and export can be limited; subscriptions and platform lock-in are possible, and accessibility and performance still need review.
Content management system A site with regular publishing, multiple editors, or a need to manage posts and media separately from presentation. Updates, backups, extensions, and hosting add maintenance and complexity.
E-commerce platform A business needing product catalogs, checkout, inventory, taxes, or shipping workflows. It adds commerce-specific cost and setup that a simple informational site does not need.

A visual mockup in a design app can help settle layout and style, but it is not a functioning website: content, responsive states, accessibility decisions, implementation, and testing remain. A builder reduces coding, not the need to plan content, check mobile layouts, optimize images, review accessibility, and make domain and maintenance decisions.

What to learn next

Once the first page works, strengthen the fundamentals before adding a framework: semantic HTML, the CSS cascade and layout, responsive behavior, keyboard accessibility, and browser debugging. Then explore JavaScript and the DOM, Git, forms and APIs, performance, and testing. Choose a CMS when publishing workflows justify it, and an e-commerce service when the site needs transaction infrastructure. MDN’s core web-development curriculum and web.dev’s learning courses provide paths through these topics.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

SaleBestseller No. 1
HTML and CSS: Design and Build Websites
HTML and CSS: Design and Build Websites
HTML CSS Design and Build Web Sites; Comes with secure packaging; It can be a gift option
$14.94
SaleBestseller No. 3
SaleBestseller No. 4
Web Design with HTML, CSS, JavaScript and jQuery Set
Web Design with HTML, CSS, JavaScript and jQuery Set
Brand: Wiley; Set of 2 Volumes
$35.05

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

More from the Paint Desk

Recommended PC Tool
Recommended PC Tool
PC Slower Than It Used to Be?Free scan - under a minute
Crashes, No Sound, or Screen Glitches?Free driver scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.