Ad Astro!
I’ve rebuilt my blog. Again. It’s been a couple of years since I last wrote something here, but I thought it might be time to pick it up again.
This time the blog is built on Astro and the entire conversion took me less than a day. I then spent some time tweaking it and adding some fun css effects.
I realized that last time i rebuilt my blog it took a lot more effort. I had my blog in Jekyll that had a completely different structure of content. I had to add redirects, rewrite every blog post in markdown, setup a new rss feed that I had to build from scratch. Nothing too difficult, just time consuming.
This time all I did was run npm create astro@latest, then I selected the blog template already available. I copied all my .md files and images from my old blog into the new template, added som front-matter to each of them and the blog was up and running. Statically generated, a full 100/100/100/100 score on lighthouse and next to zero configuration on my part. Amazing!
Then came the fun part, making the blog my own. I’ve kept some parts of the original CSS, but have rewritten most of it. I’ve added a fun little intersection observer interaction when you scroll through the blog posts. The code is minimal and looks like this:
const options: IntersectionObserverInit = {
threshold: 0.1,
};
const callback: IntersectionObserverCallback = (entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
entry.target.classList.add("show");
} else {
entry.target.classList.remove("show");
}
});
};
const observer = new IntersectionObserver(callback, options);
const posts = document.querySelectorAll(".post");
posts.forEach((el) => observer.observe(el));
First off I set a threshold for how much of an element needs to be in the viewport for the intersection observer to fire. I then set up the actual callback that will be run everytime an element intersects, just adding or removing the class show if the element is intersecting or not. Then we create the actual observer and tells it to observe every element with the class .post.
The rest is up to CSS:
.post {
opacity: 0;
scale: 0;
transition: all ease-in-out 400ms;
}
.post.show {
opacity: 1;
scale: 1;
}
That simple! If it’s a post it’s transparent and has a scale of 0. If it also has the class show we transition to full opacity and scale.
I then considered how I wanted the top menu to behave and look. I remembered seeing something cool that Kevin Powell posted a video about a while ago. Creating an effect that follows your cursor as you hover a link. It took a while to achieve the effect I wanted but I’m pretty happy with the result. Hover or focus a link in the top menu to see it in action.
Creating this effect requires css anchor positions which is currently not supported in Firefox, but can be enabled using the layout.css.anchor-positioning.enabled flag.
Finally I removed all the large images the blog template contained. They were a significant load, especially in the blog list. I opted instead for a simple linear gradient to separate the posts. I am using an upcoming css feature for the corner shapes though.
@supports (corner-shape: squircle) {
corner-shape: squircle;
}
This is a cool feature that still has limited availability, but we will just fall back to regular border-radius in case it’s missing. You can read more about it here.
I will talk more about Astro and why it’s so awesome in a future post. My blog isn’t the only thing I’ve built with it recently…