// Beginner's Complete Reference

Hello,
Web Dev.

A complete, annotated guide to HTML5, CSS & PHP — written for programmers who already think in code and just need the syntax.

</> HTML 5 { } CSS 3 ?? PHP 8
📋

Complete Outline

What you'll learn in this guide

① HTML5 Foundations

  • Document structure & DOCTYPE
  • Semantic elements
  • Text, links, images, media
  • Lists, tables, forms
  • Attributes & global attributes
  • HTML5 APIs (canvas, audio, video)

② CSS3 Styling

  • Selectors & specificity
  • Box model (margin/border/padding)
  • Typography & color
  • Flexbox layout
  • CSS Grid layout
  • Animations & transitions
  • Media queries (responsive)
  • CSS variables

③ PHP 8 Server-Side

  • Variables, types, operators
  • Control flow (if/else, loops)
  • Functions & scope
  • Arrays & superglobals
  • String functions
  • Forms & POST/GET
  • File I/O & includes
  • MySQL / PDO basics

④ Project: Hello World Site

  • Full page structure
  • Styled components
  • Working HTML form
  • PHP form handler
  • Database insert (PDO)
  • Responsive layout
</>

HTML 5

HyperText Markup Language — the skeleton of every webpage

1 · Document Structure

Every HTML5 page follows this skeleton. Tags are elements; most have an opening <tag> and closing </tag>.

HTML<!-- This is an HTML comment -->
<!DOCTYPE html>             <!-- Declares HTML5 (not a tag, a declaration) -->
<html lang="en">               <!-- Root element -->
  <head>                       <!-- Meta info; NOT displayed on page -->
    <meta charset="UTF-8">     <!-- Self-closing tag (no / needed in HTML5) -->
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Page Title</title>
    <link rel="stylesheet" href="style.css">  <!-- External CSS -->
  </head>
  <body>                       <!-- Everything visible goes here -->
    <h1>Hello, World!</h1>
    <script src="app.js"></script> <!-- JS at BOTTOM for performance -->
  </body>
</html>

2 · Semantic Elements (HTML5 additions)

Semantic tags describe meaning, not appearance. They help SEO, accessibility, and readability. Use them instead of generic <div> everywhere.

ElementMeaningReplaces
<header>Site or section header<div id="header">
<nav>Navigation links<div id="nav">
<main>Primary page content<div id="main">
<article>Self-contained piece (blog post, card)<div class="post">
<section>Thematic grouping with heading<div class="section">
<aside>Sidebar / related content<div id="sidebar">
<footer>Page or section footer<div id="footer">
<figure>Image + caption wrapper<div class="img-wrap">
<time>Date/time (machine-readable)<span>
<mark>Highlighted text<span class="hl">

3 · Text, Links & Inline Elements

HTML<!-- Headings: h1 (most important) → h6 (least) -->
<h1>Main Title</h1>  <h2>Sub</h2>  <h3>Sub-sub</h3>

<p>A paragraph. Use <strong>bold</strong> and <em>italic</em>.</p>

<!-- Anchor (link): href= destination, target= opens new tab -->
<a href="https://example.com" target="_blank" rel="noopener">Visit</a>

<!-- Image: src= path, alt= fallback text (REQUIRED for a11y) -->
<img src="photo.jpg" alt="A cat sitting on a keyboard" width="400">

<br>         <!-- line break (use sparingly) -->
<hr>         <!-- horizontal rule (thematic break) -->
<span>inline container, no semantic meaning</span>
<div>block container, no semantic meaning</div>

4 · Lists & Tables

HTML<!-- Unordered list (bullets) -->
<ul>
  <li>Apple</li>  <li>Banana</li>
</ul>

<!-- Ordered list (numbers) -->
<ol type="A" start="3">   <!-- type: 1 A a I i | start= offset -->
  <li>Step one</li>
</ol>

<!-- Description list (key→value pairs) -->
<dl>
  <dt>HTML</dt>  <dd>HyperText Markup Language</dd>
</dl>

