| 1 |
# jefftml's HTML & CSS Boilerplate |
| 2 |
|
| 3 |
> A modern, minimal 2026 starting point for webpages. |
| 4 |
|
| 5 |
This boilerplate is deliberately tiny. It isn't a framework or a reset; it's a sensible, opinionated foundation that gives you comfortable typography, native dark mode, and a readable layout **before you write a single line of your own CSS**. Everything here is standards-based and ships in every current browser (with one tiny exception). |
| 6 |
|
| 7 |
--- |
| 8 |
|
| 9 |
## Table of Contents |
| 10 |
|
| 11 |
- [Why this exists](#why-this-exists) |
| 12 |
- [Features at a glance](#features-at-a-glance) |
| 13 |
- [Getting started](#getting-started) |
| 14 |
- [Anatomy](#anatomy) |
| 15 |
- [The `<head>`](#the-head) |
| 16 |
- [The CSS](#the-css) |
| 17 |
- [Customizing](#customizing) |
| 18 |
- [Browser support](#browser-support) |
| 19 |
- [License](#license) |
| 20 |
|
| 21 |
--- |
| 22 |
|
| 23 |
## Why this exists |
| 24 |
|
| 25 |
Most "boilerplates" are either bloated (a whole CSS reset plus a grid system you didn't ask for) or too bare (a blank `<html>` with nothing to make text readable). This one aims for the middle: a handful of well-chosen modern CSS features that make a page look intentional and read comfortably on any device, with nothing to install and nothing to tear out later. |
| 26 |
|
| 27 |
It also leans on newer platform features, logical properties, `clamp()`, `color-scheme`, `text-wrap`, `hanging-punctuation`, so the defaults are future-friendly and internationalization-ready out of the box. |
| 28 |
|
| 29 |
--- |
| 30 |
|
| 31 |
## Features at a glance |
| 32 |
|
| 33 |
| Feature | What it does | Why it helps | |
| 34 |
|---|---|---| |
| 35 |
| **Single file, zero dependencies** | All CSS lives in an inline `<style>` block | Nothing to download, no build tooling, instant first paint | |
| 36 |
| **Native light & dark mode** | `color-scheme: light dark` | Respects the user's OS preference automatically; form controls and scrollbars adapt too | |
| 37 |
| **Fluid typography** | `clamp()`-based font size | Text scales smoothly between mobile and desktop with no media queries | |
| 38 |
| **Optimal reading measure** | `min(68ch, 100%)` content width | Caps line length at a comfortable ~68 characters for readability | |
| 39 |
| **Logical properties** | `inline-size`, `margin-inline`, `padding-block` | Works correctly in right-to-left and vertical writing modes | |
| 40 |
| **Comfortable line spacing** | `line-height: 1.7` | Easier, less cramped reading of long-form text | |
| 41 |
| **Smarter body line breaks** | `text-wrap: pretty` | Avoids orphaned single words at the end of paragraphs | |
| 42 |
| **Balanced headings** | `text-wrap: balance` on `h1`–`h6` | Multi-line headings wrap into even, tidy blocks instead of a long line plus a stray word | |
| 43 |
| **Hanging punctuation** | `hanging-punctuation: first last` | Cleaner typographic alignment where supported | |
| 44 |
| **iOS zoom fix** | `-webkit-text-size-adjust: 100%` | Stops mobile Safari from inflating text on rotation | |
| 45 |
| **System font stack** | `font-family: sans-serif` | No web-font request, so text renders instantly with no layout shift | |
| 46 |
| **Semantic, accessible base** | `lang`, `<main>`, proper meta tags | Better SEO and screen-reader behavior from the start | |
| 47 |
|
| 48 |
--- |
| 49 |
|
| 50 |
## Getting started |
| 51 |
|
| 52 |
1. Copy the boilerplate into a new `index.html`. |
| 53 |
2. Replace the `<h1>` and `<p>` placeholders with your content. |
| 54 |
3. Open it in a browser. That's it, there's no step 4. |
| 55 |
|
| 56 |
When your styles outgrow the inline block, uncomment the stylesheet link in the `<head>` and move your CSS into a `style.css` file: |
| 57 |
|
| 58 |
```html |
| 59 |
<link rel="stylesheet" href="style.css"> |
| 60 |
``` |
| 61 |
|
| 62 |
--- |
| 63 |
|
| 64 |
## Anatomy |
| 65 |
|
| 66 |
### The `<head>` |
| 67 |
|
| 68 |
```html |
| 69 |
<meta charset="UTF-8"> |
| 70 |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| 71 |
<title>jefftml’s HTML & CSS Boilerplate</title> |
| 72 |
<meta name="description" content="A 2026 starting point for webpages."> |
| 73 |
``` |
| 74 |
|
| 75 |
- **`lang="en"`** on the `<html>` element tells browsers and assistive technology which language the page is in, improving screen-reader pronunciation and search indexing. |
| 76 |
- **`charset="UTF-8"`** declares Unicode encoding so every character, including emoji and non-Latin scripts, renders correctly. It's placed first so the browser knows the encoding before parsing anything else. |
| 77 |
- **`viewport`** makes the page responsive by mapping the layout to the device's actual width instead of a zoomed-out desktop view. |
| 78 |
- **`meta description`** provides the summary search engines and social previews can use. |
| 79 |
- **`’`** in the title uses a proper typographic curly apostrophe (’) rather than a straight quote, a small detail that signals the same typographic care found throughout the CSS. |
| 80 |
|
| 81 |
### The CSS |
| 82 |
|
| 83 |
```css |
| 84 |
:root { |
| 85 |
color-scheme: light dark; |
| 86 |
} |
| 87 |
``` |
| 88 |
|
| 89 |
Declares that the page supports **both light and dark color schemes**. The browser then renders its default UI (text color, backgrounds, form controls, scrollbars) to match the visitor's system preference, giving you automatic dark mode with a single line and no JavaScript. |
| 90 |
|
| 91 |
```css |
| 92 |
html { |
| 93 |
font-family: sans-serif; |
| 94 |
font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem); |
| 95 |
line-height: 1.7; |
| 96 |
-webkit-text-size-adjust: 100%; |
| 97 |
text-wrap: pretty; |
| 98 |
hanging-punctuation: first last; |
| 99 |
} |
| 100 |
``` |
| 101 |
|
| 102 |
- **`font-family: sans-serif`** uses the reader's default sans-serif face. There's no web font to download, so text appears immediately with zero layout shift and no privacy or performance cost. |
| 103 |
- **`font-size: clamp(1rem, 0.95rem + 0.25vw, 1.125rem)`** is fluid typography. The size never drops below `1rem` (16px) or rises above `1.125rem` (18px), and in between it grows gently with the viewport (`0.95rem + 0.25vw`). You get responsive text without writing breakpoints. |
| 104 |
- **`line-height: 1.7`** is a generous, unitless line height that keeps paragraphs airy and comfortable for extended reading. Being unitless, it scales correctly with any font size. |
| 105 |
- **`-webkit-text-size-adjust: 100%`** prevents mobile WebKit browsers from auto-enlarging text when the device rotates, so your intended sizes are respected. |
| 106 |
- **`text-wrap: pretty`** asks the browser to spend a little extra effort on line breaking in body text. Its headline benefit is eliminating **orphans**, a final line left with one lonely word, by pulling a word down from the line above; it also reduces long runs of consecutive hyphenated lines. Set on `html` so it inherits to every paragraph on the page. |
| 107 |
- **`hanging-punctuation: first last`** lets opening quotes and similar marks hang slightly into the margin, keeping the left edge of text optically aligned. It degrades gracefully, browsers that don't support it simply ignore it. |
| 108 |
|
| 109 |
```css |
| 110 |
main { |
| 111 |
inline-size: min(68ch, 100%); |
| 112 |
margin-inline: auto; |
| 113 |
padding-block: 2rem; |
| 114 |
} |
| 115 |
``` |
| 116 |
|
| 117 |
- **`inline-size: min(68ch, 100%)`** sets the content width to whichever is smaller: 68 characters or the full available space. The `ch` unit ties the measure to the font itself, capping line length around the ~45–75 character sweet spot that's easiest to read, while `100%` ensures it never overflows on narrow screens. |
| 118 |
- **`margin-inline: auto`** centers the content horizontally using a logical property, so it behaves correctly regardless of text direction. |
| 119 |
- **`padding-block: 2rem`** adds breathing room above and below the content, again via a logical property, so "block" means the flow direction rather than a hard-coded top/bottom. |
| 120 |
|
| 121 |
> **Note on logical properties:** `inline-size`, `margin-inline`, and `padding-block` are direction-aware equivalents of `width`, horizontal `margin`, and vertical `padding`. They automatically adapt to right-to-left languages (like Arabic or Hebrew) and vertical writing modes, making the layout internationalization-ready with no extra work. |
| 122 |
|
| 123 |
```css |
| 124 |
h1, h2, h3, h4, h5, h6 { |
| 125 |
text-wrap: balance; |
| 126 |
} |
| 127 |
``` |
| 128 |
|
| 129 |
- **`text-wrap: balance`** evens out the line lengths of a heading that wraps to more than one line, so it forms a tidy block rather than a full-width first line with a single stranded word beneath it. It's the sibling of `pretty` above, where `pretty` optimizes how a passage *ends*, `balance` distributes text across *all* of its lines, and this rule overrides the inherited `pretty` for headings only. |
| 130 |
- It's scoped to `h1`–`h6` deliberately: browsers cap `balance` at a small number of lines (commonly ~4–6) to keep it cheap, and the payoff is most visible on short, large, high-contrast text. Applying it to long paragraphs would mostly do nothing. |
| 131 |
|
| 132 |
> **Note on `text-wrap`:** both values are purely cosmetic. Browsers that don't support them fall back to ordinary line breaking, nothing shifts, overflows, or breaks. |
| 133 |
|
| 134 |
--- |
| 135 |
|
| 136 |
## Customizing |
| 137 |
|
| 138 |
- **Swap the font:** replace `sans-serif` with your own stack, e.g. `font-family: "Inter", system-ui, sans-serif;` |
| 139 |
- **Adjust the measure:** change `68ch` to taste, lower for narrower columns, higher for wider ones. |
| 140 |
- **Tune the fluid range:** edit the three values in `clamp()` to set your own minimum, growth rate, and maximum text size. |
| 141 |
- **Force a single theme:** change `color-scheme` to just `light` or `dark` if you don't want it to follow the OS. |
| 142 |
- **Balance more than headings:** add other short, display-sized text, blockquotes, figure captions, card titles, to the `text-wrap: balance` selector list. |
| 143 |
- **Opt out of pretty wrapping:** set `text-wrap: wrap` on any element where you'd rather have plain, maximally fast line breaking. |
| 144 |
- **Go external:** uncomment the `<link rel="stylesheet">` and move the styles into `style.css` once the project grows. |
| 145 |
|
| 146 |
--- |
| 147 |
|
| 148 |
## Browser support |
| 149 |
|
| 150 |
Every feature here works in current versions of Chrome, Edge, Firefox, and Safari, and the whole file is built so that anything unsupported fails silently rather than breaking the layout. |
| 151 |
|
| 152 |
The progressive enhancements, `hanging-punctuation`, `color-scheme`, and the two `text-wrap` values, simply do nothing in browsers that lack them: readers get standard punctuation, the default light rendering, and ordinary line breaks. `text-wrap: balance` and `text-wrap: pretty` in particular have landed on different timelines across engines, so treat them as a bonus for readers on newer browsers rather than something to rely on. Everything else (`clamp()`, logical properties, `min()`, `ch` units) is broadly supported across modern browsers. |
| 153 |
|
| 154 |
--- |
| 155 |
|
| 156 |
## License |
| 157 |
|
| 158 |
Use it, change it, ship it. No attribution required. |