diff options
author | Prefetch | 2022-11-20 11:36:46 +0100 |
---|---|---|
committer | Prefetch | 2022-11-20 11:36:46 +0100 |
commit | 41420c0e32cba69d4f4e19175bd3350fed427275 (patch) | |
tree | a5391cc76fb1e46387384044f4d5f0218400cdb9 | |
parent | 4880f641ade11e60f18f907fdf0660ca349714a7 (diff) |
Publish "Website adventures" part 2 about HTML and CSS
-rw-r--r-- | source/_includes/preamble.html | 2 | ||||
-rw-r--r-- | source/blog/2022/website-adventures-basics/index.md | 356 | ||||
-rw-r--r-- | source/blog/2022/website-adventures-generators/index.md | 27 | ||||
-rw-r--r-- | source/infra/css/main.css | 13 | ||||
-rw-r--r-- | source/know/concept/boltzmann-equation/index.md | 8 |
5 files changed, 384 insertions, 22 deletions
diff --git a/source/_includes/preamble.html b/source/_includes/preamble.html index 6953524..7b57115 100644 --- a/source/_includes/preamble.html +++ b/source/_includes/preamble.html @@ -17,7 +17,7 @@ {% if page.layout == "concept" or page.maths %} <link rel="stylesheet" href="/infra/css/katex.min.css?v=20221008"> {% endif %} -<link rel="stylesheet" href="/infra/css/main.css?v=20221108"> +<link rel="stylesheet" href="/infra/css/main.css?v=20221119"> {% if jekyll.environment != "development" %} <script data-goatcounter="https://prefetch.goatcounter.com/count" async src="/infra/js/count.js?v=20221103"></script> diff --git a/source/blog/2022/website-adventures-basics/index.md b/source/blog/2022/website-adventures-basics/index.md new file mode 100644 index 0000000..31e0fc3 --- /dev/null +++ b/source/blog/2022/website-adventures-basics/index.md @@ -0,0 +1,356 @@ +--- +title: "Adventures in making this website:<br>reviewing the basics" +date: 2022-11-20 +layout: "blog" +toc: true +--- + +Published on 2022-11-20. + +Making and managing this personal website has been an adventure. +In this series, I go over the technical challenges I've encountered +and philosophical decisions I've made, +and I review some of the tools I've used along the way. +After [part 1](/blog/2022/website-adventures-generators/), +this is part 2, with more coming soon. + + + +After the previous article about static site generators, +let's take a step back: as you probably know if you're reading this, +a modern websites consists of three components: +1. [HyperText Markup Language](https://en.wikipedia.org/wiki/HTML) (HTML), + an [Extensible Markup Language](https://en.wikipedia.org/wiki/XML) (XML) + that describes the structure of the page, + e.g. top navigation bar, footer, titles, paragraphs, etc. + For arguably historic reasons, + it does some basic styling too, like making text *italic*, + and it provides basic interactive elements like buttons. + In recent years, it's also been increasingly controlling + the browser's interaction with external resources. +2. [Cascading Style Sheets](https://en.wikipedia.org/wiki/CSS) (CSS) + that control the visual design of the page. + CSS consists of rules referring to certain HTML elements, + and set things like colours and fonts. + Due to limitations of HTML, + CSS also tells the browser how to handle the page's HTML structure, + by specifying e.g. elements' widths and positions. +3. [JavaScript](https://en.wikipedia.org/wiki/JavaScript) (JS), + or specifically its [ECMAScript](https://en.wikipedia.org/wiki/ECMAScript) (ES) standard, + is a programming language that can do many things: + it can interact with a "dynamic" copy + of the HTML structure to e.g. add interactive animations, + it can handle complex server-browser communications, etc.... + or it can mine cryptocurrencies behind your back. + In principle, JS is used to do anything that HTML and CSS can't, + but in practice some features of HTML/CSS are so obscure + that many web developers use JS anyway out of ignorance, or for compatibility. + +This website barely uses JS, so the rest of this article is just about HTML and CSS. +Let's start by asking ourselves if those technologies are any good... + + + +## The good: HTML + +Right-click on this page and select *"View Source"* (or something similar) +to see the HTML file where the magic happens +(if you're reading this on a mobile device, you'll just have to trust me when I say it's magic). +Looks like a mess, right? +Well, in my opinion, HTML (or really any XML) is a good fit for the web, +because its hierarchical structure is a natural way to describe UIs. + +However, the kind of UI being described by HTML has changed a lot over the decades: +once upon a time it was just one big block of text, +now we have interactive apps. +The web has outgrown a lot of HTML's original features, +but at the same time HTML has kept up with the Internet's needs just fine, +thanks almost entirely to the `<div>` tag. + +Sure, we could have some philosophical debates about HTML's design decisions. +Why is there a distinction between `<i>` and `<em>`? +What's the point of some of [HTML5](https://en.wikipedia.org/wiki/HTML5)'s +new semantic tags if I can just replace them with `<div>`s? +Don't the new media elements (e.g. `<picture>`) +maybe control the browser's behaviour a bit *too* explicitly? +And whose idea was [`<marquee>`](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/marquee) anyway? +But overall it holds up pretty well to scrutiny. + +I've heard people suggest that instead of XML, +HTML should've used [S-expressions](https://en.wikipedia.org/wiki/S-expression). +Yes, I wish we lived in a world where HTML and JS were both replaced by a single Lisp! +That would be wonderful, but unfortunately *this* is the world we live in; +the sooner we accept it, the better. +And if I'm honest, I like how XML shows me the element name in the closing tag)))))). + + + +## The bad: CSS + +CSS, on the other hand, is a pain. +I want the following statement on my gravestone: +*"At least 33% of the CSS you write is for fixing the unexpected behaviour of the other 67%"*. +I came up with this rule of thumb a few years ago, and I don't think it's failed me yet, +although note that I include code churn under "writing CSS". +My site's [`main.css`](/code/prefetch-jekyll/tree/source/infra/css/main.css) +is quite simple, but I've obsessed over it for many hours, +trying to trim all the fat without breaking anything. + +Although CSS is well-standardized, +browser compatibility appears to be a surprisingly big issue. +This why we have projects like +[`normalize.css`](https://github.com/necolas/normalize.css), +[`destyle.css`](https://github.com/nicolas-cusan/destyle.css), +and [`reseter.css`](https://github.com/resetercss/reseter.css), +which I learned about later than I should have. +See the vertical line under this page's header? +You wouldn't believe how many times its location surprised me +while testing different browsers and devices. +Sure, you can argue that using an `<hr>` isn't ideal here, +but isn't this its intended purpose? + +The fundamental issue is that CSS is trying to handle two things at the same time: +*formatting* and *layout*. +Formatting refers to fonts, colours, text alignment, cursor icon, borders, etc., +and is quite simple: it shouldn't be able to surprise you +and barely needs to adapt to its environment, +and can therefore easily be handled by CSS. + +Layout, however, is a hard problem. +Defining the positions and sizes of elements on *your* device is doable, +but what about other devices? +Does your text fit in that box? +Where did that awkward line break come from? +Those elements were side by side, +so why are they suddenly under each other, +and partially overlapping the rest of the page? +Half of writing CSS is getting things to look good on phones; +it's a lot harder than you'd expect! +Is this a phone, or an awkwardly-shaped desktop window? +Why is my font size not honoured on mobile? +Are you sure that isn't a tablet? +Or what if they connect their phone to a monitor? +Wait, is that a mouse? + +Nowadays, we have technology that makes layout easier, +like [flex](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox) +and [grid](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/Basic_Concepts_of_Grid_Layout) layouts, +but these are clearly afterthoughts. +The CSS language itself is very basic +(but still [Turing-complete](https://stackoverflow.com/a/5239256)), +resulting in quite repetitive code +with a lot of hard-coded values. +Some aspects are improved by e.g. [Sass](https://sass-lang.com/), +a "syntax wrapper" that helps avoid repetition. +But Sass doesn't address any fundamental issues, +and CSS' newer quality-of-life features +don't work well (or at all) on older browsers. + + + +## The ugly: Microsoft + +Ah, the subject of backwards compatibility, always a fun one. +When Microsoft released Windows 10 in July 2015, +they introduced the Edge browser and deprecated Internet Explorer (IE), +which in itself is just normal software churn. +The catch is that Windows 7 (then in extended support) +and Windows 8.1 (then still in mainstream support) +weren't getting Edge, and were thus stuck with IE version 11.0 forever. +In effect, they left many users without an up-to-date browser... +for 4 years, until they ported Edge to Windows 7 and 8.1 in June 2019. + +Okay, some people are using old Windows versions, +but who uses IE anyway, am I right? +Isn't its only function to download other browsers' installers? +Well, as of writing, IE makes up about 0.8% of the global desktop market +([source](https://gs.statcounter.com/browser-market-share/desktop/worldwide)). +In fact, for my job I need to use a virtual environment with only IE +(although it fortunately isn't exposed to the Internet). +When Microsoft decided to ship a browser with their OS, +it became their responsibility to maintain it for the fast-evolving Internet. +Microsoft, if you're reading this, +think of all the revenue you missed out on +by not tracking many of your users' browsing for 4 years! +Don't you want to be Google?! + +The reason I bring it up is that IE still casts a long shadow over web development, +due to its lack of support for many recent features in HTML, CSS and JS. +If you try to do something fancy, or just use modern best practices, +you need to ask yourself if you want to support IE. +If you choose yes, your implementation will probably look quite different. +Take a look at the ["Can I use?"](https://caniuse.com/) website +to check which browsers have which features; +often IE lags behind. + + + + +## Some tips and tricks + +As this website gradually became more advanced, +I found some interesting tricks to optimize things or enable new kinds of content. +In this series' future posts, I will dive into some topics in great detail, +but here I'm putting anything that won't fit elsewhere. + + + +### Automatic light/dark theme + +Depending on how you've configured your browser or operating system +(pretty much the same thing nowadays), +this website should have either a light or dark background. +I implemented the default light colour scheme as follows in CSS: + +```css +/* Light theme (default) */ +:root { + --b: #ededed; /* background color */ + --f: #121212; /* foreground color */ + --a: #0000ff; /* link color */ +} +``` + +The prefix `--` is required for so-called *custom properties*, +which will act as variables containing the colours of the theme. +The dark theme automatically overwrites these variables: + +```css +/* Dark theme */ +@media only screen and (prefers-color-scheme: dark) { +:root { + --b: #121212; + --f: #ededed; + --a: #ffff00; +} +} +``` + +Here [`@media`](https://developer.mozilla.org/en-US/docs/Web/CSS/@media) +is a *media query*, which tells CSS how to behave depending on the environment in which it's being interpreted. +The magic words here are `prefers-color-scheme: dark`, +such that, if your browser knows you like dark themes, +it will apply the corresponding CSS rules. + +If you were wondering: `only screen` means that the rule only applies +when the website is shown on a screen, instead of being printed. +But actually, that isn't the reason it's there (I mean, who prints webpages?). +The real reason is backwards compatibility with older browsers (i.e. IE) +that don't understand `prefers-color-scheme` (but do know `screen`), +to prevent them from applying the rules underneath anyway. +Basically, an old browser will see `only` while it's looking for a media type like `screen`; +since `only` isn't a valid type, it decides "this media query doesn't apply to me", +and moves on, ignoring the rules in this block. + +So, now that the variables `--b`, `--f`, and `--a` are set correctly, +we apply them using the function `var()` as follows... +assuming the browser even supports CSS variables like this: + +```css +body { + /* Light theme fallback (for IE, duh) */ + background: #ededed; + color: #121212; + /* Apply selected theme */ + background: var(--b); + color: var(--f); +} +``` + +In modern browsers that do support `var()`, +the latter lines simply overwrite the earlier ones. + +But what if there's some content on the website with hard-coded colours, like a logo? +Well, then things get a lot more complicated. +Either you rethink your design to allow the same image to be used in multiple themes, +or you serve different images. +The latter approach is becoming easier +thanks to the brand-new `Sec-CH-Prefers-Color-Scheme` HTTP Header, +which asks the server to send over dark-themed resources. +If you're interested, read [this article](https://web.dev/user-preference-media-features-headers/). + +For me that's all too much work, and this is supposed to be a static website after all, +meaning there shouldn't be any fancy client-server negotiations. +Instead, I chose my colours such that the dark theme is simply the inverse of the light one: +if an image is suitable to invert in this way too, +I simply give it the `.darkinv` class and apply the following CSS: + +```css +.darkinv {} +@media only screen and (prefers-color-scheme: dark) { + .darkinv {filter: invert(100%);} +} +``` + +This is what I've done on the [front page](/). +Obviously, IE doesn't support the `filter` property. + + + +### Collapsible content + +A common thing you might want to create is collapsible content: +a box that shrinks or expands when the user clicks a toggle. +Fortunately, HTML can do this out-of-the-box +using the `<details>` and `<summary>` elements. +Great, no JS required! +These tags were only recently added to HTML, +so (can you see where this is going?) they're [unsupported in IE](https://caniuse.com/details). +A demonstration: + +<details open style="border: 3px dotted; border-color: #121212; border-color: var(--f); padding: 0.25rem 0.5rem;"> +<summary style="display: block; color: #0000ff; color: var(--a);">Click me, I dare you</summary> +<em>Here we can bully IE users, because they can't close this `<details>` box: +IE is old and slow, and its users are even older and slower, +and they're also smelly! Take that!</em> +</details> + +So... time for JS? Well, fortunately, there's another way, +using just old-school HTML and CSS: + +<div class="proof"> +<input type="checkbox" class="proof" id="proof-example"/> +<label class="proof" for="proof-example">Click to show (IE welcome too)</label> +<div class="proof-hidden"> +<label class="proof" for="proof-example">Click to hide.</label> +<br> +<em>This is a safe space where users of all browsers can rejoice together in peace.</em> +</div> +</div> + +Pretty cool eh? This box is structured as follows, +using only `<div>`, `<input>` and `<label>`: +```html +{% raw %}<!-- Wrapper for applying CSS to the entire collapsible object --> +<div class="collapsible"> +<!-- (Invisible) checkbox that controls the content's visibility --> +<input type="checkbox" class="collapsible" id="my-example"/> +<!-- (Visible) text label standing in for the checkbox --> +<label class="collapsible" for="my-example">Click to show</label> +<!-- Wrapper for what should be hidden when the checkbox isn't checked --> +<div class="collapsible-hidden"> +<!-- Replacement text label for when the content is being shown --> +<label class="collapsible" for="my-example">Click to hide</label>{% endraw %} +<!-- The actual content that we want to show/hide --> +... +</div> +</div> +``` +And then the magic happens in CSS, where `x + y` means +"if `<x>` is immediately followed by `<y>` in the HTML document, +then apply this rule to the `<y>` element": +```css +/* Hide the content by default */ +.collapsible-hidden {display: none;} +/* Make the checkbox invisible */ +input.collapsible {display: none;} +/* If it's checked, then show the content... */ +input.collapsible:checked + label + .collapsible-hidden {display: block;} +/* ... and hide the original text label */ +input.collapsible:checked + label {display: none;} +``` + +Compared to `<details>`, this even gives some extra flexibility. +For an example of a page using this technique, +click [here](/know/concept/boltzmann-equation/) and scroll down. + diff --git a/source/blog/2022/website-adventures-generators/index.md b/source/blog/2022/website-adventures-generators/index.md index 0aba183..7e52f17 100644 --- a/source/blog/2022/website-adventures-generators/index.md +++ b/source/blog/2022/website-adventures-generators/index.md @@ -5,11 +5,14 @@ layout: "blog" toc: true --- +Published on 2022-11-15, last updated on 2022-11-20. + Making and managing this personal website has been an adventure. In this series, I go over the technical challenges I've encountered and philosophical decisions I've made, and I review some of the tools I've used along the way. -This is part 1, with more posts coming soon. +This is part 1, followed by [part 2](/blog/2022/website-adventures-basics/), +with more coming. @@ -201,14 +204,17 @@ after a few small tweaks like adding a navigation bar at the top of the page: ``` On the one hand, Hugo provides the convenient `.TableOfContents` variable -at the cost of control, unlike Zola, where we had to do it manually. -On the other hand, Hugo doesn't use block-based templates -and hence lacks a nice inheritance system like Zola's. -If you want to reuse a snippet, you put it in a file e.g. `navbar.html` +at the cost of control, unlike Zola, where we had to do it +manually. ~~On the other hand, Hugo doesn't use block-based templates +and hence lacks a nice inheritance system like Zola's~~ +[I stand corrected](https://lobste.rs/s/x2bknz/adventures_making_my_website_static_site#c_jbmpl2), +Hugo can do [Zola-style blocks](https://gohugo.io/templates/base/), +but it's hard to figure this out on your own. +If you want to reuse a snippet, you typically put it in a file e.g. `navbar.html` and include it as `{% raw %}{{ partial "navbar.html" . }}{% endraw %}`. Note the dot at the end... I'll get to that. -Overall, Hugo's approach to organizing templates feels "dumber" than Zola's, -although, to be fair, my website had become a lot more complicated by then. +Overall, Hugo's template organization feels "dumber" than Zola's, +although my requirements had become a lot more complicated by then. Like most SSGs, Hugo uses an external template engine, namely the [`text/template`](https://pkg.go.dev/text/template) Go package. @@ -472,3 +478,10 @@ Personally, compared to those two, I wouldn't recommend Hugo, but for some people (probably Go developers) it just might be what they're looking for. +EDIT: There exists an SSG called [Soupault](https://soupault.app/) +that has interesting alternative take on site generation. +Its creator [pitched it to me](https://lobste.rs/s/x2bknz/adventures_making_my_website_static_site#c_cgemzs), +and coincidentally its website includes [this comparison](https://soupault.app/tips-and-tricks/comparison) +with the SSGs discussed in this article. +Like I said, I don't intend to migrate again, like, *ever*, +so I'm writing this to spread the word about an, in my opinion, intriguing project. diff --git a/source/infra/css/main.css b/source/infra/css/main.css index 242c08d..0b1b47f 100644 --- a/source/infra/css/main.css +++ b/source/infra/css/main.css @@ -15,16 +15,11 @@ } /* Basic elements */ -/* See also https://github.com/necolas/normalize.css/blob/master/normalize.css */ html { line-height: 1.5; -webkit-text-size-adjust: none; text-size-adjust: none; } -hr { - box-sizing: content-box; - height: 0; -} body { background: #ededed; background: var(--b); @@ -46,13 +41,13 @@ h4 { font-style: italic; } a { - background-color: transparent; + background-color: transparent; /* normalize.css */ text-decoration: none; color: #0000ff; color: var(--a); } img { - border-style: none; + border-style: none; /* normalize.css */ display: block; max-width: 100%; height: auto; @@ -64,7 +59,6 @@ td {padding: 0 1.5rem;} font-family: monospace, monospace; font-size: 1em; }*/ -b, strong {font-weight: bolder;} /* Header and footer */ .nav { @@ -98,8 +92,7 @@ b, strong {font-weight: bolder;} /* IE-compatible collapsible proofs */ div.proof { - display: block; - border: dotted; + border: 3px dotted; padding: 0.25rem 0.5rem; } label.proof { diff --git a/source/know/concept/boltzmann-equation/index.md b/source/know/concept/boltzmann-equation/index.md index d2631b2..9cb3bcd 100644 --- a/source/know/concept/boltzmann-equation/index.md +++ b/source/know/concept/boltzmann-equation/index.md @@ -12,7 +12,7 @@ layout: "concept" Consider a collection of particles, each with its own position $$\vb{r}$$ and velocity $$\vb{v}$$. We can thus define a probability density function $$f(\vb{r}, \vb{v}, t)$$ -describing the expected number of particles at $$(\vb{r}, \vb{v})$$ at time $$t$$. +describing the expected particle count at $$(\vb{r}, \vb{v})$$ at time $$t$$. Let the total number of particles $$N$$ be conserved, then clearly: $$\begin{aligned} @@ -205,9 +205,9 @@ $$\begin{aligned} = \rho \Expval{(\vb{v} \!-\! \vb{V}) (\vb{v} \!-\! \vb{V})} \end{aligned}$$ -This leads to the expected result, -where $$\nabla \cdot (\rho \vb{V}\vb{V})$$ represents the fluid momentum, -and $$\nabla \cdot \hat{P}$$ the viscous/pressure momentum: +This leads to the desired result, +where $$\nabla \cdot (\rho \vb{V}\vb{V})$$ is the fluid momentum, +and $$\nabla \cdot \hat{P}$$ is the viscous/pressure momentum: $$\begin{aligned} 0 |