← Back to Tutorials

Introduction to Web Development with HTML and CSS for Beginners

htmlcssweb developmentbeginnersfront-endresponsive design

Introduction to Web Development with HTML and CSS for Beginners

Web development starts with two core technologies:

This tutorial walks you from “empty folder” to a small multi-section page with clean styling. You’ll learn not just what to type, but why it works, how browsers interpret it, and how to avoid common beginner mistakes.


Table of Contents

  1. What You Need (Tools and Setup)
  2. How the Web Works (Quick Mental Model)
  3. Your First Project Folder
  4. HTML Basics: Structure, Tags, and Semantics
  5. Building a Real Page with Semantic HTML
  6. CSS Basics: Selectors, Cascade, and Box Model
  7. Styling the Page: Layout, Typography, and Colors
  8. Responsive Design with Flexbox and Media Queries
  9. Common Pitfalls and Debugging Tips
  10. Next Steps

What You Need (Tools and Setup)

1) A code editor

Use any editor, but a dedicated one makes life easier. Popular choices:

2) A web browser

Chrome, Firefox, Edge, or Safari. You’ll also use Developer Tools (DevTools) to inspect HTML/CSS and debug.

3) A terminal (command line)

You can do web development without the terminal, but it’s extremely useful. Below are real commands for macOS/Linux and Windows.


How the Web Works (Quick Mental Model)

When you type a URL into a browser:

  1. The browser requests a resource (often an HTML file) from a server.
  2. The server returns the HTML.
  3. The browser parses HTML into a structure called the DOM (Document Object Model).
  4. The browser loads linked resources (CSS, images, fonts).
  5. The browser applies CSS rules to DOM elements and paints pixels on the screen.

Two key ideas:


Your First Project Folder

Create a new folder for your site. Example: my-first-site.

Create files using the terminal

macOS / Linux

mkdir my-first-site
cd my-first-site
touch index.html styles.css

Windows (PowerShell)

mkdir my-first-site
cd my-first-site
New-Item index.html -ItemType File
New-Item styles.css -ItemType File

Your folder should now look like:

my-first-site/
  index.html
  styles.css

Open the folder in your editor

Most editors can open a folder directly. In VS Code, you can also run:

code .

(That command works if the code command is installed.)


HTML Basics: Structure, Tags, and Semantics

What is HTML made of?

HTML is made of elements. Most elements have:

Example:

<p>Hello, world!</p>

Some elements are void elements (they don’t wrap content), like:

<img src="photo.jpg" alt="A description">

Attributes

Attributes provide extra information:

Example:

<a href="https://example.com">Visit Example</a>

The essential HTML skeleton

Create this in index.html:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My First Site</title>
    <link rel="stylesheet" href="styles.css">
  </head>
  <body>
    <h1>Hello HTML</h1>
    <p>This page is styled with CSS.</p>
  </body>
</html>

Why these lines matter

Semantic HTML (meaningful structure)

Semantic elements describe what content is, not how it looks:

Using semantic HTML makes your site more accessible, easier to maintain, and easier for search engines to understand.


Building a Real Page with Semantic HTML

