[00:00:13] Henri: I may discuss the Jamstack, I will talk about web performance, but I'm also a fan of accessibility, especially anything that has to do with the human visual system. Did you know that color contrast is the number one WCAG failure? Well, you do now. This is why I thought the next presentation would be very interesting. Here to build, or talk about building a color contrast checker using Eleventy Serverless is our good friend Ben Myers. Enjoy!
[00:00:44] Ben: You should be seeing a whole lot of purple. Fair warning, today's going to have a whole lot of purple!
[00:00:50] Alright. Howdy, howdy! It is an honor to kick off today's 11ties. I'm super excited to be here. Today I'm going to be demonstrating how to build a color contrast checker with Eleventy's hot new feature, Eleventy Serverless. I'm super excited to be going through this.
[00:01:05] Now, because this is a lightning talk, I know that this is going to go fairly quickly. There's going to be a lot of code that I have sped up the recordings of. And so, you're probably going to wanna see the source code, you're gonna wanna see the slides, you're gonna wanna see the actual demo. All of that is available for you at benmyers.dev/11ties. The slides will be forthcoming, but they will be at that destination as well. So if ever you need anything, that's where to go, is benmyers.dev/11ties.
[00:01:32] A bit about myself, just real quickly. Hi, I'm Ben. You can find me on Twitter at @BenDMyers. And the long story short is I blog and stream about accessibility and core web technologies and sometimes about Eleventy. So that is the world's quickest summary. My cat is just as famous as I am. His name is Tuna. He is delightful, and he's everyone's favorite coworker!
[00:01:56] Yeah! So what are we going to be doing today? We're going to be building a color contrast checker, an experience that looks an awful lot like this. It, you know, takes two hex code colors and it spits out their contrast ratio. Now we can imagine, if we were going to be doing this with Eleventy before Eleventy Serverless, we were going to have to generate a page for every possible combination, every pair of colors. So any two hex code colors.
[00:02:24] Assuming six digits for each hex code color, the math on that is astronomical. That would assume we would have about 2.75 × 10^14 pages that we would have to render. And we would pay that cost every time we rebuilt our dev server, as well as every time we redeployed! And that is hugely wasteful. Like, I just… I wouldn't want to make any changes. I wouldn't want to have to go in and, like, update the footer or anything like that anytime I needed to update the design because this is an exorbitant number of pages. So prior to Eleventy Serverless, we had no good way to handle anything of that scale with Eleventy, right? I'm sure that there were ways, there were workarounds, but now we have Eleventy Serverless, which is a first-class solution to this.
[00:03:13] So we're going to take this experience. I've actually already built out the template for this. It's got values hardcoded in it. We're going to take this experience and we're going to make it a serverless application.
[00:03:23] So, step one is we're going to be installing Serverless. You are going to need to have a version of Eleventy that is the 1.0 canary 39 or above or beta 1 through 4. And once you've got that installed, you can add the Serverless plugin to your Eleventy config like this. I'm actually on a canary, so we're going to see that I'm adding an input directory that is no longer necessary. I am behind the times here.
[00:03:51] But long and short, what we're saying is, hey, we're adding the Serverless plugin here. We're going to call this plugin
'onrequest'. You can call it whatever you want, but I'm just giving this this name because that's what makes sense to me, is like, oh, every time I request one of these pages, I'm going to return something. So I'm calling it
'onrequest'. And then I'm saying that my serverless functions will live in the
netlify/functions directory here. So that's, real quickly, all you need to do to add this to your Eleventy config.
[00:04:19] And then the next time you build your project, you're going to get a whole bunch of stuff like this. These are these serverless functions that are generated for you, all of that code. We actually don't want to deploy all of this. The only thing we really need to deploy is our
index.js. So we're going to go into our
.gitignore and exclude everything else. That way, Netlify can generate those other things for us during build time. So to do that, we ignore
netlify/functions — any file inside
netlify/functions except for that
[00:04:54] Now to call out, we could make changes to that
index.js if we wanted, specifically if we were interested in using Netlify's on-demand builders for caching our color contrast pages. However, as we're going to see later, I'm going to take advantage of query parameters in our routes, and that is not supported by Netlify's on-demand builders, so I'm going to use all the default serverless function configuration here. I'm not making any changes. But if you need, the Eleventy docs do tell you how you can use on-demand builders and what changes you would need to make to these files. So, that is itself a bit of a caveat.
[00:05:33] So now that we've got Eleventy Serverless all installed in our project, we need to make sure that our contrast ratio template is serverless. And so to do that, we're going to first go into our template. Here I've got my
contrast.html template. And I'm going to add a permalink! But unlike the permalinks that we're used to which are strings, this one is an object. It has a key of
onrequest, which matches what we called it in our
.eleventy.js, and the destination is
'/contrast/'. So anytime someone goes to the
/contrast/ route, it will be generated for them by the serverless function instead of using anything that was built during build time. So currently, there's no change to the experience here, just a change to how the page is actually created and delivered.
[00:06:20] So, we have now specified that this template is a serverless template and we can start to use some nifty things! Like, for instance, we can start to use query parameters that were applied whenever someone went to our page. So here, I'm just going to update the display so that we're no longer using our hardcoded hex codes, but rather we're using hex codes from the URL.
[00:06:42] So here we go! We're accessing the
.background properties, so if you use the
background query parameters, those are now injected into the page. And we can actually see that here. I've got the hex codes
#ee4433 in my query parameters. That "
%23," that's the URL-encoded hash. So we're now displaying the hex codes that were provided through the URL.
[00:07:12] So we're already starting to get some dynamic behavior depending on the query parameters that you provided when you hit this page, but the next thing is we need to make sure that the ratio actually works. Currently, the ratio is hardcoded to 21, and that would be kind of useless as a color contrast tool. So let's go ahead and generate our ratios.
[00:07:34] To do this, I'm actually going to use some computed data. So I'm creating a
contrast.11tydata.js data file. This is a data file that corresponds to the
contrast.html template. And in there, I'm creating some computed data. Specifically, a property called
ratio, which uses that foreground and background that was supplied by Eleventy Serverless, and it returns the ratio here. And then I'm actually creating a second computed data property called
formattedRatio, which does a bit of handy formatting because after, you know, two degrees of precision, you really don't need any more specificity there. So, this injects two new data properties into our data cascade: one called
ratio, which is the fully qualified ratio number, and then one called
formattedRatio, which is the truncated version of that. And it's specifically using those two query parameters.
[00:08:30] So now, at this point, we want to actually use this ratio in our templates. So let's go ahead and override our hardcoded ratio here. There we go! We provide our neatly formatted ratio. And now, whenever you get to this page, you can see that it says, like, oh, this specific pairing has a ratio of 3.37:1, or 3.86:1.
[00:09:24] I'm going to take advantage of the
foreground field gets translated into the
foreground query parameter. There we go. We've just added a handy form there.
[00:09:46] And now we can see it in action! Let's go ahead and, you know, go back to our page here. We're going to specify two colors here and we're going to navigate to another page, and we get a new ratio! And we can see that this works, you know, one more time, too!
[00:10:01] So this, at this point, now has all the full navigation we need. It's really starting to come together as an application, right? Now people don't even have to memorize the format of the URL. But I think we could go a little further. We can use Serverless to add some of the little things, the nice little details. Specifically, adding some nicer styles! Like, for instance, we can use our query parameters in our CSS here and create a neat little background that uses both of the supplied colors. Or we could go into our form and we could add some default values so that way, as you navigate between pages, it persists the value of your query parameters so it doesn't feel like it's resetting every time.
[00:11:10] So this is a quick little demo. I know it's been incredibly whirlwind and I do apologize for that. However, again, you can go to benmyers.dev/11ties for all the resources. And then if you want to specifically play around with this, which I highly recommend — it's a lot of fun — go to contrast-11ties.netlify.app. You'll be able to play with that very experience yourself. It's totally deployed. I'd love to know what you think. I'd love to be able to add more, like maybe guidance about what WCAG thresholds you're meeting and so forth.