<!-- Table -->
<table>
  <thead>
    <tr><th>Name</th><th>Score</th></tr>
  </thead>
  <tbody>
    <tr><td>Alice</td><td>95</td></tr>
    <tr><td colspan="2">Total: 95</td></tr>  <!-- spans 2 cols -->
  </tbody>
</table>

5 · Forms — The HTML↔PHP Bridge

Forms collect user input and send it to a server. action= is the PHP file that processes it; method= is GET (URL params) or POST (hidden in body).

HTML<!-- action= where data goes | method= GET or POST -->
<form action="process.php" method="POST" enctype="multipart/form-data">

  <!-- Text input -->
  <label for="uname">Username:</label>
  <input type="text" id="uname" name="username"
         placeholder="Enter name" required minlength="3">

  <!-- Other input types: -->
  <input type="email"    name="email">     <!-- validates @ format -->
  <input type="password" name="pass">      <!-- hides characters -->
  <input type="number"   name="age" min="0" max="120">
  <input type="date"     name="dob">
  <input type="checkbox" name="agree" value="yes">
  <input type="radio"    name="gender" value="m"> Male
  <input type="file"     name="avatar" accept="image/*">

  <!-- Dropdown -->
  <select name="country">
    <option value="">-- Choose --</option>
    <option value="us">United States</option>
  </select>

  <!-- Multi-line text -->
  <textarea name="bio" rows="4" cols="40"></textarea>

  <button type="submit">Submit</button>
</form>
▶ Live Demo — Styled Form

6 · HTML5 Media & Embeds

HTML<!-- Video (native, no Flash needed) -->
<video width="640" controls autoplay muted loop poster="thumb.jpg">
  <source src="video.mp4"  type="video/mp4">
  <source src="video.webm" type="video/webm">
  Your browser doesn't support video.
</video>

<!-- Audio -->
<audio controls preload="metadata">
  <source src="track.mp3" type="audio/mpeg">
</audio>

<!-- Canvas (drawn via JavaScript) -->
<canvas id="myCanvas" width="400" height="200"></canvas>

<!-- iFrame embed (YouTube, maps, etc.) -->
<iframe src="https://www.youtube.com/embed/VIDEO_ID"
        width="560" height="315" allowfullscreen></iframe>
{ }

CSS 3

Cascading Style Sheets — the skin and layout of every webpage

1 · Selectors & Specificity

Specificity determines which rule wins when multiple rules target the same element. Higher = wins.

SelectorExampleSpecificity
elementh1 { }0-0-1 (lowest)
.class.card { }0-1-0
[attr]input[type="text"] { }0-1-0
:pseudo-classa:hover { }0-1-0
::pseudo-elementp::first-line { }0-0-1
#id#hero { }1-0-0
inline stylestyle="color:red"1-0-0-0
!importantcolor: red !importantOverrides all ⚠️

Combinator Selectors

CSSdiv p     { }   /* descendant: any p inside div */
div > p   { }   /* child: direct p children only */
h1 + p    { }   /* adjacent sibling: p immediately after h1 */
h1 ~ p    { }   /* general sibling: all p after h1 */
a, button { }   /* group: applies to both a AND button */

2 · The Box Model

Every HTML element is a rectangular box with four layers. box-sizing: border-box (recommended) makes width include padding and border.

margin
border
padding
content
width × height
CSS.box {
  box-sizing: border-box;

  width:   300px;
  height:  200px;

  padding:  16px;       /* all 4 sides */
  padding:  8px 16px;  /* top/bot  left/right */

  margin:   0 auto;     /* center horizontally */

  border:   2px solid red;
  border-radius: 8px;
}

3 · Flexbox — 1D Layout

Flex arranges items in a row or column. Parent holds the container properties; children get item properties.

CSS/* PARENT (container) */
.parent {
  display:         flex;           /* activates flex */
  flex-direction:  row;            /* row | row-reverse | column | column-reverse */
  justify-content: space-between; /* main axis: flex-start center end space-around */
  align-items:     center;         /* cross axis: stretch flex-start flex-end */
  flex-wrap:       wrap;           /* allow wrapping to new row */
  gap:             1rem;           /* spacing between items */
}