Replace your index.html with the following. This is a small, realistic layout: header, navigation, hero section, feature cards, and a contact form.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Beginner Web Page</title>
    <link rel="stylesheet" href="styles.css">
  </head>

  <body>
    <header class="site-header">
      <div class="container header-inner">
        <a class="brand" href="#">MySite</a>

        <nav aria-label="Primary navigation">
          <ul class="nav-list">
            <li><a href="#features">Features</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#contact">Contact</a></li>
          </ul>
        </nav>
      </div>
    </header>

    <main>
      <section class="hero">
        <div class="container hero-inner">
          <div class="hero-text">
            <h1>Build clean websites with HTML & CSS</h1>
            <p>
              Learn structure with semantic HTML and create modern layouts with CSS.
              This page is a beginner-friendly example you can expand.
            </p>
            <a class="button" href="#features">See features</a>
          </div>

          <div class="hero-card" role="note" aria-label="Quick tip">
            <h2>Quick Tip</h2>
            <p>
              Use <strong>classes</strong> for styling groups of elements.
              Use <strong>IDs</strong> sparingly, mainly for unique anchors like sections.
            </p>
          </div>
        </div>
      </section>

      <section id="features" class="section">
        <div class="container">
          <h2>Features</h2>
          <p class="section-lead">
            These cards demonstrate spacing, typography, and a responsive grid layout.
          </p>

          <div class="card-grid">
            <article class="card">
              <h3>Semantic Structure</h3>
              <p>
                Elements like <code>&lt;header&gt;</code>, <code>&lt;main&gt;</code>, and
                <code>&lt;section&gt;</code> communicate meaning to browsers and assistive tech.
              </p>
            </article>

            <article class="card">
              <h3>Reusable CSS</h3>
              <p>
                Classes such as <code>.container</code> and <code>.button</code> help you keep styles
                consistent across the page.
              </p>
            </article>

            <article class="card">
              <h3>Responsive Layout</h3>
              <p>
                With Flexbox and media queries, the layout adapts from mobile to desktop without
                rewriting the HTML.
              </p>
            </article>
          </div>
        </div>
      </section>

      <section id="about" class="section section-alt">
        <div class="container">
          <h2>About</h2>
          <p>
            HTML provides the content and structure. CSS controls presentation. Keeping them separate
            helps you maintain and scale a project.
          </p>

          <ul class="checklist">
            <li>Use headings in order: <code>h1</code> then <code>h2</code>, etc.</li>
            <li>Prefer semantic elements over generic <code>div</code> when possible.</li>
            <li>Test on small screens early.</li>
          </ul>
        </div>
      </section>

      <section id="contact" class="section">
        <div class="container">
          <h2>Contact</h2>
          <p class="section-lead">
            This form won’t send anywhere yet (that requires a backend), but it demonstrates
            accessible HTML form structure.
          </p>

          <form class="contact-form" action="#" method="post">
            <div class="field">
              <label for="name">Name</label>
              <input id="name" name="name" type="text" autocomplete="name" required>
            </div>

            <div class="field">
              <label for="email">Email</label>
              <input id="email" name="email" type="email" autocomplete="email" required>
            </div>

            <div class="field">
              <label for="message">Message</label>
              <textarea id="message" name="message" rows="5" required></textarea>
            </div>

            <button class="button" type="submit">Send</button>
          </form>
        </div>
      </section>
    </main>

    <footer class="site-footer">
      <div class="container footer-inner">
        <p>&copy; <span id="year">2026</span> MySite. Built with HTML & CSS.</p>
        <a href="#top" class="back-to-top">Back to top</a>
      </div>
    </footer>
  </body>
</html>

Notes on accessibility in the HTML


CSS Basics: Selectors, Cascade, and Box Model

How CSS works

CSS is a set of rules. Each rule has:

Example:

p {
  color: #333;
  line-height: 1.6;
}

Common selectors

The cascade and specificity (why styles “win”)

When multiple rules apply, the browser decides which one wins based on:

  1. Importance: !important overrides most things (avoid using it as a beginner crutch).
  2. Specificity: IDs are more specific than classes; classes are more specific than elements.
  3. Source order: later rules override earlier ones when specificity is equal.

Example:

a { color: blue; }
.nav-list a { color: black; } /* wins because it's more specific */

The box model (critical for layout)

Every element is a rectangular box:

A common beginner confusion: width calculations. By default, width applies to content only, and padding adds extra size. Many developers set:

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

This makes widths easier: padding and border are included in the declared width.


Styling the Page: Layout, Typography, and Colors

Add the following to styles.css. This is a complete stylesheet for the HTML above.

/* 1) Global defaults and design tokens */
:root {
  --bg: #0b1220;
  --panel: #111a2e;
  --text: #e8eefc;
  --muted: #b8c3e0;
  --brand: #6ea8ff;
  --brand-strong: #3b82f6;
  --border: rgba(232, 238, 252, 0.12);

  --radius: 14px;
  --shadow: 0 10px 30px rgba(0, 0, 0, 0.35);
  --max-width: 1100px;
}

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

