CodeWorlds
Back to collections
Guide15 min readCodeWorlds Team

HTML and CSS basics: a free course from scratch

A free HTML and CSS course from scratch, step by step. Page structure, semantic tags, forms, selectors, the box model, Flexbox, Grid and publishing your first site.

HTML and CSS basics: a free course from scratch

You can learn HTML and CSS from scratch for free with just a browser and a code editor, and at 30-60 minutes a day the basics take about four weeks. HTML describes the structure of a page and CSS how it looks. Learn them in this order: document skeleton, text, links and images, lists, tables and forms, then selectors, the box model, Flexbox, Grid and responsive design. Finally, you publish your own page.

This article works as a mini course: each stage is an explanation, a code example and a task. Most stages link to a free lesson from the HTML and CSS course on CodeWorlds for practice in the browser. Not sure web development is for you? Read where to start learning to code first.

What HTML and CSS are

HTML (HyperText Markup Language) is a markup language describing the structure of a page: where the heading, paragraph or image is. CSS (Cascading Style Sheets) handles the appearance: colours, fonts, spacing and layout. HTML says what is on the page, CSS says how it looks. JavaScript adds behaviour, but you do not need it yet.

You write content with tags. Most come in pairs, such as <p> and </p>, with the content between them. Some, like <img>, have no closing tag. Attributes add information: href tells a link where to go, and alt describes an image for people who cannot see it. These are enough to begin:

  • <h1> to <h6>: headings, most important first,
  • <p>: a paragraph,
  • <a>: a link,
  • <img>: an image,
  • <ul>, <ol> and <li>: bulleted and numbered lists,
  • <div>: a generic container,
  • <button>: a button.

The MDN documentation describes every element, and the Introduction to HTML lesson makes a good warm-up.

A four-week learning plan

The plan assumes 30-60 minutes a day. With more time you finish sooner, and with less, spread it over two months. Regularity matters most, as the article on how to learn to code explains.

WeekTopicsWhat you have at the end
1document skeleton, semantics, text, links, imagesa few subpages connected with links
2lists, tables, forms, CSS selectorsa styled page with a contact form
3the cascade, the box model, Flexbox, Grida menu, cards and a gallery on a grid
4responsive design, final project, publishingyour own page at a public address

You need a code editor, such as the free Visual Studio Code, and a browser with developer tools (F12, or Cmd+Option+I on a Mac). There you click any element, see its styles and edit them live: the best place to experiment.

The HTML document skeleton

Every page shares the same skeleton. Create a project folder with an index.html file:

Code
HTML
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>My first page</title>
  </head>
  <body>
    <h1>Hello, world!</h1>
    <p>This is my first paragraph written in HTML.</p>
  </body>
</html>

<!DOCTYPE html> means modern HTML, and lang gives the content language to screen readers and search engines. <head> holds page information: the character encoding, the tab title and the viewport setting, without which a phone shows the page zoomed out like a desktop. Visible content goes into <body>.

Task: open the file in a browser, change the heading, save and refresh. That is your working loop for the whole course.

Semantic tags

Headings form a hierarchy: <h1> is the page title, <h2> marks chapters and <h3> subsections. Choose them by importance, not size, since CSS sets the size. Semantic tags split a page into parts, and their names say what they contain:

Code
HTML
<body>
  <header>
    <nav>
      <a href="index.html">Home</a>
      <a href="projects.html">Projects</a>
      <a href="contact.html">Contact</a>
    </nav>
  </header>
  <main>
    <article>
      <h1>How my first page came to be</h1>
      <p>It all started with a single index.html file.</p>
    </article>
    <aside>
      <h2>Useful links</h2>
    </aside>
  </main>
  <footer>
    <p>Contact: anna@example.com</p>
  </footer>
</body>

On screen <header> looks just like <div>, but screen reader users can jump straight to <main> or the navigation, and search engines better understand the main content. Keep <div> for containers needed only for styling. The Semantics in HTML lesson goes further.

Task: sketch a favourite site on paper as header, nav, main and footer.

Text, links and images

You split text into <p> paragraphs, mark important fragments with <strong> and emphasis with <em>. These tags carry meaning, not looks, so decorative bold belongs in CSS.

Code
HTML
<p>You can build your first page in <strong>a single evening</strong>.</p>
<p>See my <a href="projects.html">projects</a> or write to
  <a href="mailto:anna@example.com">anna@example.com</a>.</p>
<img src="img/photo.jpg" alt="Anna at a desk with a laptop" width="600" height="400">

