// A Programmer's Field Guide

Hello,
World.

A comprehensive, annotated reference to HTML5 and CSS3 — written for developers who already think in code and just need the syntax fast.

</>  HTML 5 { }  CSS 3
00

Complete Outline

Everything covered in this guide

01

HTML5 — Structure

  • DOCTYPE & html/head/body
  • <meta> tags & charset
  • Semantic elements
  • Headings, text, links
  • Images & figures
  • Lists & tables
  • Forms & all input types
  • HTML5 media & embeds
  • Global & data-* attributes
02

CSS3 — Selectors

  • Syntax & linking CSS
  • All selector types
  • Specificity & cascade
  • Inheritance
  • Custom properties (vars)
03

CSS3 — Layout

  • Box model diagram
  • Display types
  • Position (all 5)
  • Flexbox (1D)
  • CSS Grid (2D)
04

CSS3 — Visual

  • Colors & gradients
  • Typography properties
  • Backgrounds
  • Transforms
  • Transitions & animations
  • Media queries
05

Hello World Project

  • Full page structure
  • Sticky nav (Flexbox)
  • Hero with animations
  • CSS Grid layout
  • Article + sidebar
  • Contact form
  • Responsive breakpoints
01

HTML 5

HyperText Markup Language — the skeleton of every webpage

1.1 · Document Structure

Every HTML5 page follows this exact skeleton. Tags are elements; most have an opening <tag> and closing </tag>. Self-closing tags (<meta>, <img>, <br>) need no closing tag in HTML5.

HTML<!-- HTML comment — ignored by the browser -->

<!DOCTYPE html>       <!-- NOT a tag. Must be line 1.
                         Tells browser: "Parse this as HTML5." -->

<html lang="en">       <!-- Root element wrapping everything.
                         lang= helps screen readers & SEO. -->

  <head>               <!-- Metadata container — nothing here renders. -->

    <meta charset="UTF-8">
    <!-- charset: UTF-8 supports all Unicode characters (emoji, accents…)
         Always include this as the FIRST child of <head>. -->

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <!-- viewport: without this, mobile browsers render at desktop width
         and then zoom out. Essential for any responsive site. -->

    <meta name="description" content="My first HTML5 site">
    <!-- description: shown in Google search results (max ~155 chars) -->

    <title>Page Title</title>
    <!-- Shown in browser tab, bookmarks, and search results.
         Use a unique, descriptive title per page. -->

    <link rel="stylesheet" href="style.css">
    <!-- Link to external CSS file.
         rel= relationship type (required — always "stylesheet")
         href= path to file (relative) or full URL -->

  </head>

  <body>               <!-- Everything visible goes here. -->

    <h1>Hello, World!</h1>

    <!-- <script> at the BOTTOM of body for performance.
         Browser parses HTML top-to-bottom — a script at the top
         blocks rendering until it fully downloads. -->
    <script src="app.js"></script>

  </body>
</html>

1.2 · Semantic Elements (HTML5 additions)

Semantic elements describe their purpose, not just appearance. Use them instead of endless <div> tags — they improve SEO, accessibility, and code readability.

ElementMeaningOld equivalent
<header> Site or section header <div id="header">
<nav> Navigation links <div id="nav">
<main> Primary page content (once per page)<div id="main">
<article> Self-contained piece (post, card) <div class="post">
<section> Thematic grouping with a heading <div class="section">
<aside> Sidebar / tangentially related content<div id="sidebar">
<footer> Page or section footer <div id="footer">
<figure> Image + optional caption wrapper <div class="img-wrap">
<figcaption>Caption for a <figure> <p class="caption">
<time> Machine-readable date/time <span>
<mark> Highlighted / relevant text <span class="highlight">
<details> Native collapsible accordion (required JS before HTML5)
<summary> Visible label for <details> (required JS before HTML5)
Rule of thumb: Ask "What is this content?" not "How should it look?" If it's the main navigation → <nav>. If it's a standalone blog post → <article>. Visual styling is CSS's job.

1.3 · Text, Links & Inline Elements

HTML<!-- ── HEADINGS: h1 (most important) → h6 (least) ───────────── -->
<!-- Use ONE <h1> per page. Don't skip levels (h1 → h3). -->
<h1>Page Title</h1>
<h2>Section</h2>
<h3>Sub-section</h3>     <!-- h4, h5, h6 continue deeper -->

<!-- ── PARAGRAPHS & INLINE FORMATTING ───────────────────────── -->
<p>
  Use <strong>bold importance</strong> and <em>italic emphasis</em>.
  Subscript: H<sub>2</sub>O   Superscript: E=mc<sup>2</sup>
  Deleted: <del>old price</del>   Inserted: <ins>new price</ins>
  Highlighted: <mark>important</mark>
  Inline code: <code>console.log()</code>
</p>

<!-- ── ANCHOR (link) ──────────────────────────────────────────── -->
<!-- href=   destination URL or path
     target= _blank = new tab | _self = same tab (default)
     rel=    noopener noreferrer — security MUST for _blank links -->
<a href="https://example.com" target="_blank" rel="noopener noreferrer">External</a>
<a href="about.html">Relative path</a>
<a href="#contact">Jump to #contact anchor on same page</a>
<a href="mailto:hi@example.com">Email link</a>
<a href="tel:+14045551234">Phone link (mobile tap-to-call)</a>

<!-- ── IMAGE ───────────────────────────────────────────────────── -->
<!-- src=     path/URL to image (REQUIRED)
     alt=     descriptive text for screen readers & broken images
              Must NOT be empty unless image is purely decorative
     width/height  prevents layout shift while loading -->