html {
  scroll-behavior: smooth;
}

body {
  margin: 0;
  font-family: system-ui, -apple-system, Segoe UI, Roboto, Arial, sans-serif;
  background: radial-gradient(1200px 600px at 20% 0%, rgba(110, 168, 255, 0.18), transparent 60%),
              radial-gradient(900px 500px at 80% 10%, rgba(59, 130, 246, 0.15), transparent 55%),
              var(--bg);
  color: var(--text);
  line-height: 1.6;
}

/* 2) Reusable layout helper */
.container {
  width: min(var(--max-width), 100% - 2rem);
  margin-inline: auto;
}

/* 3) Header and navigation */
.site-header {
  position: sticky;
  top: 0;
  z-index: 10;
  background: rgba(11, 18, 32, 0.75);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--border);
}

.header-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 0;
}

.brand {
  font-weight: 700;
  letter-spacing: 0.2px;
  text-decoration: none;
  color: var(--text);
}

.nav-list {
  list-style: none;
  display: flex;
  gap: 0.9rem;
  padding: 0;
  margin: 0;
}

.nav-list a {
  color: var(--muted);
  text-decoration: none;
  padding: 0.35rem 0.55rem;
  border-radius: 10px;
}

.nav-list a:hover,
.nav-list a:focus-visible {
  color: var(--text);
  background: rgba(232, 238, 252, 0.08);
  outline: none;
}

/* 4) Hero section */
.hero {
  padding: 3.2rem 0 2.2rem;
}

.hero-inner {
  display: flex;
  gap: 1.4rem;
  align-items: stretch;
}

.hero-text {
  flex: 1.6;
}

.hero h1 {
  font-size: clamp(2rem, 3vw, 3rem);
  line-height: 1.15;
  margin: 0 0 0.8rem;
}

.hero p {
  margin: 0 0 1.2rem;
  color: var(--muted);
  max-width: 60ch;
}

.hero-card {
  flex: 1;
  background: linear-gradient(180deg, rgba(17, 26, 46, 0.9), rgba(17, 26, 46, 0.65));
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: 1.2rem;
}

.hero-card h2 {
  font-size: 1.1rem;
  margin: 0 0 0.6rem;
}

.hero-card p {
  margin: 0;
  color: var(--muted);
}

/* 5) Buttons (link styled as a button and real button) */
.button {
  display: inline-block;
  border: 0;
  background: linear-gradient(180deg, var(--brand), var(--brand-strong));
  color: #061022;
  font-weight: 700;
  text-decoration: none;
  padding: 0.7rem 1rem;
  border-radius: 12px;
  box-shadow: 0 10px 25px rgba(59, 130, 246, 0.25);
  cursor: pointer;
}

.button:hover,
.button:focus-visible {
  filter: brightness(1.05);
  outline: none;
}

/* 6) Sections and typography */
.section {
  padding: 2.6rem 0;
}

.section-alt {
  background: rgba(232, 238, 252, 0.04);
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
}

.section h2 {
  font-size: 1.7rem;
  margin: 0 0 0.3rem;
}

.section-lead {
  margin: 0 0 1.4rem;
  color: var(--muted);
  max-width: 75ch;
}

/* 7) Card grid */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 1rem;
}

.card {
  background: rgba(17, 26, 46, 0.75);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 1.1rem;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.25);
}

.card h3 {
  margin: 0 0 0.5rem;
}

.card p {
  margin: 0;
  color: var(--muted);
}

/* 8) Checklist */
.checklist {
  margin: 1rem 0 0;
  padding-left: 1.2rem;
  color: var(--muted);
}

.checklist li {
  margin: 0.4rem 0;
}

/* 9) Form styling */
.contact-form {
  max-width: 620px;
  display: grid;
  gap: 1rem;
}

.field {
  display: grid;
  gap: 0.4rem;
}

label {
  font-weight: 600;
}

