Redesigning my website
...with the power of Astro and friendshipposted 2024-09-23
Today I redesigned my website. If you’re reading this, it’s probably that new website! Let’s talk about what changed and how I did it. (This one will be a short one.)
Motivations for redesigning
- Add better accessibility features
- Many people have complained about the colors, font, and layout. Let them change all of them
- Fix the janky CSS the current site relies on
- Fun fact: On the old site, you could scroll to extra whitespace on the side on Firefox Mobile, and only Firefox Mobile for some reason
- Clean up the messy Markdown plugins
- I use a few to fix some quirks in the rendered Markdown output, but I want to not rely on it anymore
- Having fun!
Picking a framework
This site, along with my “old” site, is Astro. I like Astro for a number of reasons:
- Simple component model with slots
- Static site generator by default
- Mix in other JS frameworks (e.g. Svelte, which I did!)
- You can write TypeScript
I ended up making a new project but I copied over 90% of the files, so I’m not really sure if this can be considered a “new” site. Was it a new site when I switched from Zola, taking the layout with it, even though it was an entirely new backend generator?
As I said above, I enabled the Svelte integration for some dynamic components (which we’ll talk about later).
Redoing the styling
My old CSS was a mess with hardcoded sizes and calc
everywhere. To make it more simple, I’ve ditched a majority of my headaches with the main container with some sizing fixes, along with using CSS variables to calculate the sizes that I need to hardcode. I used Sass to automatically generate some of the annoying bits.
New features
At the top of your screen is a nice path showing what file you’re in. You can click on each folder (or the root “notnite” node) to get to where you want to go.
The real star of the show, though, is the new theme button. Click on it to open a panel. This panel stores configuration in localStorage, and can change CSS classes on the fly. It’s the only part of the website that uses Svelte so far.
This was the hardest part of the entire redesign, and the main focus of it.
Applying themes without looking bad
The biggest issue was that the themes need to be applied before the page loads, or you’ll get a flash of the wrong color, which can be very disorienting. To solve this, I wrote some JavaScript at the root of the body tag marked with defer. It sets up the defaults and exposes some functions in the window
object so the Svelte component can also set the theme.
These exposed functions are hacky, but it works. This even means you can use them! Try running this in DevTools:
window.__notnite_theme_set("color", "nitelight");
I also manually edit the source URL of the Giscus frame when the color changes, so that it stays in sync with the theme of the site. Giscus, if you are unaware, is the comment section at the bottom of this blog.
Using the theme in CSS
With the classes at the root of the body, it’s pretty easy to apply them to other elements:
.fontInconsolata {
--font: "Inconsolata", monospace;
}
.fontInter {
--font: "Inter", sans-serif;
}
.positionRight main {
text-align: right;
}
$sizes: (
"Normal": 35rem,
"More": 50rem,
"All": 100%
);
@each $size, $value in $sizes {
// --size is needed on multiple components for proper sizing
.size#{$size} main,
.size#{$size} > .container,
.size#{$size} > pre,
.size#{$size} > img,
.size#{$size} > video {
--size: #{$value};
}
}
Functioning without JavaScript
Because this site is written with Astro, JavaScript is optional. If you have JavaScript disabled, I hide the settings button and replace it with an identical button that’s greyed out:
<noscript>
<button><!-- .... --></button>
<style>
.a11y {
display: none;
}
</style>
</noscript>
<A11y client:load />
The body has a noscript
class on it that sets default themes, accounting for the prefers-color-scheme
value. When the site loads with JavaScript enabled, the class is removed and the “real” one from localStorage is applied. I used Sass to generate the defaults:
// Color defaults
.noscript {
@each $key, $value in $nitefall {
--#{$key}: #{$value};
}
}
@media (prefers-color-scheme: light) {
.noscript {
@each $key, $value in $nitelight {
--#{$key}: #{$value};
}
}
}
// Color themes
.colorNitefall {
@each $key, $value in $nitefall {
--#{$key}: #{$value};
}
}
(Also, that codeblock syntax highlighting looks pretty bad, I’ll get around to wrangling Prism with better colors later.)
Final product
You’re looking at it! If you find any issues, feel free to leave a comment below, and I’ll try and fix it when motivation arrives. Here’s hoping it’s stable…