2025-02-16 16:25:23 -05:00
Title: Style-a-blog
Date: 2025-02-16T14:46:36-04:00
---
2025-02-16 21:07:55 -05: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.
2025-02-16 16:25:23 -05:00
2025-02-16 21:07:55 -05:00
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.
2025-02-16 16:25:23 -05:00
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 >
2025-02-16 21:07:55 -05:00
Basically just a golang `http.FileServer` that uses `Cache-Control: "no-cache, no-store"` by default.
2025-02-16 16:25:23 -05:00
2025-02-16 21:07:55 -05:00
And something to run our build when files change. In the spirit of homebrewing boring stuff - I made `~/bin/make-watch`
2025-02-16 16:25:23 -05:00
```bash
2025-02-23 16:40:46 -05:00
last_run_seconds=0
grace_seconds=1
2025-02-16 21:18:49 -05:00
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"
2025-02-16 16:25:23 -05:00
continue;
fi
2025-02-16 21:18:49 -05:00
if [[ $SECONDS -ge $((last_run_seconds + grace_seconds)) ]]; then
# reset last_run_seconds if enough time has elapsed
last_run_seconds=0
fi
2025-02-16 16:25:23 -05:00
done
```
2025-02-16 21:07:55 -05:00
`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.
2025-02-16 21:09:51 -05:00
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.
2025-02-16 21:07:55 -05:00
Now lets go!
2025-02-16 16:25:23 -05:00
## From scratch
Firstly I want to make sure this looks decent across many browsers. So that means considering a normalize or CSS reset.
2025-02-16 21:07:55 -05:00
< 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
2025-02-16 16:25:23 -05:00
```
❯ 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;
}
```
2025-02-16 21:07:55 -05:00
This alone gives you a pretty decent base for a dark mode in most browsers.
2025-02-16 16:25:23 -05:00
2025-02-16 16:49:48 -05:00

2025-02-16 16:25:23 -05:00
At this point I might consider just leaving the colors up to the browser! Why not, the main goal here is just readability.
2025-02-16 21:07:55 -05:00
As you can see from the screenshot, the normalize is working pretty well. But we need to settle on font and size.
2025-02-16 16:25:23 -05:00
```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 >
2025-02-16 16:29:49 -05:00
<!-- global footer -->
2025-02-16 16:25:23 -05:00
< / footer >
< / main >
```
2025-02-16 21:07:55 -05:00
And just a bit of media query stuff to make it look nice on mobile.
2025-02-16 16:25:23 -05:00
```css
main {
width: 600px;
margin: 0 auto;
}
@media (width < 600px ) {
main {
width: 100%;
margin: auto;
}
section.content {
padding: 0 1rem;
}
}
```
2025-02-16 21:07:55 -05:00
Believe it or not, this is about all you need for a readable web page.
2025-02-16 16:25:23 -05:00
2025-02-16 21:07:55 -05:00
## Tweaks and extras
2025-02-16 16:25:23 -05:00
A few more things that I want to differ from browser defaults.
2025-02-16 21:07:55 -05:00
* Remove underline from header links in the markdown rendered output.
2025-02-16 16:25:23 -05:00
* `<pre>` monospaced font is a bit large by default.
* Inline `<code>` tags get a little padding to separate them while reading.
2025-02-16 21:21:16 -05:00
* Use [`highlight.js` ](https://highlightjs.org/ ) and a theme [chalk ](https://github.com/highlightjs/highlight.js/blob/main/src/styles/base16/chalk.css )
2025-02-16 21:07:55 -05:00
* A few horizontal lines wow!
2025-02-16 16:25:23 -05:00
## 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.
2025-02-16 21:07:55 -05:00
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 >
2025-02-16 16:25:23 -05:00
[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