input,
textarea {
  width: 100%;
  padding: 0.75rem 0.85rem;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: rgba(17, 26, 46, 0.65);
  color: var(--text);
  font: inherit;
}

input:focus,
textarea:focus {
  outline: 2px solid rgba(110, 168, 255, 0.45);
  outline-offset: 2px;
}

/* 10) Footer */
.site-footer {
  border-top: 1px solid var(--border);
  padding: 1.4rem 0;
  color: var(--muted);
}

.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}

.back-to-top {
  color: var(--muted);
  text-decoration: none;
}

.back-to-top:hover,
.back-to-top:focus-visible {
  color: var(--text);
  outline: none;
}

/* 11) Responsive adjustments */
@media (max-width: 900px) {
  .hero-inner {
    flex-direction: column;
  }

  .card-grid {
    grid-template-columns: 1fr;
  }

  .footer-inner {
    flex-direction: column;
    align-items: flex-start;
  }
}

What you just did (important concepts explained)

1) CSS variables (custom properties)

At the top, you defined variables like --bg and --brand. This is a maintainable way to manage colors and spacing. If you change --brand, every place that uses it updates automatically.

2) Layout with Flexbox and Grid

3) Responsive design

The @media (max-width: 900px) block overrides layout rules when the viewport is narrow. This is a core workflow in modern web development: build a layout, then add breakpoints to adapt it.

4) Focus styles

:focus-visible and :focus improve keyboard navigation. Many beginners remove outlines; don’t. Instead, style them to match your design.


Responsive Design with Flexbox and Media Queries

Flexbox in plain language

Flexbox is designed for arranging items in one dimension (row or column). Key properties:

Example:

.row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 1rem;
}

Media queries in plain language

A media query applies CSS only when conditions are true. The most common condition is viewport width.

Example:

@media (max-width: 600px) {
  .row {
    flex-direction: column;
  }
}

This means: on screens 600px wide or less, stack items vertically.


Running Your Site Locally (Real Commands)

You can open index.html by double-clicking it, but a local server is better because it behaves more like a real website (especially when you later add JavaScript modules or fetch requests).

Option A: Use Python (simple and common)

macOS / Linux

cd my-first-site
python3 -m http.server 8000

Windows (PowerShell)

cd my-first-site
python -m http.server 8000

Then open:

Stop the server with Ctrl + C.

Option B: Use Node.js npx (if you have Node installed)

cd my-first-site
npx serve .

It will print a local URL. Use Ctrl + C to stop.


Common Pitfalls and Debugging Tips

1) “My CSS isn’t applying”

Check these in order:

Use DevTools:

2) Margin collapse confusion

Vertical margins can “collapse” between certain block elements. If spacing looks weird, try adding padding to a parent container or using display: flow-root; in some cases. In this tutorial, sections use padding, which avoids many collapse surprises.

3) Images overflow their container

A common fix:

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

4) Centering isn’t working

Remember: margin: 0 auto; centers a block element only if it has a width (or a constrained max-width) and is not full-width by default. That’s why .container uses:

width: min(var(--max-width), 100% - 2rem);
margin-inline: auto;

5) Overusing IDs

IDs are unique and very specific in CSS. Beginners often use IDs for everything, then struggle to override styles later. Prefer classes for styling.


Next Steps

Once you’re comfortable with this project, expand it in realistic ways:

  1. Add more pages
    Create about.html and contact.html, then link them in the nav. You can reuse the same styles.css.

  2. Learn modern layout patterns
    Practice:

    • sticky headers
    • responsive grids
    • card components
    • spacing systems (consistent margins/paddings)
  3. Introduce JavaScript carefully
    JavaScript adds behavior (menus, form validation, fetching data). Keep HTML semantic and CSS modular first.

  4. Deploy your site
    When you’re ready, you can host static sites on platforms like GitHub Pages, Netlify, or Cloudflare Pages.


Quick Reference (Cheat Sheet)

HTML essentials

CSS essentials


If you want, tell me what kind of site you want to build next (portfolio, restaurant page, product landing page), and I can provide a beginner-friendly structure and styling plan using the same HTML/CSS foundations.