From 41420c0e32cba69d4f4e19175bd3350fed427275 Mon Sep 17 00:00:00 2001 From: Prefetch Date: Sun, 20 Nov 2022 11:36:46 +0100 Subject: Publish "Website adventures" part 2 about HTML and CSS --- .../blog/2022/website-adventures-basics/index.md | 356 +++++++++++++++++++++ .../2022/website-adventures-generators/index.md | 27 +- 2 files changed, 376 insertions(+), 7 deletions(-) create mode 100644 source/blog/2022/website-adventures-basics/index.md (limited to 'source/blog') 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:
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 `
` tag. + +Sure, we could have some philosophical debates about HTML's design decisions. +Why is there a distinction between `` and ``? +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 `
`s? +Don't the new media elements (e.g. ``) +maybe control the browser's behaviour a bit *too* explicitly? +And whose idea was [``](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 `
` 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 `
` and `` 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: + +
+Click me, I dare you +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! +
+ +So... time for JS? Well, fortunately, there's another way, +using just old-school HTML and CSS: + +
+ + +
+ +
+This is a safe space where users of all browsers can rejoice together in peace. +
+
+ +Pretty cool eh? This box is structured as follows, +using only `
`, `` and `