/* CHILDREN (items) */
.item {
  flex: 1 1 200px;  /* grow  shrink  basis */
  align-self: flex-end;  /* override align-items for this item */
  order: 2;            /* reorder without changing HTML */
}
▶ Live Flexbox Demo
flex-item 1
flex-item 2
flex-item 3
flex-item 4

4 · CSS Grid — 2D Layout

Grid places items on both rows AND columns simultaneously — ideal for full-page layouts.

CSS.parent {
  display:               grid;
  grid-template-columns: repeat(3, 1fr);   /* 3 equal columns */
  grid-template-columns: 200px 1fr 2fr;   /* mixed widths */
  grid-template-rows:    auto 1fr auto;
  gap:                   1rem;            /* row-gap and column-gap */
}

.span-two {
  grid-column: span 2;  /* takes 2 column slots */
  grid-row:    1 / 3;   /* from row line 1 to 3 */
}

/* Named template areas */
.layout {
  grid-template-areas:
    "header  header"
    "sidebar content"
    "footer  footer";
}
header { grid-area: header; }
▶ Live Grid Demo — 3 columns with span
col 1
col 2 — spans 2
col 1
col 2
col 3

5 · Colors, Typography & Custom Properties

CSS/* Color formats */
color: red;                         /* named */
color: #ff0000;                     /* hex */
color: rgb(255, 0, 0);             /* RGB */
color: rgba(255, 0, 0, 0.5);       /* RGBA (50% opacity) */
color: hsl(0, 100%, 50%);          /* Hue Saturation Lightness */

