158 lines · 9.9 KB
Raw Download
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&rsquo;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
- **`&rsquo;`** 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.