<img src="photo.jpg"
     alt="A red barn in a snowy field at dusk"
     width="800" height="533"
     loading="lazy">     <!-- loading=lazy defers off-screen images -->

<!-- Figure with caption -->
<figure>
  <img src="chart.png" alt="Q4 sales chart">
  <figcaption>Fig. 1 — Q4 2024 revenue by region.</figcaption>
</figure>

<!-- ── STRUCTURAL HELPERS ─────────────────────────────────────── -->
<br>               <!-- line break — use sparingly, prefer CSS margins -->
<hr>               <!-- horizontal rule — thematic / topic break -->
<span>inline</span>   <!-- generic INLINE container (no semantic meaning) -->
<div>block</div>    <!-- generic BLOCK container (no semantic meaning) -->

<!-- ── HTML ENTITIES ─────────────────────────────────────────── -->
<!-- Use named or numeric entities for reserved / special chars: -->
&copy;    <!-- © -->
&amp;     <!-- & (ampersand inside HTML!) -->
&lt;      <!-- <  (less-than sign inside HTML!) -->
&gt;      <!-- > -->
&nbsp;    <!-- non-breaking space -->
&mdash;   <!-- — em dash -->
&middot;  <!-- · middle dot -->

1.4 · Lists & Tables

HTML<!-- ── UNORDERED LIST (bullet points) ───────────────────────── -->
<ul>
  <li>Apples</li>
  <li>Oranges</li>
  <li>
    Basket     <!-- lists can be nested inside any <li> -->
    <ul><li>Grapes</li></ul>
  </li>
</ul>

<!-- ── ORDERED LIST (numbered) ──────────────────────────────── -->
<!-- type= 1 (default) | A | a | I | i
     start= starting number | reversed attribute -->
<ol type="A" start="3">
  <li>Shows as "C"</li>
  <li>Shows as "D"</li>
</ol>

<!-- ── DESCRIPTION LIST (term → definition pairs) ───────────── -->
<dl>
  <dt>HTML</dt>   <!-- dt = description term -->
  <dd>HyperText Markup Language</dd>  <!-- dd = description detail -->
  <dt>CSS</dt>
  <dd>Cascading Style Sheets</dd>
</dl>

<!-- ── TABLE ─────────────────────────────────────────────────── -->
<!-- Use tables for TABULAR DATA, not for page layout. -->
<table>
  <caption>Monthly Sales (USD)</caption>   <!-- optional title -->
  <thead>                          <!-- thead groups header rows -->
    <tr>                             <!-- tr = table row -->
      <th scope="col">Month</th>    <!-- th = header cell -->
      <th scope="col">Revenue</th>
    </tr>
  </thead>
  <tbody>                          <!-- tbody groups data rows -->
    <tr>
      <td>January</td>              <!-- td = data cell -->
      <td>$12,400</td>
    </tr>
    <tr>
      <td colspan="2">Q1 Total: $38,200</td>
                          <!-- colspan= span multiple columns
                               rowspan= span multiple rows -->
    </tr>
  </tbody>
  <tfoot>
    <tr><td colspan="2">Year Total: $148,000</td></tr>
  </tfoot>
</table>

1.5 · Forms — Collecting User Input

Forms send data to a server (action=) using GET (URL params) or POST (hidden body). Every input needs a name= attribute — that becomes the key sent to the server.

HTML<!-- action= where to send form data
     method= GET (appended to URL) | POST (hidden in request body) -->
<form action="/submit" method="POST">

  <!-- label: for= MUST match the input's id= — connects them for
       accessibility. Clicking the label focuses the input. -->
  <label for="username">Username</label>
  <input type="text"
         id="username"           <!-- connects to label -->
         name="username"         <!-- key sent to server -->
         placeholder="jsmith"   <!-- hint text; disappears on type -->
         required                <!-- HTML5 built-in validation -->
         minlength="3" maxlength="30"
         autocomplete="username">

  <!-- HTML5 INPUT TYPES — each has built-in browser validation: -->
  <input type="email"    name="email">       <!-- validates @ format -->
  <input type="password" name="pass">        <!-- hides characters -->
  <input type="number"   name="age" min="0" max="120" step="1">
  <input type="date"     name="dob">         <!-- date picker -->
  <input type="url"      name="website">
  <input type="tel"      name="phone">
  <input type="range"    name="vol" min="0" max="100">  <!-- slider -->
  <input type="color"    name="fav">          <!-- colour picker -->
  <input type="file"     name="upload" accept="image/*" multiple>
  <input type="checkbox" name="agree" value="yes" checked>
  <input type="radio"    name="size" value="S"> Small
  <input type="radio"    name="size" value="L"> Large
  <!-- same name= groups radios; only one can be selected at a time -->

  <!-- SELECT dropdown -->
  <select name="country">
    <option value="" disabled selected>Choose…</option>
    <optgroup label="North America">     <!-- group options -->
      <option value="us">United States</option>
      <option value="ca">Canada</option>
    </optgroup>
  </select>

  <!-- TEXTAREA: multi-line text. rows/cols set initial size. -->
  <textarea name="message" rows="5" placeholder="Your message…"></textarea>

  <!-- FIELDSET groups related inputs; LEGEND labels the group -->
  <fieldset>
    <legend>Preferred contact</legend>
    <input type="radio" name="contact" value="email"> Email
    <input type="radio" name="contact" value="phone"> Phone
  </fieldset>

  <!-- Submit buttons -->
  <button type="submit">Send</button>   <!-- preferred — allows HTML inside -->
  <input  type="reset">               <!-- resets all fields -->

</form>
▶ Live Rendered Form

1.6 · HTML5 Media, Embeds & Global Attributes