/* Gradients */
background: linear-gradient(135deg, #f06 0%, #60c8f0 100%);
background: radial-gradient(circle, #fff 0%, #000 100%);

/* CSS Custom Properties (variables) */
:root {
  --primary: #3b82f6;   /* define with -- prefix */
}
.btn { background: var(--primary); }   /* use with var() */

/* Typography */
body {
  font-family: 'Georgia', serif;    /* fallback stack */
  font-size:   1rem;               /* 1rem = 16px by default */
  font-weight: 400;                /* 100 thin → 900 black */
  line-height: 1.6;               /* unitless = × font-size */
  letter-spacing: .05em;
  text-transform: uppercase;
}

6 · Transitions & Keyframe Animations

CSS/* TRANSITION — smooth change on state/class change */
.btn {
  background: blue;
  transition: background .3s ease, transform .2s;
  /*          property  duration  easing */
}
.btn:hover {
  background: navy;
  transform:  scale(1.05);
}

/* KEYFRAME ANIMATION */
@keyframes pulse {
  0%   { transform: scale(1);   opacity: 1; }
  50%  { transform: scale(1.1); opacity: .7; }
  100% { transform: scale(1);   opacity: 1; }
}
.badge {
  animation: pulse 2s ease-in-out infinite;
  /*         name  dur  easing            iteration-count */
}

/* TRANSFORM functions */
transform: translate(20px, -10px)   /* move X, Y */
           rotate(45deg)             /* spin */
           scale(1.5)                /* resize */
           skew(10deg);             /* slant */

7 · Media Queries — Responsive Design

Media queries apply CSS rules only when conditions are met. Design mobile-first: write base styles for small screens, then add overrides for larger ones.

CSS/* Mobile-first breakpoints */
/* Base styles (mobile, 0px+) */
.grid { grid-template-columns: 1fr; }

@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)  { /* dark mode */ }
@media (orientation: landscape)      { /* landscape */ }
@media (hover: none)                  { /* touch device */ }
@media print                           { /* printer styles */ }
??

PHP 8

Hypertext Preprocessor — server-side scripting for dynamic pages

How PHP works: PHP runs on the web server (Apache/Nginx), not in the browser. Files end in .php. PHP code lives between <?php and ?> tags. The server executes the PHP, then sends plain HTML to the browser. You need XAMPP / LAMP / WAMP locally, or a hosting provider, to run PHP files.

1 · Variables, Types & Operators

PHP<?php
// Variables start with $ — dynamically typed
$name    = "Alice";          // string (single OR double quotes)
$age     = 30;                // integer
$gpa     = 3.8;               // float
$active  = true;              // boolean (true / false)
$nothing = null;              // null

// Type juggling and checking
gettype($age);                 // "integer"
is_string($name);              // true
(int) "42abc";                 // cast to 42

// Operators
$sum = 5 + 3;                  // + - * / % **  (** = exponent)
$str = "Hello" . " World";    // . = string concatenation
$str .= "!";                   // .= append shorthand

// Comparison
5 ==  "5"   // true  (loose: only value)
5 === "5"   // false (strict: value AND type)
5 !=  6     // true
5 <=> 6     // -1 (spaceship: <0, 0, >0)

// Null coalescing (PHP 7+)
$user = $_GET['user'] ?? "Guest";  // if null, use "Guest"
?>

2 · Output & String Interpolation

PHP<?php
$name = "World";

echo "Hello, $name!";            // variables expand in double quotes
echo "Hello, {$name}s!";          // {} for complex expressions
echo 'Hello, $name';             // single quotes: NO interpolation
print "Hello";                    // like echo, returns 1

// Heredoc (multi-line, interpolates variables)
echo <<<EOT
  <p>Name: $name</p>
  <p>This can span lines.</p>
EOT;

// Common string functions
strlen($name);                   // length: 5
strtoupper($name);               // WORLD
strtolower($name);               // world
str_replace("o", "0", $name);   // W0rld
trim("  hi  ");                  // removes whitespace
explode(",", "a,b,c");           // ["a","b","c"] — split to array
implode("-", ["a","b"]);        // "a-b"   — join array
htmlspecialchars($input);        // ALWAYS escape user input!
?>

3 · Control Flow

PHP<?php
// if / elseif / else
if ($age >= 18) {
    echo "Adult";
} elseif ($age >= 13) {
    echo "Teen";
} else {
    echo "Child";
}

// Ternary shorthand
$label = ($age >= 18) ? "Adult" : "Minor";

// switch
switch ($day) {
    case "Mon": echo "Monday";  break;
    default:   echo "Other day";
}

// match expression (PHP 8 — strict, no fall-through)
$result = match($status) {
    1       => "Active",
    0, -1   => "Inactive",
    default => "Unknown",
};

// Loops
for ($i = 0; $i < 5; $i++) { echo $i; }

while ($x > 0) { $x--; }         // check before each iteration

do { $x--; } while ($x > 0);     // always runs once

foreach ($array as $key => $value) {
    echo "$key: $value";          // iterates arrays/objects
}
?>

4 · Arrays

PHP<?php
// Indexed array
$fruits = ["apple", "banana", "cherry"];
echo $fruits[0];                   // apple (0-indexed)
$fruits[] = "date";               // append

// Associative array (like a dictionary/hash map)
$person = [
    "name"  => "Alice",
    "age"   => 30,
    "email" => "alice@example.com",
];
echo $person["name"];              // Alice

// Multidimensional array
$users = [
    ["name" => "Alice", "age" => 30],
    ["name" => "Bob",   "age" => 25],
];
echo $users[1]["name"];           // Bob

// Array functions
count($fruits);                  // 4
array_push($fruits, "elderberry");
array_pop($fruits);
sort($fruits);                   // alphabetical
in_array("apple", $fruits);     // true
array_map(fn($f) => strtoupper($f), $fruits);  // PHP 7.4 arrow fn
array_filter($fruits, fn($f) => strlen($f) > 5);
?>

5 · Functions

PHP<?php
// Basic function
function greet(string $name, string $greeting = "Hello"): string
{
    return "$greeting, $name!";
}
echo greet("Alice");             // "Hello, Alice!"
echo greet("Bob", "Hi");         // "Hi, Bob!"

// Named arguments (PHP 8)
greet(greeting: "Hey", name: "Carol");

// Variadic (spread) arguments
function sum(int ...$nums): int {
    return array_sum($nums);
}

// Anonymous function (closure)
$double = function(int $n): int { return $n * 2; };

// Arrow function (PHP 7.4+)
$triple = fn(int $n): int => $n * 3;
?>

6 · Superglobals & Form Handling

PHP<?php
// PHP superglobals (always available, any scope)
$_GET     // URL params:  ?name=Alice
$_POST    // Form data:   method="POST"
$_FILES   // Uploaded files
$_SESSION // Persistent across page loads (need session_start())
$_COOKIE  // Browser cookies
$_SERVER  // Server info: IP, request method, URI…
$_ENV     // Environment variables

// Safe form handler pattern
if ($_SERVER['REQUEST_METHOD'] === 'POST') {

    // 1. Retrieve
    $name  = $_POST['name']  ?? '';
    $email = $_POST['email'] ?? '';

    // 2. Sanitize
    $name  = htmlspecialchars(strip_tags(trim($name)));
    $email = filter_var($email, FILTER_SANITIZE_EMAIL);

    // 3. Validate
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $error = "Invalid email";
    }

    // 4. Use (store, email, redirect…)
    if (empty($error)) {
        header("Location: thankyou.php");   // redirect
        exit;
    }
}
?>
server output → <p>Hello, Alice! Your email alice@example.com was saved.</p>

