Being able to do everything from a single API call is not only a big improvement from my initial proof of concept for this version, but an incredibly big improvement from the prior version, which used an API call for each category. This marks a huge step forward in my problem solving abilities, so rather than be mortified by the last version (OK, I’m still a little mortified!), I’m going to be proud of the improvements I’ve made over the last two years.
A lot of this will go in the update of the Airtable and Eleventy article, but here are some particulars on the filtering.
I used the randItem filter from 11ty Rocks to display a “Random Dataset of the Day”. Since Eleventy only pulls from the API on build, I used Zapier to schedule a daily build at Netlify. This displays a new random dataset and picks up any datasets I’ve added to Airtable since the last build, making maintenance a snap.
The All Datasets page displays alphabetically and the sort order is set at Airtable. But on the category pages the default listing is to display by most recently added. With some search engine luck I found this approach and was able to create a filter to sort by title to keep the same approach used on the All Datasets listing.
The filter gets added in eleventy.js
…
config.addFilter("sortByTitle", arr => {
arr.sort((a, b) => (a.title) > (b.title) ? 1 : -1);
return arr;
});
And then used in the for loop in the template…
{% for datakey in all | sortByTitle %}
...
{% endfor %}
The set-up is similar for the Recently Added page. The filter gets added in eleventy.js
…
config.addFilter("sortByNewest", arr => {
arr.sort((b, a) => (a.date) > (b.date) ? 1 : -1);
return arr;
});
And then used in the template…
{% for datakey in all | sortByNewest | limit(5) %}
...
{% endfor %}
I’m also using the limit filter from 11ty Rocks to set the amount of most recent datasets to return.
In the previous version the header was sticky and navigation sidebar was fixed with scrolling on larger screens. Generally I like this sort of layout for documentation or for browsing listings, but there are issues with screen reflow when zooming out the screen size. The previous version became less usable around 240% zoom.
In the current version everything flows nicely and it’s easy to read all the way up to 500%.
Other improvements include visible focus states and color contrast that meets WCAG AA standards in both the light and dark mode.
The current set up uses the visitor’s system-level settings, but I want to add to add the ability toggle sooner rather than later. I tried to implement the Piccalilli user controlled dark or light mode with no luck. I already had the current implementation working by time I tried it, and I’m also using a LOT of custom properties for the themes, but I think my lack of JavaScript skill was the real culprit. Rather than hold up the latest version I decided I’ll put this one on the to do list and come back to it.
The menu toggle is simple yet progressively enhanced to work when JavaScript is disabled or fails to load. It uses the “no-js” fallback approach, which can easily cause accessibility issues. I tested in VoiceOver as well as keyboard-only with JavaScript enabled and disabled and it worked well. My testing was very limited, but hopefully it will work well for everyone.
For a more robust and bulletproof approach Andy Bell has a great premium tutorial at Piccalilli. The membership price recently dropped making it easier to avail yourself of top-notch educational content! I want to improve my JavaScript skills to really understand more about resizeObserver and other more advanced topics before I try my hand at that one. But for now I feel like the site offers a good experience.
Filed under “know thy audience”, when doing any horse racing related project I make sure to do a quick pass in IE11 on my work machine (don’t ask!). The core horse racing audience generally skews older and is less likely to keep their devices up to date. Since I use custom properties the site pretty much renders as black and white in IE11. I have shadows on the dataset container and tags, and originally had them directly in their respective class selectors. They looked a bit odd in the “no color” version so I moved them to custom properties to keep them from rendering in IE11. This site basically looks like a generic food label in IE, and I have to admit that I kind of like it.
I also took a quick look with Edge on my work machine and was surprised to discover that it was an older version (44). I discovered this because the spacing was off in several areas and I realized that clamp() was not supported in that version. I should’ve thought of this level of progressive enhancement before, but it lead me to figure out that defaults can be set in combination with clamp()
, which allows unsupported browsers to pick-up the non-clamp property.
.dataset-container {
background: var(--dataset-bg);
padding: 1rem;
padding: clamp(1rem, 2vw, 1.25rem);
border: 1px solid var(--dataset-border);
box-shadow: var(--shadow-lg);
}
In the above example browsers that don’t support clamp()
use padding: 1rem while the others use clamp()
.
Performance improvements are no surprise when going from a site that did an API call on every page to a static site. But it did surprise me that the previous version’s performance scores weren’t worse, not that they’re good, but I imagined much worse.
The performance metrics show the details of the improvements…
Performance Metric | Previous Version | Current Version |
---|---|---|
First Contentful Paint | 1.5s | 0.8s |
Speed Index | 1.7s | 0.8s |
Largest Contentful Paint | 3.2s | 1.7s |
Time to Interactive | 3.5s | 0.8s |
Total Blocking Time | 160ms | 0 |
Cumulative Layout Shift | 0.113 | 0.01 |
Another area of performance improvement was moving from Tailwind CSS to handwritten CSS. Tailwind isn’t necessarily a performance issue, but I used it as is with no optimization, mostly because I didn’t (and arguably still don’t!) know how to use build tools.
Here’s a comparison using CSS Stats
CSS Stat | Previous Version | Current Version |
---|---|---|
File size | 566kb | 8kb |
Gzipped file size | 77kb | 2kb |
Rules | 9,901 | 78 |
Selectors | 9,969 | 101 |
Declarations | 10,988 | 244 |
Properties | 117 | 100 |
ID | 2 | 0 |
Class | 9,834 | 59 |
Pseudo class | 3,837 | 19 |
Pseudo element | 12 | 5 |
No surprises that there were drastic reductions, you can also view the full stats for the All Datasets listing page at CSS Stats.
As mentioned in the Filtering section, I set up daily build at Netlify using Zapier. API calls are only made at build time, so this ensures that there will be a new Random Dataset of Day on the homepage and that any datasets I’ve added to Airtable will picked up daily.
I changed a couple of urls from the previous version so I set up redirects for those changes. Netlify offers a couple of different approaches to handle redirects. I went with the redirects file. To make sure it ends up in the directory that’s deployed I added this to my eleventy.js
file…
config.addPassthroughCopy('./src/_redirects');
Finally, I wasn’t originally going to have individual pages for each dataset, but I realized this would make it easier to share and reference them. I used this handy approach from the Eleventy Docs.
Knocking this one off the list was a big accomplishment, but there’s always something else to do. Here’s what I’ll be focusing on next.