A link is an <a> tag with an href, which can be relative (projects.html), absolute (starting with https://) or special, like mailto:, which opens an email client. In <img>, src points to the file and alt describes it: screen readers read it, and browsers show it when the image fails to load. width and height reserve space, so content does not jump while loading. Practise this in the Text formatting in HTML lesson.

Task: create index.html and projects.html and link them both ways.

Lists and tables

<ul> creates a bulleted list, <ol> a numbered one, and each item is an <li>. Tables hold data in rows and columns, like a timetable or a price list.

Code
HTML
<ol>
  <li>Write the structure in HTML</li>
  <li>Add styles in CSS</li>
  <li>Publish the page</li>
</ol>

<table>
  <caption>Weekly plan</caption>
  <thead>
    <tr><th>Day</th><th>Topic</th></tr>
  </thead>
  <tbody>
    <tr><td>Monday</td><td>Links and images</td></tr>
    <tr><td>Tuesday</td><td>Forms</td></tr>
  </tbody>
</table>

Put column headings in <th>, not <td>, so screen readers know which column a value belongs to. Nobody lays out whole pages with tables any more: that is the job of Flexbox and Grid.

Forms

Forms collect data: logging in, searching, contact. The key rule is a <label> tied to its field with the for and id attributes. Clicking the label then focuses the field, and screen readers know its name.

Code
HTML
<form action="/contact" method="post">
  <label for="email">Email</label>
  <input type="email" id="email" name="email" required>

  <label for="message">Message</label>
  <textarea id="message" name="message" rows="4" required></textarea>

  <button type="submit">Send</button>
</form>

With the email type, phones show a keyboard with @ and the browser checks the address format, while required blocks sending an empty field. That is convenience, not security, because the server must validate the data anyway. HTML alone will not send the message to your inbox either: you need a server or a form service. The HTML forms lesson covers field types.

Task: add a contact form and see what happens when you click Send with an empty field.

CSS selectors and the cascade

Styles live in a separate file, such as style.css, attached in <head> with <link rel="stylesheet" href="style.css">. A CSS rule is a selector pointing at elements plus declarations saying what to do with them.

Code
CSS
p {
  line-height: 1.6;
  color: #1f2937;
}

.button {
  background-color: #2563eb;
  color: white;
  padding: 12px 24px;
  border-radius: 8px;
}

#contact {
  margin-top: 48px;
}

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

The element selector p targets all paragraphs, the class selector .button elements with class="button", and the id selector #contact the one element with id="contact". The last rule combines a descendant selector with a pseudo-class: links in nav under the cursor.

When several rules set the same property, higher specificity wins: an id beats a class, and a class beats an element. On a tie, the later rule wins. Day to day you style mostly with classes, because their weight is predictable and easy to override. Text colour and font inherit from the parent, so setting them on body changes the whole page. Practise selectors in the Classes and IDs in CSS lesson.

Task: set a font on body and change the menu link colour on hover.

The box model

Every element is a rectangular box of four layers, from the inside out: content, padding (inner spacing), border and margin (outer spacing). Padding pushes content away from the edge, margin pushes the whole element away from its neighbours.

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

.card {
  width: 300px;
  padding: 16px;
  border: 2px solid #d4a017;
  margin: 24px auto;
}

By default width covers only the content, so the card would be 336 pixels wide: 300 of content plus 16 of padding and 2 of border on each side. box-sizing: border-box counts padding and border into the width, so the card is exactly 300 pixels. Most projects start with this rule.

margin: 24px auto gives 24 pixels above and below, and the automatic side margins centre the card. Developer tools draw every element's box model, so that is where you find the source of an unwanted gap. The CSS box model lesson has more examples, and MDN has an illustrated explanation.

Flexbox

Flexbox lays out elements in one dimension: a row or a column. Give a container display: flex and its direct children line up side by side.

Code
CSS
.menu {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
}

.projects {
  display: flex;
  flex-wrap: wrap;
  gap: 24px;
}

.project {
  flex: 1 1 250px;
}

justify-content distributes elements on the main axis, horizontal in a row, and align-items aligns them on the cross axis. These two solve most everyday alignment problems, and gap sets spacing without margins. flex-wrap: wrap moves cards to a new line, and flex: 1 1 250px tells each card: start at 250 pixels, grow when there is room, shrink when there is not. Learn the rest in the Flexbox, flexible layout lesson.

Task: build a page header with the logo on the left and the menu on the right, aligned vertically.

CSS Grid

Grid lays out elements in two dimensions at once, in rows and columns. You define the grid on the container, and elements fill the cells in order.

Code
CSS
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 16px;
}

The fr unit is a fraction of the free space. repeat(auto-fit, minmax(200px, 1fr)) creates as many columns of at least 200 pixels as fit and shares the rest equally. The gallery gets one column on a phone and several on a wide monitor, without a single media query. The sidebar layout comes in the responsive design section, and the CSS Grid lesson introduces the grid.

Task: lay out six images as this gallery and resize the window to watch the columns change.

Flexbox or Grid

A quick cheat sheet for anyone who knows both techniques:

FeatureFlexboxGrid
Dimensionone: a row or a columntwo: rows and columns at once
What sets the sizethe content of the elementsthe grid on the container
Typical usesmenus, button bars, centringgalleries, cards in equal columns, page layout
Key propertiesjustify-content, align-items, flexgrid-template-columns, grid-area, gap
Browser supportall modern onesall modern ones

