Introduction to Web Development with HTML and CSS for Beginners
Web development starts with two core technologies:
- HTML (HyperText Markup Language): the structure and meaning of a web page.
- CSS (Cascading Style Sheets): the presentation—layout, colors, typography, spacing, and responsiveness.
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
- What You Need (Tools and Setup)
- How the Web Works (Quick Mental Model)
- Your First Project Folder
- HTML Basics: Structure, Tags, and Semantics
- Building a Real Page with Semantic HTML
- CSS Basics: Selectors, Cascade, and Box Model
- Styling the Page: Layout, Typography, and Colors
- Responsive Design with Flexbox and Media Queries
- Common Pitfalls and Debugging Tips
- Next Steps
What You Need (Tools and Setup)
1) A code editor
Use any editor, but a dedicated one makes life easier. Popular choices:
- Visual Studio Code
- Sublime Text
- WebStorm
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:
- The browser requests a resource (often an HTML file) from a server.
- The server returns the HTML.
- The browser parses HTML into a structure called the DOM (Document Object Model).
- The browser loads linked resources (CSS, images, fonts).
- The browser applies CSS rules to DOM elements and paints pixels on the screen.
Two key ideas:
- HTML describes meaning and structure, not appearance.
- CSS describes appearance, and it can change without changing the HTML.
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:
- an opening tag:
<p> - content:
Hello - a closing tag:
</p>
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:
hreffor linkssrcfor imagesaltfor accessibilityclassandidfor targeting with CSS/JS
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
<!doctype html>tells the browser to use modern standards mode.<html lang="en">sets the page language (important for accessibility and SEO).<meta charset="utf-8">supports a wide range of characters.<meta name="viewport" ...>is crucial for responsive design on mobile.<link rel="stylesheet" href="styles.css">attaches your CSS file.
Semantic HTML (meaningful structure)
Semantic elements describe what content is, not how it looks:
<header>: top area, often logo/nav<nav>: navigation links<main>: main content<section>: grouped content<article>: self-contained piece (blog post, card)<footer>: bottom area
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><header></code>, <code><main></code>, and
<code><section></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>© <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
- The
<nav>hasaria-labelso screen readers can announce what it is. - Form inputs use
<label for="...">connected to the inputid. This improves usability and accessibility. - Headings are in a logical order: one
h1, thenh2for sections, thenh3for cards.
CSS Basics: Selectors, Cascade, and Box Model
How CSS works
CSS is a set of rules. Each rule has:
- a selector (what to style)
- a declaration block (how to style it)
Example:
p {
color: #333;
line-height: 1.6;
}
Common selectors
- Element selector:
p,h1,a - Class selector:
.button,.card - ID selector:
#contact - Descendant:
.card p(paragraphs inside.card) - Pseudo-class:
a:hover(when hovering)
The cascade and specificity (why styles “win”)
When multiple rules apply, the browser decides which one wins based on:
- Importance:
!importantoverrides most things (avoid using it as a beginner crutch). - Specificity: IDs are more specific than classes; classes are more specific than elements.
- 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:
- Content: the text/image area
- Padding: space inside the element around content
- Border: line around padding/content
- Margin: space outside the element
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
.header-inneruses Flexbox to place the brand on the left and nav on the right..hero-inneruses Flexbox to create a two-column layout that becomes a single column on smaller screens..card-griduses CSS Grid to create three equal columns, then switches to one column atmax-width: 900px.
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:
display: flex;activates flex layout.justify-contentcontrols horizontal distribution (in a row).align-itemscontrols vertical alignment (in a row).gapcreates spacing between items.
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:
http://localhost:8000
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:
- Did you link the stylesheet correctly?
<link rel="stylesheet" href="styles.css"> - Is
styles.cssin the same folder asindex.html? - Are there typos in class names?
.hero-cardis not the same as.herocard.
Use DevTools:
- Right-click the page → Inspect
- Select an element
- Look at the Styles panel to see which rules apply and which are crossed out.
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:
-
Add more pages
Createabout.htmlandcontact.html, then link them in the nav. You can reuse the samestyles.css. -
Learn modern layout patterns
Practice:- sticky headers
- responsive grids
- card components
- spacing systems (consistent margins/paddings)
-
Introduce JavaScript carefully
JavaScript adds behavior (menus, form validation, fetching data). Keep HTML semantic and CSS modular first. -
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
- Page skeleton:
<!doctype html>,<head>,<body> - Structure:
<header>,<nav>,<main>,<section>,<footer> - Text:
<h1>–<h6>,<p>,<strong>,<em> - Links and images:
<a href="">,<img src="" alt=""> - Forms:
<form>,<label>,<input>,<textarea>,<button>
CSS essentials
- Selectors:
p,.class,#id,.parent a,a:hover - Layout:
display: flex,display: grid - Spacing:
margin,padding,gap - Box model:
box-sizing: border-box - Responsive:
@media (max-width: ...)
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.