Create a folder with two plain text files, index.html for the content and styles.css for the look. Start index.html with the standard skeleton (doctype, html, head, body), link the stylesheet in the head, add a header, main sections and a footer, then open the file in a browser. Upload the folder to any static host to publish it.
| Step | File | What you add |
|---|---|---|
| 1. Skeleton | index.html | doctype, html lang, head with charset, viewport and title |
| 2. Structure | index.html | header, nav, main with sections, footer |
| 3. Content | index.html | Headings, paragraphs, an image with alt text, a form |
| 4. Style | styles.css | Font, colours, spacing, a centred content width |
| 5. Layout | styles.css | Flexbox for the header, grid for cards, one media query |
| 6. Publish | Both | Upload the folder to a static host |
Updated
This is the whole build, not just the first file. You will write a small business page from an empty folder to a responsive layout, and the builder below lets you type your own name and details and see the finished page update. Every snippet is complete, so you can copy the final two files and open them straight away.
Type your business name, tagline and three offerings. The preview and both files update as you type, ready to copy.
Every HTML page starts with the same few lines. The doctype keeps browsers in standards mode, lang tells screen readers which language to speak, and the viewport tag makes phones use their real width.
Save this, open it in a browser, and you already have a valid page with a tab title.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Harbour Bakery | Fresh bread in Portside</title>
<meta name="description" content="Small-batch sourdough baked every morning in Portside.">
<link rel="stylesheet" href="styles.css">
</head>
<body>
<!-- page content goes here -->
</body>
</html>Inside body, a header holds the name and menu, main holds the sections, and a footer closes the page. The live result below has no styles yet, which shows how readable good HTML is on its own.
Edit the text and the result updates. Notice the form labels: clicking a label focuses its field.
<header class="site-header">
<a class="logo" href="index.html">Harbour Bakery</a>
<nav aria-label="Main">
<ul><li><a href="#menu">Menu</a></li><li><a href="#contact">Contact</a></li></ul>
</nav>
</header>
<main>
<section class="hero">
<h1>Fresh sourdough, baked before sunrise</h1>
<p>Small batches, long fermentation, open from 7am.</p>
<a class="button" href="#contact">Order a loaf</a>
</section>
<section id="menu">
<h2>Today's bread</h2>
<ul class="cards">
<li><h3>Country sourdough</h3><p>Crisp crust, open crumb.</p></li>
<li><h3>Seeded rye</h3><p>Dense, nutty, keeps for days.</p></li>
<li><h3>Cinnamon knots</h3><p>Weekends only.</p></li>
</ul>
</section>
<section id="contact">
<h2>Order ahead</h2>
<form action="mailto:[email protected]" method="post">
<label for="name">Your name</label>
<input id="name" name="name" autocomplete="name" required>
<label for="msg">What would you like?</label>
<textarea id="msg" name="message" rows="3"></textarea>
<button type="submit">Send</button>
</form>
</section>
</main>
<footer class="site-footer"><p>Harbour Bakery, 12 Quay Street</p></footer>Put this in styles.css next to index.html. It sets readable type, a centred column, a flex header and a card grid that becomes three columns on wider screens.
Wrap the inside of header, main and footer in <div class="wrap"> to centre the content, as the builder output does.
* { box-sizing: border-box; }
body { margin: 0; font-family: system-ui, -apple-system, "Segoe UI", sans-serif; line-height: 1.6; color: #1f2933; background: #fbfaf7; }
img { max-width: 100%; height: auto; }
.wrap { max-width: 960px; margin-inline: auto; padding: 0 20px; }
.site-header { background: #fff; border-bottom: 1px solid #e5e7eb; }
.site-header .wrap { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 12px; padding-block: 14px; }
.logo { font-weight: 700; color: inherit; text-decoration: none; }
nav ul { display: flex; gap: 18px; list-style: none; margin: 0; padding: 0; }
nav a { color: #1f2933; }
.hero { padding: 56px 0; }
.hero h1 { font-size: clamp(1.8rem, 5vw, 2.8rem); line-height: 1.15; margin: 0 0 12px; }
.button { display: inline-block; background: #0f766e; color: #fff; padding: 10px 18px; border-radius: 8px; text-decoration: none; }
.button:focus-visible, a:focus-visible, input:focus-visible, textarea:focus-visible { outline: 3px solid #f59e0b; outline-offset: 2px; }
.cards { display: grid; gap: 16px; padding: 0; list-style: none; }
.cards li { background: #fff; border: 1px solid #e5e7eb; border-radius: 12px; padding: 16px; }
form { display: grid; gap: 10px; max-width: 480px; }
input, textarea { font: inherit; padding: 8px; border: 1px solid #9aa5b1; border-radius: 6px; width: 100%; }
.site-footer { margin-top: 48px; padding: 24px 0; border-top: 1px solid #e5e7eb; font-size: 0.9rem; }
@media (min-width: 720px) {
.cards { grid-template-columns: repeat(3, 1fr); }
}| Route | Good for | What you do |
|---|---|---|
| Drag and drop static host | Your first site | Upload the folder in the host's dashboard |
| Git-connected static host | Sites you will keep editing | Push to a repository; the host redeploys |
| Shared web hosting | Sites that need email or PHP too | Upload with the file manager or SFTP into the public folder |
| A website builder | Skipping code entirely | Describe the site and edit visually |
header, nav, main, section and footer are not just tidier names for div. Screen readers expose them as landmarks people can jump between, and search engines use them to tell the main content from repeated menus.
Use one h1 for the page's subject and h2 for each section. The heading outline should read like a table of contents if you list it on its own.
Write the single-column phone layout as the default, since blocks already stack vertically. Then add one media query with min-width to switch on columns once there is room.
Cap the reading width with max-width on a wrapper and centre it with margin-inline: auto. Lines stay comfortable on wide screens without any extra rules.
A static host serves your files as they are, which is all an HTML and CSS site needs. Typical options let you drag the folder into a dashboard or connect a Git repository so each push updates the live site.
After uploading, open the live address on your phone, click every link, and submit the form once to confirm it reaches you.
No. Writing the files only needs a text editor and a browser, both free. Several static hosts have free plans for small sites; a custom domain name is usually the only cost if you want one.
Without it, phone browsers lay the page out at a wide desktop width and shrink it, so text becomes tiny. width=device-width tells them to use the real screen width, which is what makes media queries behave.
HTML draws the form, but something has to receive the submission. On a static host, point the form's action at a form-handling service or your host's built-in forms feature. A mailto: link is the simplest fallback.
Create another file such as about.html with the same header and footer, link to it with <a href="about.html">About</a>, and share the one styles.css between them. Each page should have its own title and h1.
Not for a first site. Plain HTML and CSS load fast, need no build step and teach you what every framework produces underneath. Reach for a framework when you need shared components across many pages or app-like behaviour.
Related: HTML boilerplate, HTML and CSS cheat sheet, Flexbox and grid cheat sheet, How to publish a website, HTML validator, Make a website mobile friendly.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.