 Hey, everybody. What's up? It's Rob Dodson. Welcome back to the Alicast show. Today, we're going to be talking about focus rings. So the focus ring is the indicator that the browser uses on an element to indicate if it has focus and to indicate if that element is about to receive keyboard events. And the focus ring is really, really, really important for keyboard users because you can think of it kind of like their mouse pointer. It's their way of knowing which element they're about to click on or interact with using something like the space bar. Now, the problem with the focus ring and where I see some developers kind of running a foul here is the focus ring is kind of displayed inconsistently in the browser. And follow me over here on my laptop and I'll show you what I mean by that. So I've got a few elements on screen here. I've got an input text field. I've got a button. And I've got another button that I've actually styled to look kind of fancy. And I'll zoom in. And you'll see that when I click on this input text field, I see a focus outline. I see a focus ring right there. But when I click on this native button, I see the active state. But I don't see a focus ring drawn on top of it. And so already you're seeing that the browser is kind of trying to be smart here and it's trying to sort of differentiate based on sort of a heuristic between different elements. So when a user clicks on a button or they tap on a button, the browser is going to say, well, this user, they kind of know what they just went over and clicked on and they know what they just interacted with. So I don't need to draw a focus ring in that case. But for something like a text field, it can be really, really helpful to have that focus indicator, especially if you're working on like a long form and maybe you look away for a bit and you come back and you want to kind of see where your place is in the form. So there's an underlying heuristic that the browser uses to differentiate between mouse and keyboard focus on different elements. The problem, though, starts to happen, again, follow me over here to my laptop, when we have custom controls and custom elements. So this button that I've styled, this is still a native button element. When I click on it, now I see a focus indicator. And that's based entirely on the fact that I've sort of changed the default browser styling. And at this point, now the browser says, I guess I'm just going to draw a focus ring. You'll also see this if you create a custom control, you know, you create your own dropdown or something like that, and you give it a tab index. So opting something into the tab order, now when you click on it, it's going to display a focus ring. And this throws a lot of developers for a loop. They'll be building a UI widget. Suddenly, this ring starts appearing. They're not quite sure what to do, because for the mouse users out there, it's aesthetically unpleasing, right? It's not something they're used to seeing. They might not like the way that it looks. And so you might have your art director or somebody coming down and saying, hey, that thing looks weird, just remove it, okay? And if you go over to Stack Overflow or something like that, you just Google Stack Overflow, remove blue ring, and there's just an endless amount of answers here where people say, oh yeah, when you see that thing, just use the CSS style, outline none, and that'll get rid of the focus ring. The problem is it gets rid of the focus ring for everybody, including your keyboard users. And this is the real issue. Really what we need is the ability to differentiate between mouse and keyboard focus for different elements. And so we can have kind of two different experiences. Enter focus ring. So focus ring is a brand new CSS selector, it's part of the CSS level four selectors spec. I can show that to you here on my laptop. And what focus ring does is it says the focus ring pseudo class applies while an element matches the focus pseudo class and the UA or the user agent, basically the browser, determines via heuristics that the focus should be specifically indicated on that element, typically by a focus ring. So basically what this means is focus ring gives you the ability to opt into these same heuristics that the browser uses when they differentiate between mouse and keyboard users for things like inputs and buttons. Now as of today, there are no browsers that ship the focus ring pseudo class. It just landed in the spec very recently, but there is a polyfill which you can take advantage of in your application. So github.com slash wicg slash focus dash ring. Here's a polyfill created by my teammate Alice Boxhol and our friend, Brian Cardell. Focus ring polyfill is gonna apply a focus ring class to elements that sort of match the heuristics. And so that way you can say, ah, this element should definitely always draw a focus ring. It has this class. So, you know, I can put my own style on it or I can opt out of that. I'm gonna show you an example here. I've already downloaded the polyfill. I've got some HTML. This is that same example page that I showed you. So I've got an input. I've got a button. It just says hello world. And then I've got another button with a class on it. So it looks like kind of a nice big material design button. And what I'm gonna do is I'm gonna start by including the script for focus ring JS. And what that's gonna do is it's going to, here, I'll actually walk you through focus ring JS so you can kind of see how it works. So inside the JavaScript for this class, the first thing it does is it tries to set a flag to indicate if a keyboard action has just taken place. Then it sort of defines a white list of elements. And these are elements which should always display the focus ring. So for instance, something like input type equals text. Regardless of if that was clicked on with a mouse or a keyboard, we're saying it should always draw a focus ring, just like what the native browser does today. But you'll notice that button is not in this white list. So if someone clicks on a button, it's not gonna display the focus ring class. And therefore we can turn off the outline for our mouse users but still display it for our keyboard users. If we go down to the bottom, we can see that this element is actually, or this class is just going through and adding some event listener. So it adds a key down listener. And when someone presses a key, it sets that keyboard flag. And at this point it starts kind of a little keyboard throttle timer in about 100 milliseconds. So at that point, if anything else receives focus within that window, we're gonna assume the user is a keyboard user and we're going to apply the focus ring class to that element. So over here in my index file, I've included focus ring JS and what we should expect to see is this input should have the focus ring class. This button should not because it's not in the white list and this other button should not because it is also not in the white list. Over in my CSS file, because I can't just outright use, the colon focus ring pseudo class just yet, what the polyfill is gonna make available to me is just a regular focus ring CSS class and I can use a selector that looks like this. So what I'm saying here is for any element that is focused, that does not have a focus ring class on it, go ahead and remove the outline. So what that's saying is anything that a mouse user clicks on essentially, we're gonna not display the outline or anything that is not part of our white list, we're gonna not display the outline, anything that is in the white list or anything that has been interacted with the keyboard has a focus ring class, we will display the outline. Okay, so let's see how that works. We will go back over to the application that we were working with before. I will open up this div so you can kind of see our elements here and as I click on the input, you'll note that it gets a focus ring class added to it and so it also gets the native focus ring indicator. When I click on these buttons though, no focus ring class and so now this fancier button that I defined before is no longer displaying a focus ring. However, when I use my keyboard to navigate the page, I hit tab, I see a focus ring class on the input, I hit tab, I see it on the first button, I hit tab and I see it on that last button as well. So now we've been able to differentiate between our mouse and keyboard users and we can have the right experience for each modality. I also wanna point out that there is another library out there called WhatInput. This does a very similar thing to the focus ring polyfill. WhatInput has been around for a little bit longer. You can find that at 10.17 slash What-Input on GitHub. Again, does a very similar thing to the focus ring polyfill. It's been out there for a bit longer. So maybe try both, see which one you prefer. They have slightly different APIs, but definitely try and give one or both of these a shot in your application, figure out which one you prefer and make sure you're not just removing focus outlines throughout your app, because that's gonna create a really gnarly experience for your keyboard users. That about covers it for today. If you have any questions for me, as always, you can leave them in the comments below or you can hit me up on a social network of your choosing. As always, thank you so much for watching and I'll see you next time. Bye.