HTML<!-- ── VIDEO ──────────────────────────────────────────────────── -->
<!-- controls=  show play/pause UI  |  autoplay  start immediately
     muted=    required for autoplay  |  loop  restart when finished
     poster=   thumbnail before play -->
<video width="640" controls autoplay muted loop poster="thumb.jpg">
  <source src="video.mp4"  type="video/mp4">   <!-- browser picks -->
  <source src="video.webm" type="video/webm">  <!-- first it can play -->
  Your browser doesn't support HTML5 video.
</video>

<!-- ── AUDIO ──────────────────────────────────────────────────── -->
<audio controls preload="metadata">   <!-- preload= none | metadata | auto -->
  <source src="track.mp3" type="audio/mpeg">
</audio>

<!-- ── CANVAS (draw via JavaScript) ────────────────────────────── -->
<canvas id="myCanvas" width="600" height="300">Canvas not supported.</canvas>

<!-- ── IFRAME embed ────────────────────────────────────────────── -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
        width="560" height="315"
        title="Video title"    <!-- required for accessibility -->
        allowfullscreen loading="lazy">
</iframe>

<!-- ── GLOBAL ATTRIBUTES (work on any element) ─────────────────── -->
<div  id="hero">                   <!-- unique page id for CSS, JS, anchors -->
<span class="card active">           <!-- one or more CSS classes -->
<p    hidden>                        <!-- display:none equivalent -->
<p    title="Tooltip text">         <!-- hover tooltip -->
<div  tabindex="0">                 <!-- keyboard focus: 0=natural, -1=JS only -->
<p    contenteditable="true">       <!-- editable in browser -->
<img  aria-label="Close menu">     <!-- aria-* for screen readers -->

<!-- data-* attributes: embed custom data; read via JS dataset.* -->
<button data-product-id="sku-42" data-price="19.99">
  Add to Cart
</button>
<!-- JS access:  btn.dataset.productId  → "sku-42"
                 btn.dataset.price      → "19.99"
     (dashes in HTML become camelCase in JS) -->
02

CSS 3

Cascading Style Sheets — the skin, layout & motion of the web

2.1 · Syntax & Linking CSS

CSS/* CSS comment */
/* Core rule syntax:
   selector { property: value; }
   Multiple declarations per rule are allowed. */

h1 {
  color:      #c84b2f;      /* hex colour */
  font-size: 2rem;         /* rem = relative to root font-size (16px) */
  margin:    0 0 1rem;     /* shorthand: top right bottom left */
}
MethodLocationNotes
<link rel="stylesheet" href="s.css">In <head>✅ Preferred — reusable, cached, clean separation
<style> … </style>In <head>Good for single-page or critical CSS
style="color:red"On any element⚠️ Inline — highest specificity, unmaintainable; avoid
@import url("other.css")Inside CSS fileLoads another file (use <link> in HTML instead)

2.2 · Selectors — All Types

CSS/* ── BASIC ────────────────────────────────────────────────────── */
*           { }  /* universal — every element */
p           { }  /* element (type) — all <p> */
.card       { }  /* class — elements with class="card" */
#hero       { }  /* id — ONE element with id="hero" */
h1, h2, h3  { }  /* group — comma = "and also" */

/* ── ATTRIBUTE ────────────────────────────────────────────────── */
a[target="_blank"]   { }  /* exact attribute value */
input[type="email"]  { }  /* input of type email */
[href^="https"]      { }  /* starts with "https" */
[src$=".png"]        { }  /* ends with ".png" */
[class*="btn"]       { }  /* contains "btn" */

/* ── COMBINATORS ──────────────────────────────────────────────── */
nav a            { }  /* DESCENDANT: any <a> inside <nav> */
nav > a          { }  /* CHILD: only DIRECT <a> children of <nav> */
h2 + p           { }  /* ADJACENT SIBLING: <p> immediately after <h2> */
h2 ~ p           { }  /* GENERAL SIBLING: all <p> siblings after <h2> */

/* ── PSEUDO-CLASSES (:) — element STATE ───────────────────────── */
a:hover          { }  /* cursor over element */
a:focus          { }  /* has keyboard/click focus */
a:active         { }  /* being clicked */
a:visited        { }  /* link previously clicked */
input:disabled   { }  /* input with disabled attribute */
input:checked    { }  /* checked checkbox/radio */
input:valid      { }  /* passes HTML5 validation */
input:invalid    { }  /* fails HTML5 validation */
p:first-child    { }  /* <p> that is the first child of its parent */
li:nth-child(2)  { }  /* 2nd child */
li:nth-child(odd)   { }  /* 1,3,5… */
li:nth-child(3n+1)  { }  /* formula: 1,4,7… */
p:not(.special)  { }  /* every <p> WITHOUT class "special" */

/* ── PSEUDO-ELEMENTS (::) — virtual sub-elements ─────────────── */
p::first-letter  { }  /* first letter (drop-cap effect) */
::selection      { }  /* user-highlighted text */
.card::before {
  content: "✦ ";    /* REQUIRED even if empty string */
  color: gold;
}
/* ::before and ::after inject virtual content INSIDE the element,
   before or after the actual content. No extra HTML needed. */

2.3 · Specificity & The Cascade

When multiple rules target the same element, the cascade decides which wins. The three pillars: Origin, Specificity, Source order.

Selector typeScoreExample
Inline style 1-0-0-0 (highest)style="color:red"
#id 0-1-0-0 #hero { }
.class / :pseudo / [attr]0-0-1-0.card:hover { }
element / ::pseudo-element0-0-0-1h1 { } p::before { }
!importantOverrides all ⚠️Avoid — creates specificity wars
CSS/* Equal specificity → LATER rule wins (source order): */
p { color: blue; }   /* written first */
p { color: red; }    /* later → WINS. Text is red. */

