Content
Reboot
Reboot, a small set of element-specific CSS changes at the top of felt.css, provides a simple, consistent baseline to build upon.
View page source on GitHubOn this page
Approach#
Like Bootstrap's Reboot, felt-css gives many HTML elements somewhat opinionated styles using only element selectors. Additional styling is done only with classes. For example, <table>s get a simpler baseline, and .table, .table-bordered, and more come on top.
felt-css's Reboot is smaller than Bootstrap's and doesn't build on Normalize. It lives in two cascade layers at the top of felt.css: reset (a handful of resets) and base (page defaults and prose). Because every later layer and all un-layered CSS win over them, your own styles override Reboot without any specificity fights.
Guidelines it follows:
- Avoid
margin-top. Vertical margins can collapse, yielding unexpected results. - Block elements use
rems for theirmargins, for easier scaling. - Keep declarations of
font-related properties to a minimum, usinginheritwhenever possible. - Colours come from custom properties on
:root(--text,--body-bg,--link…), so everything follows the look and the color mode.
Page defaults#
The <html> and <body> elements are updated to provide better page-wide defaults. More specifically:
- The
box-sizingis globally set on every element—including*::beforeand*::after, toborder-box. - The
<body>loses its default margin. - No base
font-sizeis declared on the<html>or the<body>; the browser's default (typically16px) applies, so visitors can change it. - The
<body>sets a globalfont-family(--font),line-height: 1.5,color(--text) and font smoothing. - The
<body>also has a declaredbackground:--body-bg, a very light grey in the clean look and cream felt in the felt look (charcoal in dark mode). Cards and other surfaces sit on it in--surface. <img>and<svg>getmax-width: 100%andvertical-align: middle, so images never overflow their container, even without.img-fluid.- Every focusable element gets a visible focus ring on
:focus-visible: a 3px outline in--focus(a translucent primary), 2px away from the element.
Native font stack#
felt-css uses a "native font stack" or "system font stack" for optimum text rendering on every device and OS:
--font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
--font-heading: var(--font);
--font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;Override these custom properties on :root to change the typeface of the body, the headings or the code, everywhere at once.
Headings#
All heading elements—<h1>—<h6> have their margin-top removed, margin-bottom: .5rem set, line-height tightened to 1.2 and a bold weight. They use --font-heading and inherit their color. See Typography for the sizes.
Paragraphs#
All <p> elements have their margin-top removed and margin-bottom: 1rem set for easy spacing.
This is an example paragraph.
<p>This is an example paragraph.</p>Links#
Links have a default color (--link) and the browser's underline. They don't change based on whether someone :visited the link. On keyboard focus they show the global focus ring.
<a href="#">This is an example link</a>Link color is mixed with transparency through the --link-opacity custom property (Bootstrap's --bs-link-opacity), so you can change the opacity of a link's colour:
<a href="#" style="--link-opacity: .5">This is an example link</a>Placeholder links—those without an href—keep the link colour but, as in every browser, lose the underline and the pointer cursor. felt-css doesn't reset their colour.
<a>This is a placeholder link</a>Horizontal rules#
The <hr> element has been simplified. Similar to browser defaults, <hr>s are styled via border-top, have a default opacity: .25, and automatically inherit their border-color via color, including when color is set via the parent.
<hr>
<div class="text-success">
<hr>
</div>
<hr class="border border-danger border-2 opacity-50">
<hr class="border border-primary border-3 opacity-75">In the felt look, an <hr> is a row of running stitches instead of a line, in a darker tone of the felt underneath, so a color set on it or its parent doesn't tint it. With border utilities you get a plain coloured line, as in the clean look.
Lists#
All lists—<ul>, <ol>, and <dl>—have their margin-top removed and a margin-bottom: 1rem. Nested lists have no margin-bottom. The padding-left on <ul> and <ol> is set to 2rem.
- All lists have their top margin removed
- And their bottom margin normalized
- Nested lists have no bottom margin
- This way they have a more even appearance
- Particularly when followed by more list items
- The left padding has also been reset
- Here's an ordered list
- With a few list items
- It has the same overall look
- As the previous unordered list
<ul>
<li>All lists have their top margin removed</li>
<li>And their bottom margin normalized</li>
<li>Nested lists have no bottom margin
<ul>
<li>This way they have a more even appearance</li>
<li>Particularly when followed by more list items</li>
</ul>
</li>
<li>The left padding has also been reset</li>
</ul>
<ol>
<li>Here's an ordered list</li>
<li>With a few list items</li>
<li>It has the same overall look</li>
<li>As the previous unordered list</li>
</ol>For simpler styling, clear hierarchy, and better spacing, description lists have updated margins. <dd>s reset margin-left to 0 and add margin-bottom: .5rem. <dt>s are bolded.
- Description lists
- A description list is perfect for defining terms.
- Term
- Definition for the term.
- A second definition for the same term.
- Another term
- Definition for this other term.
<dl>
<dt>Description lists</dt>
<dd>A description list is perfect for defining terms.</dd>
<dt>Term</dt>
<dd>Definition for the term.</dd>
<dd>A second definition for the same term.</dd>
<dt>Another term</dt>
<dd>Definition for this other term.</dd>
</dl>Inline code#
Wrap inline snippets of code with <code>. Be sure to escape HTML angle brackets. Inline code is set in --font-mono at .875em and coloured with --danger-emphasis.
<section> should be wrapped as inline.
For example, <code><section></code> should be wrapped as inline.Code blocks#
Use <pre>s for multiple lines of code. Once again, be sure to escape any angle brackets in the code for proper rendering. The <pre> element is reset to remove its margin-top and use rem units for its margin-bottom. Unlike Bootstrap's, it is a padded, scrollable box with a sunken background, a border and rounded corners.
<p>Sample text here...</p>
<p>And another line of sample text here...</p>
<pre><code><p>Sample text here...</p>
<p>And another line of sample text here...</p>
</code></pre>Variables#
For indicating variables use the <var> tag.
<var>y</var> = <var>m</var><var>x</var> + <var>b</var>User input#
Use the <kbd> to indicate input that is typically entered via keyboard. It's a small dark key cap; nested <kbd>s are bold.
To edit settings, press Ctrl + ,
To switch directories, type <kbd>cd</kbd> followed by the name of the directory.<br>
To edit settings, press <kbd><kbd>Ctrl</kbd> + <kbd>,</kbd></kbd>Sample output#
For indicating sample output from a program use the <samp> tag.
<samp>This text is meant to be treated as sample output from a computer program.</samp>Tables#
Tables are slightly adjusted to style <caption>s (below the table, muted, left-aligned), collapse borders, and ensure consistent text-align throughout. Additional changes for borders, padding, and more come with the .table class.
| Table heading | Table heading | Table heading | Table heading |
|---|---|---|---|
| Table cell | Table cell | Table cell | Table cell |
| Table cell | Table cell | Table cell | Table cell |
| Table cell | Table cell | Table cell | Table cell |
<table>
<caption>
This is an example table, and this is its caption to describe the contents.
</caption>
<thead>
<tr>
<th>Table heading</th>
<th>Table heading</th>
<th>Table heading</th>
<th>Table heading</th>
</tr>
</thead>
<tbody>
<tr>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
</tr>
<tr>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
</tr>
<tr>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
<td>Table cell</td>
</tr>
</tbody>
</table>Forms#
Various form elements have been rebooted for simpler base styles. Here are some of the most notable changes:
<fieldset>s have no borders, padding, or margin so they can be easily used as wrappers for individual inputs or groups of inputs.<legend>s, like fieldsets, have also been restyled to be displayed as a heading of sorts.<label>s are set todisplay: inline-blockto allowmarginto be applied.<input>s,<select>s,<textarea>s, and<button>s have theirmarginremoved and inheritfontandcolor.<textarea>s are modified to only be resizable vertically as horizontal resizing often "breaks" page layout.<button>s havecursor: pointer.
These changes, and more, are demonstrated below.
<form>
<fieldset>
<legend>Example legend</legend>
<p>
<label for="rebootInput">Example input</label>
<input type="text" id="rebootInput" placeholder="Example input">
</p>
<p>
<label for="rebootEmail">Example email</label>
<input type="email" id="rebootEmail" placeholder="test@example.com">
</p>
<p>
<label for="rebootSelect">Example select</label>
<select id="rebootSelect">
<option value="">Choose...</option>
<optgroup label="Option group 1">
<option value="">Option 1</option>
<option value="">Option 2</option>
<option value="">Option 3</option>
</optgroup>
<optgroup label="Option group 2">
<option value="">Option 4</option>
<option value="">Option 5</option>
<option value="">Option 6</option>
</optgroup>
</select>
</p>
<p>
<label>
<input type="checkbox" value="">
Check this checkbox
</label>
</p>
<p>
<label>
<input type="radio" name="rebootRadios" value="option1" checked>
Option one is this and that
</label>
<br>
<label>
<input type="radio" name="rebootRadios" value="option2">
Option two is something else that's also super long to demonstrate the wrapping of these fancy form controls.
</label>
</p>
<p>
<label for="rebootTextarea">Example textarea</label>
<textarea id="rebootTextarea" rows="3"></textarea>
</p>
<p>
<label for="rebootDate">Example date</label>
<input type="date" id="rebootDate">
</p>
<p>
<label for="rebootRange">Example range</label>
<input type="range" id="rebootRange" min="0" max="10">
</p>
<p>
<button type="submit">Button submit</button>
<input type="submit" value="Input submit button">
<input type="button" value="Input button">
</p>
</fieldset>
</form>Address#
The <address> element is updated to reset the browser default font-style from italic to normal, and margin-bottom: 1rem has been added. <address>s are for presenting contact information.
1123 Fictional St,
San Francisco, CA 94103
P: (123) 456-7890 Full Name
first.last@example.com
<address>
<strong>ACME Corporation</strong><br>
1123 Fictional St,<br>
San Francisco, CA 94103<br>
<abbr title="Phone">P:</abbr> (123) 456-7890
</address>
<address class="mb-0">
<strong>Full Name</strong><br>
<a href="mailto:first.last@example.com">first.last@example.com</a>
</address>Blockquote#
The default margin on blockquotes is 1em 40px, so we reset that to 0 0 1rem for something more consistent with other elements.
A well-known quote, contained in a blockquote element.
<blockquote>A well-known quote, contained in a blockquote element.</blockquote>Inline elements#
The <abbr> element receives basic styling to make it stand out amongst paragraph text: a dotted underline and a help cursor. <mark> gets a soft mustard highlight, <small> is .875em, and <sub>/<sup> no longer change the line height.
The <abbr title="HyperText Markup Language">HTML</abbr> abbreviation element, some <mark>marked text</mark>, H<sub>2</sub>O and E = mc<sup>2</sup>.Summary#
felt-css doesn't restyle a bare <summary>; it keeps the browser's default cursor and marker. For a styled disclosure, use <details class="accordion-item"> (see the accordion).
HTML5 [hidden] attribute#
HTML5 adds a new global attribute named [hidden], which is styled as display: none by default. felt-css improves upon this default by making [hidden] { display: none !important; } to help prevent its display from getting accidentally overridden.
<input type="text" hidden>To merely toggle the visibility of an element, meaning its display is not modified and the element can still affect the flow of the document, use the .invisible class instead.