Title:  Style-a-blog
Date:   2025-02-16T14:46:36-04:00
---
Originally when writing the blog, I just grabbed an existing stylesheet from a [blog][1] and [site][2] that I liked. It worked great, but it contains a lot of things I don't need.

I want to achieve a similar design with the minimal amount of CSS possible. I want it to be semantic, minimal, fast ... basically - Boring with a capital B.

In the same spirit of "build-a-blog", I will start from scratch and write and take notes as I go.

CSS in 2025 is really insane to look at compared to the early-mid 2010s where most of my experience lies.

* [Custom properties (variables)][3]
* [Grid layouts][4]
* [Nesting and child selectors][5]
* [Built in color-scheme light/dark helper][6]

All the nice features are right there and well supported making a preprocessor or polyfilling unnecessary.

A few tools that will make this a bit easier:

A static file server with sane defaults for local dev and static pages: <https://codeberg.org/cfebs/srv>
Basically just a golang `http.FileServer` that uses `Cache-Control: "no-cache, no-store"` by default.

And something to run our build when files change. In the spirit of homebrewing boring stuff - I made `~/bin/make-watch`

```bash
last_run_seconds=0
grace_seconds=1
inotifywait -r -m --exclude "${dir}/.git\/" -e modify -e create -e delete "$dir" | while read -r event; do
	if [[ $last_run_seconds -eq 0 ]]; then
		make "$@"
		last_run_seconds="$SECONDS"
		continue;
	fi

	if [[ $SECONDS -ge $((last_run_seconds + grace_seconds)) ]]; then
		# reset last_run_seconds if enough time has elapsed
		last_run_seconds=0
	fi
done
```

`inotifywait` spits out lines of events when files change based on the options you want - here it's just modify, create, delete events in the directory.

The [`$SECONDS`](https://man.archlinux.org/man/bash.1.en#SECONDS) logic just ensures that `make` does not run N times if N files change in a fraction of a second.

Now lets go!

## From scratch

Firstly I want to make sure this looks decent across many browsers. So that means considering a normalize or CSS reset.

<https://github.com/necolas/normalize.css> is probably the gold standard of this still to this day. So lets just minify it and dump it at the head of our `style.css` file

```
❯ curl -sL 'https://necolas.github.io/normalize.css/latest/normalize.css' -o /tmp/normalize.css
❯ sass --no-source-map --style compressed /tmp/normalize.css /tmp/normalize.min.css
❯ cat /tmp/normalize.min.css
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
```

Now to pick some colors starting with dark mode as it's my system preference.

```
:root {
  color-scheme: light dark;
}
```

This alone gives you a pretty decent base for a dark mode in most browsers.

![base styles test](/img/style_a_blog_1.png)

At this point I might consider just leaving the colors up to the browser! Why not, the main goal here is just readability.

As you can see from the screenshot, the normalize is working pretty well. But we need to settle on font and size.

```css
html {
	font-size: 16px;
	font-family: sans-serif;
    line-height: 1.4;
}
```

Now to some layout stuff. I just want a simple narrow main content column which will be the `<main>` element. Basically this:

```html
<main>
    <nav>
        <!-- global top nav -->
    </nav>
    <section class="content">
        <!-- where blog list/post will be rendered -->
    </section>
    <footer>
        <!-- global footer -->
    </footer>
</main>
```

And just a bit of media query stuff to make it look nice on mobile.

```css
main {
	width: 600px;
	margin: 0 auto;
}

@media (width < 600px) {
	main {
		width: 100%;
		margin: auto;
	}

    section.content {
        padding: 0 1rem;
    }
}
```

Believe it or not, this is about all you need for a readable web page.

## Tweaks and extras

A few more things that I want to differ from browser defaults.

* Remove underline from header links in the markdown rendered output.
* `<pre>` monospaced font is a bit large by default.
* Inline `<code>` tags get a little padding to separate them while reading.
* Use [`highlight.js`](https://highlightjs.org/) and a theme [chalk](https://github.com/highlightjs/highlight.js/blob/main/src/styles/base16/chalk.css)
* A few horizontal lines wow!

## Conclusion

There is nothing that profound here. But if the goal is simplicity and readability, browser defaults and simple HTML semantics take you _very_ far.

And now I can say something like "the browser and importantly _the user_ should decide how they want to view their text". In reality I'm just a bit lazy.

See also:

* <https://motherfuckingwebsite.com>
* <http://bettermotherfuckingwebsite.com>
* <https://thebestmotherfucking.website>

[1]: https://drewdevault.com/
[2]: https://sr.ht/
[3]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_cascading_variables/Using_CSS_custom_properties
[4]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_grid_layout
[5]: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_nesting/Using_CSS_nesting
[6]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/light-dark
