#137

🐦 A Note from Robin on Focus States

This week was an awful one for me. It was the stuff of Greek tragedies and epic, mythological disasters that are passed down from generation to generation. It was such a terrible week for me that in the long and distant future, fables and songs will be sung about how bad it all was. There will be handsome, tragic actors that will play me in movies and on stage, there will be short stories and epic poems lamenting just how miserable this week was for me.

Let me explain: the batteries in my mouse died.

But! I had also come down with a pretty nasty flu so I was unable to get out of the house to get some more. So I was devastated. I huffed and puffed for several hours before I realized this would perhaps make for a good experiment: could I use the web with nothing but a keyboard?

I booted up my machine and started flipping between applications with ease. I could load up Firefox, toggle between tabs, and I could focus on the search bar easily. Cool, neat, great. But what about the websites themselves?

Well, this is where I started to feel despondent again. I shortly realized that :focus states on most websites are basically just :hover states in disguise; it’s difficult to see which element is focused on a page when you hit TAB, forms are extremely difficult to use, and there’s so many times when you focus on something that you wouldn’t expect to.

And I think I know why this is a problem.

Around a decade ago when I started learning about web design we were taught never forget the :focus states. Let’s say you were designing a button or a form, we were always told that when we add :hover states then we should always remember to append the :focus state like this:

.btn {
  background-color: black;
  color: white;
}

.btn:hover,
.btn:focus {
  background-color: blue;
}

I can’t remember who taught me this but it was something that I just kept doing over and over again and I kept seeing folks recommend doing it this way, too. In books and podcasts and blogs – everyone recommended that we should never forget the :focus state for accessibility reasons but basically everyone argued that it’s essentially a duplicate :hover state.

Now a decade later here’s why I think that’s bad design: with :hover states they’re mostly an indication that you can click something. A little animation, a tiny change in color or an underline shows that yes, I am a clickable thing. These effects can be subtle because as a user you already know where the mouse is – it was you that moved it over that widget.

But with a :focus state our users don’t now where they are. That’s because it’s difficult to tell what happens when you hit TAB and which element is going to be focused next – so that visual cue needs to be way less subtle. Focus states must be much more prominent to help point users in the right direction.

In other words, our :focus and :hover states need to be entirely separate from one another, like this:

.btn {
  background-color: black;
  color: white;
}

.btn:hover {
  background-color: blue;
}

.btn:focus {
  outline: 2px solid yellow;
}

So this week of using the web with just my keyboard has entirely convinced me that this area of accessibility is mostly overlooked by modern web designers, and it’s something that I’ve been pretty bad at, too. But if we really want our websites to be device agnostic then we need to care deeply about the :focus states.

It’s a small thing to care about but it makes an enormous difference in the long run.


📝 Good Stuff from the Blog

HTML, CSS and JS in an ADD, OCD, Bi-Polar, Dyslexic and Autistic World. Tim Smith shares his story of learning. Here’s his intro:

I have ADDOCDBi-Polar, Dyslexia… and not to mention that I am on the Autism spectrum. This combination (apart from causing me to feel a lot of personal shame) makes coding very hard — especially learning how to code, which I am trying to do. Things get mixed up in my head and appear backwards to the point that I find it nearly impossible to focus any longer than 15-20 minutes at a time.

Lots of interesting stuff in here as Tim’s journey is ongoing. His favorite way to learn? Video tutorials.


Styling Based on Scroll Position. The only native web technology that can know and respond to scroll position is JavaScript, but often the appropriate native technology to deal with it is CSS. Let’s bridge that gap in a couple of different performance-minded ways.


Using React Loadable for Code Splitting by Components and Routes.

Speaking of React links… we drop quite a few of them on Twitter, grouped up like this, and recently, threaded. Maybe someday we can group them all together in a micro site kinda thing, although I just saw someone do that pretty nicely lately!


Extracting Text from Content Using HTML Slot, HTML Template and Shadow DOM. This is more clever than it got credit for! It’s one possible answer to “Gosh, I wish I could do pull quotes without needing to replicate markup.” Although it still requires JavaScript. Maybe element() is a good solution in the future, which Preethi has also written about!


Learning to Learn. Sarah Drasner has loads of helpful stuff for us all:

I used to be a college professor, and so I still organize my own learning as though I’m teaching. I even still use a paper planner designed for teachers. I’ll show you how I do it in case it’s helpful.


We ended up talking typography just a smidge more than usual last week! Taimur Abdaal took aim at code-focused beginners in Typography for Developers. Robin got wonderfully practical in Six tips for better web typography. Limit that line length people! And don’t get too gosh-danged thin with those fonts. Have you seen the new Gmail mobile app? Some usage of thin might be OK, but it’s THIN EVERYWHERE and doesn’t help with any hierarchy.


This week’s newsletter is brought to you by CodePen PRO. There is a whole slew of features you get access to when you upgrade from a free account on CodePen. One of them is Live View, which gives you a real-time preview of your code at a URL you open on any number of other devices and browsers. No need to refresh as you code, that happens automatically!