/* Higher specificity wins regardless of order: */
p               { color: gray; }  /* 0-0-0-1 */
.intro          { color: teal; }  /* 0-0-1-0 beats above */
#hero p.intro   { color: navy; }  /* 0-1-1-1 beats all above */

/* CSS CUSTOM PROPERTIES (variables) */
:root {
  --primary:  #c84b2f;             /* define: prefix -- */
  --spacing:  1rem;
}
.btn {
  background: var(--primary);      /* use with var() */
  padding:    var(--spacing);
  color:      var(--btn-color, white);  /* fallback value if --btn-color unset */
}

2.4 · The Box Model

Every HTML element is a rectangular box with four layers. With box-sizing: border-box, width/height includes padding and border — no arithmetic surprises.

margin
border
padding
content
CSS.box {
  width:  300px;
  height: 200px;

  padding:       16px;       /* all 4 sides */
  padding:       8px 16px;  /* top/bot left/right */
  padding:       4px 8px 12px 16px;
                              /* ↑ → ↓ ← */
  border:        2px solid #ccc;
  border-top:    3px dashed red;
  border-radius: 8px;

  margin:        0 auto;     /* auto centres block */
  margin-top:    2rem;

  box-sizing:    border-box; /* ← KEY */
}
Tip: Always add *, *::before, *::after { box-sizing: border-box; } to your CSS reset. It's standard practice in every modern project.

2.5 · Display Types & Positioning

CSS/* ── DISPLAY ──────────────────────────────────────────────────── */
.item {
  display: block;         /* full width, stacks vertically */
  display: inline;        /* flows in text; ignores width/height */
  display: inline-block;  /* flows inline BUT respects w/h */
  display: none;          /* removed from layout (no space kept) */
  visibility: hidden;     /* invisible BUT space preserved */
  opacity: 0;             /* transparent; space kept; animatable! */
}

/* ── POSITION ──────────────────────────────────────────────────── */
/* STATIC (default) — in normal flow. top/left/etc have no effect. */

/* RELATIVE — offset from normal position; space preserved. */
.box { position: relative; top: 10px; left: 20px; }

/* ABSOLUTE — removed from flow; positioned to nearest non-static
   ancestor (or <html> as fallback). */
.parent { position: relative; }
.badge  {
  position: absolute;
  top: -8px; right: -8px;  /* sticks to top-right of .parent */
}

/* FIXED — relative to VIEWPORT; stays during scroll. */
nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 100;   /* stack order; higher = on top */
}

/* STICKY — relative until scroll threshold, then fixed. */
.header {
  position: sticky;
  top: 60px;   /* sticks 60px from viewport top */
}

/* Perfect centring trick with absolute: */
.centered {
  position: absolute;
  top: 50%; left: 50%;
  transform: translate(-50%, -50%);  /* pull back by own 50% */
}

2.6 · Flexbox — 1D Layout

Flexbox arranges items along a single axis (row or column). The parent is the flex container; its direct children are flex items.

CSS/* ── CONTAINER properties ────────────────────────────────────── */
.parent {
  display:         flex;           /* activates Flexbox */
  flex-direction:  row;           /* row | row-reverse | column | column-reverse */
  justify-content: space-between; /* MAIN axis:
                                      flex-start | center | flex-end |
                                      space-between | space-around | space-evenly */
  align-items:     center;        /* CROSS axis:
                                      stretch | flex-start | flex-end | center */
  flex-wrap:       wrap;          /* nowrap (default) | wrap | wrap-reverse */
  gap:             1rem;          /* space between items */
}

/* ── ITEM properties ─────────────────────────────────────────── */
.item {
  /* flex: grow  shrink  basis */
  flex:      1 1 200px;   /* grow=1, shrink=1, starting size=200px */
  flex:      1;           /* grow=1, shrink=1, basis=0 (equal share) */
  flex:      none;        /* don't grow or shrink */
  align-self: flex-end;  /* override align-items for this one item */
  order:      -1;         /* reorder visually without changing HTML */
}
▶ Live Flexbox — flex:1 (equal) · flex:2 (double width)
flex:1
flex:2 — double width
flex:1
flex:1

2.7 · CSS Grid — 2D Layout

Grid places items on rows and columns simultaneously — best for full page layouts.

CSS/* ── CONTAINER ──────────────────────────────────────────────── */
.layout {
  display:               grid;
  grid-template-columns: repeat(3, 1fr);    /* 3 equal columns */
  grid-template-columns: 200px 1fr 2fr;   /* mixed units */
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
                                           /* responsive auto columns */
  gap:                   1.5rem;          /* row + column gap */
}

/* ── NAMED TEMPLATE AREAS ────────────────────────────────────── */
.page {
  display: grid;
  grid-template-columns: 250px 1fr;
  grid-template-rows:    auto 1fr auto;
  grid-template-areas:
    "header  header"
    "sidebar content"
    "footer  footer";
}
header  { grid-area: header; }
aside   { grid-area: sidebar; }
main    { grid-area: content; }
footer  { grid-area: footer; }

/* ── ITEM PLACEMENT ─────────────────────────────────────────── */
.banner {
  grid-column: 1 / -1;   /* line 1 to last line (full width) */
  grid-column: span 2;   /* span 2 columns from current position */
  grid-row:    1 / 3;     /* row lines 1 to 3 */
}
▶ Live CSS Grid Demo
grid-column: 1 / -1 (full width)
col 1
col 2+3 (span 2)
col 1
col 2
col 3