7 · MySQL Database with PDO

PDO (PHP Data Objects) provides a safe, database-agnostic way to run SQL queries. Always use prepared statements to prevent SQL injection.

PHP<?php
// 1. Connect
$dsn = "mysql:host=localhost;dbname=myapp;charset=utf8mb4";
$pdo = new PDO($dsn, 'root', 'password', [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
]);

// 2. CREATE TABLE (run once)
$pdo->exec("
  CREATE TABLE IF NOT EXISTS users (
    id    INT AUTO_INCREMENT PRIMARY KEY,
    name  VARCHAR(100) NOT NULL,
    email VARCHAR(150) NOT NULL UNIQUE
  )
");

// 3. INSERT with prepared statement (:placeholder syntax)
$stmt = $pdo->prepare("INSERT INTO users (name, email) VALUES (:name, :email)");
$stmt->execute([':name' => $name, ':email' => $email]);
$newId = $pdo->lastInsertId();

// 4. SELECT all rows
$rows = $pdo->query("SELECT * FROM users ORDER BY name")->fetchAll();
foreach ($rows as $row) {
    echo "<li>{$row['name']} — {$row['email']}</li>";
}

// 5. SELECT one row
$stmt = $pdo->prepare("SELECT * FROM users WHERE id = :id");
$stmt->execute([':id' => 1]);
$user = $stmt->fetch();
?>
🚀

Hello World Project

A complete 3-file website bringing it all together

File structure: Save these 3 files in the same folder and open via a PHP server (XAMPP, WAMP, or php -S localhost:8000 in terminal). Visit http://localhost:8000/index.php.

📄 File 1 — index.php (main page)

PHP + HTML<?php
// Include shared config (db connection, functions)
require_once 'config.php';

// Handle form submission
$message = '';
$error   = '';

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $name  = sanitize($_POST['name']  ?? '');
    $email = sanitize($_POST['email'] ?? '');

    if (empty($name) || empty($email)) {
        $error = "All fields are required.";
    } elseif (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        $error = "Please enter a valid email.";
    } else {
        // Save to DB
        $stmt = $pdo->prepare(
            "INSERT INTO greetings (name, email) VALUES (:name, :email)"
        );
        $stmt->execute([':name' => $name, ':email' => $email]);
        $message = "Hello, $name! You're registered.";
    }
}