The two often work together: Grid lays out the page or a section, while Flexbox aligns details inside cells, like an icon next to button text. Rule of thumb: one row or column means Flexbox, a grid means Grid. Check support for newer properties on Can I use.

Responsive design

A responsive page adapts to the screen width. The simplest approach is mobile first: styles for a narrow screen first, then changes for wider ones in media queries.

Code
CSS
img {
  max-width: 100%;
  height: auto;
}

.layout {
  display: grid;
  gap: 24px;
}

@media (min-width: 768px) {
  .layout {
    grid-template-columns: 250px 1fr;
  }
}

On a narrow screen .layout has one column with the sidebar above the content, and from 768 pixels two: a fixed sidebar and flexible content. The img rule keeps images inside their container.

Add three habits: max-width instead of rigid widths, rem units for fonts and spacing, and testing in the developer tools' device mode and on a real phone. Without the viewport tag from the first stage, media queries will not behave on a phone as you expect. Practise it all in the Media queries lesson.

First project: a personal page

In week four, build a complete page about yourself. It does not have to be beautiful, it has to work. You need index.html, style.css and an img folder for photos, and the page should have:

  1. a header with your name and a Flexbox menu,
  2. an about section with a photo and alt text,
  3. a projects section with cards on a Grid,
  4. a contact form with labels,
  5. a footer with links to your profiles.

Start with HTML alone and check that the page makes sense without styles, then add CSS section by section. Sketch the layout first on paper or in Figma, since following a plan beats inventing the look while coding. Finally, run the file through the W3C validator to catch unclosed tags and typos in attributes.

How to publish your page

A static page, just HTML, CSS and image files, needs no server of your own and no paid hosting. Three popular routes:

  1. GitHub Pages. Create a public repository, upload the files with the Add file button, and under Settings, Pages, publish from the main branch. The page soon goes live at an address like your-username.github.io/repository-name. See the GitHub Pages documentation.
  2. Netlify. With an account, drag your folder onto the Netlify Drop page and get a public address. More in the article on Netlify.
  3. Vercel. Connect your account to a GitHub repository, and every pushed change publishes itself. Details in the article on Vercel.

Start with GitHub Pages: it is free for public repositories and teaches repository work you will need in any developer job. The Static site hosting lesson compares all three routes.

Common beginner mistakes

  • Unclosed tags. The browser guesses what the author meant, so instead of an error message you see an oddly rendered page. A validator finds the cause in seconds.
  • Missing alt text on images. Without a few words of description, some visitors never learn what the photo shows.
  • Fighting styles with !important. When a rule does not apply, check in developer tools which one wins and why.
  • Copying code without understanding it. A snippet from the internet or an AI assistant helps only when you know what every line does, so retype it and change the values.

Practising with CodeWorlds

Prefer a structured path with instant feedback? Try the HTML and CSS course on CodeWorlds. It is the Ancient Egypt world: 9 modules and 429 exercises, from first tags through CSS basics, Flexbox, responsive design, animations and SASS to CSS Grid and a final project. Mohamed is your guide, and you solve exercises in the browser, some in a code editor with a live preview, so there is nothing to install. The course description estimates it at 40-60 hours. The free plan gives 10 units of fuel a day, so you can practise daily without paying. See also the other programming courses.

What comes after HTML and CSS

Once your page is live, you have three sensible directions. The first is JavaScript, which adds behaviour: drop-down menus, form checks, fetching data. The article on JavaScript for beginners lays out a plan.

The second is CSS tooling. Tailwind CSS styles a page with classes right in the HTML, but it makes sense only once you understand plain CSS, since each class maps to properties you already know. Reading other people's code helps too: the Uiverse library has plenty of CSS buttons and cards to take apart.

The third is deepening the basics: accessibility, animations, SASS and modern CSS features, for example with the free Learn CSS course on Google's web.dev.

FAQ

Can I learn HTML and CSS for free?

Yes. MDN, the web.dev courses and the W3C validators are free, and a free code editor plus a browser are all you need. On CodeWorlds the free plan gives 10 units of fuel a day, so you can practise daily at no cost.

How long does it take to learn HTML and CSS from scratch?

The basics take 2-4 weeks of regular study, as in the plan above. Building simple pages comfortably usually takes a few months of practice. Regularity matters most: half an hour a day beats long sessions once a week.

Do I need to know HTML before I start learning CSS?

Yes, because CSS styles HTML elements. Still, headings, paragraphs, links, images and lists are enough to write your first CSS rules and learn the rest in parallel.

Is HTML a programming language?

Not in the strict sense. HTML is a markup language: it describes the structure of content but has no variables, conditions or loops. CSS is usually not counted as a programming language either. You learn programming in the full sense with JavaScript, which makes HTML and CSS a gentle start.

Will HTML and CSS get me a developer job?

On their own they rarely do, because most frontend job offers also require JavaScript and a framework. Still, they are the foundation you cannot skip. The article on how to become a developer describes the whole path.

Read next

We use cookies to enhance your experience on the site