2.8 · Colors, Backgrounds & Typography

CSS/* ── COLOR FORMATS ──────────────────────────────────────────── */
color: tomato;                      /* 148 CSS named colours */
color: #c84b2f;                      /* hex #rrggbb */
color: #c84;                         /* shorthand #rgb */
color: rgb(200, 75, 47);           /* RGB 0–255 each */
color: rgba(200, 75, 47, 0.5);     /* RGBA — a = alpha (0 transparent, 1 opaque) */
color: hsl(12, 62%, 48%);          /* HSL — Hue° Saturation% Lightness% */
color: hsl(12 62% 48% / 0.7);      /* modern syntax with alpha */

/* ── BACKGROUNDS ─────────────────────────────────────────────── */
.box {
  background-color:    white;
  background-image:    url('photo.jpg');
  background-size:     cover;    /* cover | contain | 100% | 300px */
  background-position: center;
  background-repeat:   no-repeat;

  /* Gradients */
  background: linear-gradient(135deg, #c84b2f 0%, #e8a844 100%);
  background: radial-gradient(circle at top, #fff 0%, #ccc 100%);
}

/* ── TYPOGRAPHY ──────────────────────────────────────────────── */
body {
  font-family:     'Georgia', serif;  /* stack: browser tries left-to-right */
  font-size:      1rem;             /* 1rem = 16px (root default) */
  font-weight:    400;             /* 100=Thin  400=Normal  700=Bold  900=Black */
  font-style:     normal;          /* normal | italic */
  line-height:    1.6;             /* unitless ✅ — scales with font-size */
  letter-spacing: .04em;          /* em = relative to current font-size */
  text-align:     left;            /* left | right | center | justify */
  text-transform: uppercase;      /* uppercase | lowercase | capitalize */
  text-decoration:underline;      /* underline | line-through | none */
}

/* clamp(min, preferred, max) — fluid sizing without media queries */
h1         { font-size: clamp(1.8rem, 5vw, 4rem); }
.container { padding:   clamp(1rem, 3vw, 3rem); }

/* ── SHADOWS ─────────────────────────────────────────────────── */
.card {
  /* box-shadow: h-offset  v-offset  blur  spread  colour */
  box-shadow:  0 4px 20px  rgba(0,0,0,.12);
  box-shadow:  0 1px 3px   rgba(0,0,0,.1),   /* stacked shadows */
               0 8px 32px  rgba(0,0,0,.08);
}
▶ Color formats — same hue, different syntax
#c84b2f
rgb()
rgba(.5)
hsl()
linear
radial

2.9 · Transforms, Transitions & Keyframe Animations

CSS/* ── TRANSFORMS — move/rotate/scale without affecting layout ─── */
.item {
  transform: translateX(50px)       /* move right */
             translateY(-20px)      /* move up */
             rotate(45deg)         /* rotate clockwise */
             scale(1.5)            /* scale X and Y equally */
             skewX(10deg);        /* slant on X axis */
  transform-origin: top left;    /* pivot point (default: center) */
}

/* ── TRANSITIONS — smooth change between two states ──────────── */
.btn {
  background: navy;
  /* transition: property  duration  timing-function  delay */
  transition: background .3s ease,
              transform  .2s ease;
  /* timing functions: ease | linear | ease-in | ease-out |
                        ease-in-out | cubic-bezier(x1,y1,x2,y2) */
}
.btn:hover {
  background: dodgerblue;
  transform:  scale(1.05);   /* transition fires from here */
}

/* ── @KEYFRAMES — full independent motion ─────────────────────── */
/* Step 1: define the animation */
@keyframes bounce {
  0%   { transform: translateY(0); }
  50%  { transform: translateY(-30px); }
  100% { transform: translateY(0); }
}
@keyframes fade-in {
  from { opacity: 0; transform: translateY(20px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Step 2: apply to element */
.animated {
  /* animation: name  duration  timing  delay  iteration  direction  fill-mode */
  animation:  bounce 1.2s ease-in-out 0s infinite  normal both;
  /* fill-mode: both = stays at last frame AND applies before start */
  animation-play-state: paused;   /* pause/play via JS class toggle */
}

/* Multiple staggered animations via animation-delay: */
.card:nth-child(1) { animation-delay: .1s; }
.card:nth-child(2) { animation-delay: .25s; }
.card:nth-child(3) { animation-delay: .4s; }
▶ Live Animation Demos
@keyframes spin-color
infinite · ease-in-out
slide-in
@keyframes slide-in
0.6s · ease · once
@keyframes pulse-ring
1.4s · ease-out · infinite
▶ Transition Demos — hover each button
Fill on hover Letter-spacing Lift + shadow

2.10 · Media Queries — Responsive Design

Mobile-first approach: write base styles for small screens, then add overrides for larger ones with min-width.

Mobile <640px
Tablet 640–1024px
Desktop 1024px+
CSS/* ── MOBILE-FIRST (recommended) ─────────────────────────────── */
/* Base: applies to ALL screen sizes */
.grid {
  display:               grid;
  grid-template-columns: 1fr;     /* single column on mobile */
}

/* min-width = "at least this wide" */
@media (min-width: 640px) {          /* tablet+ */
  .grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {         /* desktop+ */
  .grid { grid-template-columns: repeat(3, 1fr); }
}

/* ── OTHER MEDIA FEATURES ────────────────────────────────────── */
@media (prefers-color-scheme: dark)  { /* OS dark mode */
  body { background: #111; color: white; }
}
@media (prefers-reduced-motion: reduce) {  /* accessibility */
  * { animation-duration: .01ms !important; }
}
@media (orientation: landscape)  { }
@media print                       { }  /* print stylesheet */
@media (hover: none)              { }  /* touch devices (no mouse hover) */

/* ── COMBINING CONDITIONS ───────────────────────────────────── */
@media (min-width: 640px) and (max-width: 1023px) {
  /* tablet range ONLY */
}
03

Hello World Project

A complete, annotated beginner website — pure HTML + CSS, no server needed

Save as index.html and open in any browser. This single file demonstrates: sticky nav (Flexbox), CSS Grid page layout, semantic HTML5, all major form inputs, keyframe animations, transitions, and responsive media queries — all annotated inline.

Live Rendered Preview

index.html — Hello World

Hello, World!

A beginner HTML5 + CSS website — annotated & responsive

Get In Touch

About This Page

This site demonstrates HTML5 semantics, CSS Grid, Flexbox, forms, and responsive design in a single annotated file.

HTML5CSS Grid FlexboxResponsive

Latest Article

What is the web made of? Every webpage is built from HTML (structure), CSS (style), and optionally JavaScript (behaviour). The browser downloads these files and renders them into the visual page you see.

Understanding this pipeline — from text files to pixels — is the foundation of web development.

Complete Annotated Source Code

Copy everything below into index.html. Open it. Modify it. Break it. Fix it. That's how you learn.

index.html
HTML + CSS<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="description" content="My first HTML5 website">
  <title>Hello World</title>

  <!-- Google Fonts (optional) -->
  <link rel="preconnect" href="https://fonts.googleapis.com">
  <link href="https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;700&family=Source+Serif+4:wght@400;600&display=swap"
        rel="stylesheet">

  <style>
    /* ════════════════════════════════════════════════
       CSS CUSTOM PROPERTIES
    ════════════════════════════════════════════════ */
    :root {
      --bg:       #faf6ef;
      --ink:      #1c1410;
      --muted:    #7a6555;
      --accent:   #c84b2f;
      --teal:     #1e6b6b;
      --border:   #cdbfa8;
      --font-head: 'Playfair Display', Georgia, serif;
      --font-body: 'Source Serif 4', Georgia, serif;
    }

    /* ════════════════════════════════════════════════
       RESET
    ════════════════════════════════════════════════ */
    *, *::before, *::after {
      box-sizing: border-box;
      margin: 0;
      padding: 0;
    }
    html { scroll-behavior: smooth; }

    /* ════════════════════════════════════════════════
       BASE BODY
    ════════════════════════════════════════════════ */
    body {
      font-family:  var(--font-body);
      background:   var(--bg);
      color:        var(--ink);
      line-height:  1.7;
    }

    /* ════════════════════════════════════════════════
       REUSABLE CONTAINER
    ════════════════════════════════════════════════ */
    .container {
      max-width: 900px;
      margin:   0 auto;    /* auto = centres block element */
      padding:  0 1.5rem;
    }

    /* ════════════════════════════════════════════════
       TYPOGRAPHY
    ════════════════════════════════════════════════ */
    h1, h2, h3 {
      font-family: var(--font-head);
      line-height: 1.2;
    }
    h1 { font-size: clamp(2rem, 5vw, 3.5rem); }
    h2 { font-size: 1.4rem; margin-bottom: .75rem; }
    p  { margin-bottom: 1rem; color: #3d2f24; }
    a  { color: var(--teal); text-decoration: underline; }
    a:hover { color: var(--accent); }

    /* ════════════════════════════════════════════════
       STICKY NAVIGATION
       position: sticky stays visible during scroll
    ════════════════════════════════════════════════ */
    .site-nav {
      position:   sticky;
      top:        0;
      z-index:    50;
      background: #1c1410;
      padding:    .7rem 0;
    }
    .nav-inner {
      display:         flex;           /* Flexbox for horizontal nav */
      align-items:     center;
      justify-content: space-between;
      max-width:       900px;
      margin:         0 auto;
      padding:        0 1.5rem;
    }
    .nav-logo {
      font-family:      var(--font-head);
      color:           #faf6ef;
      font-size:       1.2rem;
      text-decoration: none;
    }
    .nav-links {
      list-style: none;   /* remove default bullet points */
      display:    flex;
      gap:        1.5rem;
    }
    .nav-links a {
      color:           #b0a090;
      text-decoration: none;
      font-size:       .9rem;
      transition:      color .2s;  /* smooth colour on hover */
    }
    .nav-links a:hover { color: white; }

    /* ════════════════════════════════════════════════
       HERO SECTION
    ════════════════════════════════════════════════ */
    .hero {
      min-height:     60vh;       /* at least 60% of viewport height */
      display:        flex;
      flex-direction: column;
      justify-content:center;
      padding:        5rem 0;
      background:     linear-gradient(135deg,#1c1410 0%,#3d2f24 100%);
      color:          white;
    }
    .hero h1 { color: white; margin-bottom: 1rem; }
    .hero p  { color: #b0a090; max-width: 500px; }
    .hero-tag {
      display:      inline-block;
      background:   rgba(200,75,47,.25);
      border:       1px solid rgba(200,75,47,.5);
      border-radius:100px;
      padding:      .3em .9em;
      font-size:    .75rem;
      color:        #e8a080;
      margin-bottom:1rem;
    }

    /* ════════════════════════════════════════════════
       PAGE LOAD ANIMATION (staggered reveal)
    ════════════════════════════════════════════════ */
    @keyframes reveal {
      from { opacity:0; transform:translateY(24px); }
      to   { opacity:1; transform:translateY(0); }
    }
    .reveal  { animation: reveal .7s ease both; }
    .delay-1 { animation-delay: .15s; }
    .delay-2 { animation-delay: .3s; }

    /* ════════════════════════════════════════════════
       CSS GRID PAGE LAYOUT (2 columns)
    ════════════════════════════════════════════════ */
    .main-grid {
      display:               grid;
      grid-template-columns: 2fr 1fr;  /* main 2/3 + sidebar 1/3 */
      gap:                   2rem;
      padding:               3rem 0;
    }
    .card {
      background:    white;
      border-radius: 12px;
      padding:       1.75rem 2rem;
      box-shadow:    0 2px 20px rgba(0,0,0,.08);
      border:        1px solid #e5dac8;
      margin-bottom: 1.5rem;
    }

    /* ════════════════════════════════════════════════
       ARTICLE METADATA
    ════════════════════════════════════════════════ */
    .post-meta {
      font-size:     .82rem;
      color:        var(--muted);
      margin-bottom:1rem;
    }

    /* ════════════════════════════════════════════════
       SIDEBAR SKILL TAGS (hover transition)
    ════════════════════════════════════════════════ */
    .sidebar-tag {
      display:       inline-block;
      background:   #f0e9db;
      border-radius:100px;
      padding:      .2em .75em;
      font-size:    .8rem;
      margin:       .2rem;
      transition:   background .2s;
    }
    .sidebar-tag:hover {
      background: var(--accent);
      color:      white;
    }

    /* ════════════════════════════════════════════════
       FORM STYLES
    ════════════════════════════════════════════════ */
    label {
      display:       block;
      font-size:     .85rem;
      font-weight:   600;
      color:         var(--muted);
      margin-top:    .9rem;
      margin-bottom: .3rem;
    }
    input[type="text"],
    input[type="email"],
    select, textarea {
      width:        100%;
      padding:      .55rem .9rem;
      border:       1.5px solid var(--border);
      border-radius:6px;
      font-family:  var(--font-body);
      font-size:    .95rem;
      outline:      none;
      transition:   border-color .2s;
    }
    input:focus, select:focus, textarea:focus {
      border-color: var(--teal);
      box-shadow:   0 0 0 3px rgba(30,107,107,.15);
    }
    textarea { min-height: 100px; resize: vertical; }
    .btn {
      margin-top:    1.25rem;
      background:   var(--accent);
      color:        white;
      border:       none;
      border-radius:6px;
      padding:      .65rem 1.75rem;
      font-family:  var(--font-body);
      font-weight:  600;
      cursor:       pointer;
      transition:   background .2s, transform .15s;
    }
    .btn:hover  { background: #a83a22; transform: translateY(-1px); }
    .btn:active { transform: translateY(0); }

    /* ════════════════════════════════════════════════
       FOOTER
    ════════════════════════════════════════════════ */
    .site-footer {
      background:  #1c1410;
      color:       #7a6555;
      padding:     2.5rem 0;
      text-align:  center;
      font-size:   .88rem;
    }

    /* ════════════════════════════════════════════════
       RESPONSIVE — single column on mobile
    ════════════════════════════════════════════════ */
    @media (max-width: 640px) {
      .main-grid {
        grid-template-columns: 1fr;
      }
    }
  </style>
</head>

<body>

  <!-- ─────────────────────────────────────────────────────────
       NAVIGATION  <nav> — sticky header, Flexbox layout
  ───────────────────────────────────────────────────────────── -->
  <nav class="site-nav" aria-label="Main navigation">
    <div class="nav-inner">
      <a href="#" class="nav-logo">Hello World</a>
      <!-- <ul> unordered list | <li> list item | <a> link -->
      <ul class="nav-links">
        <li><a href="#">Home</a></li>
        <li><a href="#about">About</a></li>
        <li><a href="#blog">Blog</a></li>
        <li><a href="#contact">Contact</a></li>
      </ul>
    </div>
  </nav>

  <!-- ─────────────────────────────────────────────────────────
       HERO  <section> — gradient bg, staggered animation
  ───────────────────────────────────────────────────────────── -->
  <section class="hero">
    <div class="container">
      <!-- .reveal and .delay-* classes trigger CSS @keyframes on load -->
      <span class="hero-tag reveal">HTML5 + CSS3</span>
      <h1 class="reveal delay-1">Hello, World!</h1>
      <p class="reveal delay-2">
        A complete beginner website: semantic HTML5, CSS Grid layout,
        Flexbox nav, forms, transitions, and responsive media queries —
        all in a single annotated file.
      </p>
    </div>
  </section>

  <!-- ─────────────────────────────────────────────────────────
       MAIN CONTENT  <main>
  ───────────────────────────────────────────────────────────── -->
  <main>
    <div class="container">
      <div class="main-grid">

        <!-- LEFT: Article + Form ─────────────────────────────────── -->
        <div>

          <!-- <article> = self-contained piece of content -->
          <article class="card" id="blog">
            <header>
              <!-- <time datetime=> is machine-readable for search engines -->
              <p class="post-meta">
                <time datetime="2025-01-15">January 15, 2025</time>
                &middot; 5 min read
              </p>
              <h2>What is the web made of?</h2>
            </header>

            <p>
              Every webpage is built from:
              <strong>HTML</strong> (structure),
              <strong>CSS</strong> (style), and
              <strong>JavaScript</strong> (behaviour).
            </p>

            <!-- Ordered list -->
            <ol>
              <li>Browser requests the HTML file from a server</li>
              <li>Browser parses HTML and builds the DOM tree</li>
              <li>CSS is applied to style the DOM elements</li>
              <li>Browser paints the result to screen</li>
            </ol>

            <!-- <figure> / <figcaption> -->
            <figure style="margin:1.5rem 0;background:#f5f0e8;
                    border-radius:8px;padding:1.5rem;text-align:center">
              <p style="font-size:2rem;margin:0">🌐 → 📄 → 🎨 → 🖥️</p>
              <figcaption style="font-size:.82rem;color:#7a6555;margin-top:.5rem">
                Fig. 1 — How a browser renders a webpage
              </figcaption>
            </figure>

            <!-- <details> / <summary> = native accordion, no JS needed -->
            <details style="margin-top:1rem;border:1px solid #e5dac8;
                     border-radius:8px;padding:.75rem 1rem">
              <summary style="cursor:pointer;font-weight:600">
                Did you know? Click to expand
              </summary>
              <p style="margin-top:.75rem">
                The first website ever created is still online at
                <a href="http://info.cern.ch" target="_blank"
                   rel="noopener">info.cern.ch</a>.
                Tim Berners-Lee created it in 1991.
              </p>
            </details>
          </article>

          <!-- CONTACT FORM  <section> + <form> ───────────────────────── -->
          <section class="card" id="contact">
            <h2>Contact Me</h2>
            <form action="" method="POST">

              <!-- Two columns via inline Grid -->
              <div style="display:grid;grid-template-columns:1fr 1fr;gap:1rem">
                <div>
                  <label for="fname">First Name</label>
                  <input type="text" id="fname" name="fname"
                         required placeholder="Jane">
                </div>
                <div>
                  <label for="lname">Last Name</label>
                  <input type="text" id="lname" name="lname"
                         placeholder="Smith">
                </div>
              </div>

              <label for="email">Email Address</label>
              <input type="email" id="email" name="email"
                     required placeholder="jane@example.com">

              <label for="subject">Subject</label>
              <select id="subject" name="subject">
                <option value="">Choose…</option>
                <option value="hi">Just saying hi</option>
                <option value="work">Work enquiry</option>
                <option value="other">Other</option>
              </select>

              <label for="message">Message</label>
              <textarea id="message" name="message"
                        rows="4" placeholder="Write your message here…"></textarea>

              <!-- Checkbox -->
              <div style="display:flex;align-items:center;gap:.5rem;margin-top:1rem">
                <input type="checkbox" id="subscribe"
                       name="subscribe" value="yes">
                <label for="subscribe"
                       style="margin:0;font-weight:400">
                  Subscribe to newsletter
                </label>
              </div>

              <!-- <button type="submit"> submits the form -->
              <button type="submit" class="btn">Send Message →</button>
            </form>
          </section>

        </div><!-- /left column -->

        <!-- RIGHT: Sidebar  <aside> ─────────────────────────────────── -->
        <aside id="about">

          <div class="card">
            <h2>About</h2>
            <!-- <figure> wraps visual content -->
            <figure style="text-align:center;margin-bottom:1rem">
              <div style="width:80px;height:80px;border-radius:50%;
                     background:#f0e9db;display:flex;align-items:center;
                     justify-content:center;font-size:2.5rem;margin:0 auto">
                👋
              </div>
            </figure>
            <p>Learning HTML5 + CSS3 by building this site from
               scratch. All in one annotated file.</p>
            <!-- Unordered list with no bullets (styled via CSS) -->
            <ul style="list-style:none;padding:0">
              <li>📍 Sugar Hill, GA</li>
              <li>💻 HTML + CSS learner</li>
              <li>📚 Always reading docs</li>
            </ul>
          </div>

          <div class="card">
            <h2>Skills</h2>
            <!-- <span> inline elements styled as pill tags -->
            <span class="sidebar-tag">HTML5</span>
            <span class="sidebar-tag">CSS3</span>
            <span class="sidebar-tag">Flexbox</span>
            <span class="sidebar-tag">CSS Grid</span>
            <span class="sidebar-tag">Forms</span>
            <span class="sidebar-tag">Animations</span>
          </div>

          <div class="card">
            <h2>Next Steps</h2>
            <!-- <dl> description list: <dt> term, <dd> detail -->
            <dl style="font-size:.88rem">
              <dt style="font-weight:600;margin-top:.5rem">JavaScript</dt>
              <dd style="color:#7a6555;margin-left:1rem">DOM, events, fetch API</dd>
              <dt style="font-weight:600;margin-top:.5rem">Frameworks</dt>
              <dd style="color:#7a6555;margin-left:1rem">React, Vue, Svelte</dd>
              <dt style="font-weight:600;margin-top:.5rem">Back-end</dt>
              <dd style="color:#7a6555;margin-left:1rem">Node.js, PHP, Python</dd>
            </dl>
          </div>

        </aside>

      </div><!-- /main-grid -->
    </div><!-- /container -->
  </main>

  <!-- ─────────────────────────────────────────────────────────
       FOOTER  <footer>
  ───────────────────────────────────────────────────────────── -->
  <footer class="site-footer">
    <div class="container">
      <!-- HTML entities:
           &copy;   → ©   (copyright)
           &middot; → ·   (middle dot)
           &amp;    → &   (literal ampersand in HTML)  -->
      <p>&copy; <time datetime="2025">2025</time>
         Hello World Site &middot;
         Built with HTML5 &amp; CSS3
      </p>
      <nav aria-label="Footer navigation" style="margin-top:.75rem">
        <a href="#"        style="color:#b0a090;margin:0 .75rem">Home</a>
        <a href="#about"   style="color:#b0a090;margin:0 .75rem">About</a>
        <a href="#contact" style="color:#b0a090;margin:0 .75rem">Contact</a>
      </nav>
    </div>
  </footer>

</body>
</html>