// Fetch all greetings for display
$greetings = $pdo->query("SELECT * FROM greetings ORDER BY id DESC")->fetchAll();
?>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Hello World</title>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <header>
    <h1>Hello, World!</h1>
    <p>HTML5 + CSS + PHP Demo Site</p>
  </header>

  <main>
    <!-- PHP output inside HTML -->
    <?php if ($message): ?>
      <div class="alert alert-success"><?= $message ?></div>
    <?php endif; ?>

    <?php if ($error): ?>
      <div class="alert alert-error"><?= $error ?></div>
    <?php endif; ?>

    <section class="card">
      <h2>Register</h2>
      <form method="POST" action="">  <!-- action="" = same page -->
        <label for="name">Name</label>
        <input type="text" id="name" name="name" required
               value="<?= htmlspecialchars($name ?? '') ?>">

        <label for="email">Email</label>
        <input type="email" id="email" name="email" required>

        <button type="submit">Say Hello!</button>
      </form>
    </section>

    <section class="card">
      <h2>Greetings Log</h2>
      <ul>
        <?php foreach ($greetings as $g): ?>
          <li><strong><?= htmlspecialchars($g['name']) ?></strong><?= htmlspecialchars($g['email']) ?></li>
        <?php endforeach; ?>
      </ul>
    </section>
  </main>

  <footer>
    <p>&copy; <?= date('Y') ?> My Hello World Site</p>
  </footer>
</body>
</html>

📄 File 2 — config.php (db + helpers)

PHP<?php
// Database credentials (move to .env in production!)
define('DB_HOST', 'localhost');
define('DB_NAME', 'helloworld');
define('DB_USER', 'root');
define('DB_PASS', '');

// PDO connection
try {
    $pdo = new PDO(
        "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8mb4",
        DB_USER, DB_PASS,
        [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
    );

    // Create table if it doesn't exist
    $pdo->exec("
        CREATE TABLE IF NOT EXISTS greetings (
            id         INT AUTO_INCREMENT PRIMARY KEY,
            name       VARCHAR(100) NOT NULL,
            email      VARCHAR(150) NOT NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
        )
    ");

} catch (PDOException $e) {
    die("DB Error: " . $e->getMessage());
}

// Reusable helper function
function sanitize(string $input): string {
    return htmlspecialchars(strip_tags(trim($input)));
}
?>

📄 File 3 — style.css (site styles)

CSS/* ── Base ── */
* { box-sizing: border-box; margin: 0; padding: 0; }
body {
  font-family: 'Segoe UI', sans-serif;
  background: #f5f7fa;
  color: #2d2d2d;
  line-height: 1.6;
}

/* ── Header ── */
header {
  background: linear-gradient(135deg, #1a1a2e, #16213e);
  color: white;
  text-align: center;
  padding: 3rem 1rem;
}
header h1 { font-size: clamp(2rem, 5vw, 3.5rem); }

/* ── Main ── */
main {
  max-width: 760px;
  margin: 2rem auto;
  padding: 0 1rem;
}

/* ── Cards ── */
.card {
  background: white;
  border-radius: 12px;
  box-shadow: 0 2px 16px rgba(0,0,0,.08);
  padding: 2rem;
  margin-bottom: 1.5rem;
}

/* ── Form ── */
label  { display: block; margin: .75rem 0 .25rem; font-weight: 600; }
input, select, textarea {
  width: 100%; border: 1px solid #ccc;
  border-radius: 6px; padding: .55rem .85rem;
  font-size: 1rem;
  transition: border-color .2s;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: #3b82f6;
  box-shadow: 0 0 0 3px rgba(59,130,246,.2);
}
button[type="submit"] {
  margin-top: 1rem;  background: #3b82f6;
  color: white;      border: none;
  border-radius: 6px;  padding: .65rem 1.5rem;
  font-size: 1rem;  font-weight: 600;  cursor: pointer;
  transition: background .2s;
}
button:hover { background: #2563eb; }

/* ── Alerts ── */
.alert { padding: 1rem; border-radius: 8px; margin-bottom: 1rem; }
.alert-success { background: #dcfce7; color: #166534; border: 1px solid #86efac; }
.alert-error   { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; }

/* ── List ── */
.card ul { padding-left: 1.2rem; }
.card li { padding: .3rem 0; border-bottom: 1px solid #f0f0f0; }

/* ── Footer ── */
footer {
  text-align: center;
  padding: 2rem;
  color: #888;
  font-size: .875rem;
}

/* ── Responsive ── */
@media (max-width: 480px) {
  .card { padding: 1.25rem; }
  header h1 { font-size: 2rem; }
}