summaryrefslogtreecommitdiff
path: root/source/blog/2022
diff options
context:
space:
mode:
authorPrefetch2022-11-20 11:36:46 +0100
committerPrefetch2022-11-20 11:36:46 +0100
commit41420c0e32cba69d4f4e19175bd3350fed427275 (patch)
treea5391cc76fb1e46387384044f4d5f0218400cdb9 /source/blog/2022
parent4880f641ade11e60f18f907fdf0660ca349714a7 (diff)
Publish "Website adventures" part 2 about HTML and CSS
Diffstat (limited to 'source/blog/2022')
-rw-r--r--source/blog/2022/website-adventures-basics/index.md356
-rw-r--r--source/blog/2022/website-adventures-generators/index.md27
2 files changed, 376 insertions, 7 deletions
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 `&lt;details&gt;` 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.