Hey all you wonderful developers out there! In this post, I am going to take you through creating a simple contact form using semantic HTML and an awesome CSS pseudo class known as :focus-within
. The :focus-within
class allows for great control over focus and letting your user know this is exactly where they are in the experience. Before we jump in, let’s get to the core of what web accessibility is.
Form Accessibility?
You have most likely heard the term “accessibility” everywhere or the numeronym, a11y. What does it mean? That is a great question with so many answers. When we look at the physical world, accessibility means things like having sharps containers in your bathrooms at your business, making sure there are ramps for wheel assisted people, and having peripherals like large print keyboards on hand for anyone that needs it.
The gamut of accessibility doesn’t stop there, we have digital accessibility that we need to be cognizant of as well, not just for external users, but internal colleagues as well. Color contrast is a low hanging fruit that we should be able to nip in the bud. At our workplaces, making sure that if any employee needs assistive tech like a screen reader, we have that installed and available. There are a lot of things that need to be kept into consideration. This article will focus on web accessibility by keeping the WCAG (web content accessibility guidelines) in mind.
This pseudo class is really great when you want to emphasize that the user is in fact interacting with the element. You can change the background color of the whole form, for example. Or, if focus is moved into an input, you can make the label bold and larger of an input element when focus is moved into that input. What is happening below in the code snippets and examples is what is making the form accessible. :focus-within
is just one way we can use CSS to our advantage.
How To Focus
Focus, in regards to accessibility and the web experience, is the visual indicator that something is being interacted with on the page, in the UI, or within a component. CSS can tell when an interactive element is focused.
Always make sure that the focus indicator or the ring around focusable elements maintains the proper color contrast through the experience.
Focus is written like this and can be styled to match your branding if you choose to style it.
:focus {
* / INSERT STYLES HERE /*
}
Whatever you do, never set your outline to 0
or none
. Doing so will remove a visible focus indicator for everyone across the whole experience. If you need to remove focus, you can, but make sure to add that back in later. When you remove focus from your CSS or set the outline to 0
or none
, it removes the focus ring for all your users. This is seen a lot when using a CSS reset. A CSS reset will reset the styles to a blank canvas. This way you are in charge of the empty canvas to style as you wish. If you wish to use a CSS reset, check out Josh Comeau’s reset.
*DO NOT DO what is below!
:focus {
outline: 0;
}
:focus {
outline: none;
}
Look Within!
One of the coolest ways to style focus using CSS is what this article is all about. If you haven’t checked out the :focus-within
pseudo class, definitely give that a look! There are a lot of hidden gems when it comes to using semantic markup and CSS, and this is one of them. A lot of things that are overlooked are accessible by default, for instance, semantic markup is by default accessible and should be used over div’s at all times.
<header>
<h1>Semantic Markup</h1>
<nav>
<ul>
<li><a href="/">Home</a></li>
<li><a href="/about">About</a></li>
</ul>
</nav>
</header>
<section><!-- Code goes here --></section>
<section><!-- Code goes here --></section>
<aside><!-- Code goes here --></aside>
<footer><!-- Code goes here --></footer>
The header
, nav
, main
, section
, aside
, and footer
are all semantic elements. The h1
and ul
are also semantic and accessible.
Unless there is a custom component that needs to be created, then a div
is fine to use, paired with ARIA (Accessible Rich Internet Applications). We can do a deep dive into ARIA in a later post. For now let’s focus…see what I did there…on this CSS pseudo class.
The :focus-within
pseudo class allows you to select an element when any descendent element it contains has focus.
:focus-within
in Action!
HTML
<form>
<div>
<label for="firstName">First Name</label><input id="firstName" type="text">
</div>
<div>
<label for="lastName">Last Name</label><input id="lastName" type="text">
</div>
<div>
<label for="phone">Phone Number</label><input id="phone" type="text">
</div>
<div>
<label for="message">Message</label><textarea id="message"></textarea>
</div>
</form>
CSS
form:focus-within {
background: #ff7300;
color: black;
padding: 10px;
}
The example code above will add a background color of orange, add some padding, and change the color of the labels to black.
The final product looks something like below. Of course the possibilities are endless to change up the styling, but this should get you on a good track to make the web more accessible for everyone!
Another use case for using :focus-within
would be turning the labels bold, a different color, or enlarging them for users with low vision. The example code for that would look something like below.
HTML
<form>
<h1>:focus-within part 2!</h1>
<label for="firstName">First Name: <input name="firstName" type="text" /></label>
<label for="lastName">Last Name: <input name="lastName" type="text" /></label>
<label for="phone">Phone number: <input type="tel" id="phone" /></label>
<label for="message">Message: <textarea name="message" id="message"/></textarea></label>
</form>
CSS
label {
display: block;
margin-right: 10px;
padding-bottom: 15px;
}
label:focus-within {
font-weight: bold;
color: red;
font-size: 1.6em;
}
:focus-within
also has great browser support across the board according to Can I use.
Conclusion
Creating amazing, accessible user experience should always be a top priority when shipping software, not just externally but internally as well. We as developers, all the way up to senior leadership need to be cognizant of the challenges others face and how we can be ambassadors for the web platform to make it a better place.
Using technology like semantic markup and CSS to create inclusive spaces is a crucial part in making the web a better place, let’s continue moving forward and changing lives.
Check out another great resource here on CSS-Tricks on using :focus-within.
Welcome back!
Glad to be back!
For readers, I want to caution against following both the examples in this post exactly.
If you are going to color the background of the entire form, then consider something that does not have such a dramatic contrast difference. For some readers too much of a change (dark to light, for example) can cause pain. If they are using a screen magnifier then their entire screen could become a glare fest. A subtler change, such as a semi-transparent color might be better.
Scaling text (even making it bold) can be a problem for screen magnifier users. It may push the field they had centered in their view out of sight, forcing them to have to shift their magnifier around for every field. In this case, a much fatter outline on the field or a row-level subtle background shift may do the job.
Appreciate that feedback Adrian! Would you be interested in writing for CSS-Tricks? I know, I would personally love to have ya contribute.
Challenge: now add a captcha and sostain accesibility.
Wait… a new post… is this a dream?
It’s a reality!
Great post!
:focus-within
is one of those CSS tools you can easily forget about so it’s great to have this reminder about it!Also awesome to see CSS Tricks is back :)
Another good example could be lost of cards with anchor tag. Tabbing through cards will receive focus behaviour because element with in received focus.
I think, the only way to make it possible without focus-within, is to make the card anchor element.
Thanks for dropping that info!
This was such a great post that I have read. I will be sharing the knowledge and some points with our developer team that I have gained from this blog post.
Thanks!!
BEWARE: You shouldnt trust “browser support” for Accessibility. A lot of people use ancient browsers or particular versions, because some or other extension or helper isnt supported or doesnt work properly in newer versions of that browser anymore.
What helps is … testing, testing, testing, AND.. most important: Graceful degradation.
Yeah, that topic. Like it once was with (and actually still is) with Javascript.
cu, w0lf.
ps: yes, I am one of these “old browser users”, too. Some strongly sight-“impaired” person, using Pale Moon for Accessibility, because extensions missing with the sad excuse of a browser thats Firefox nowadays.
My favorite use case for
:focus-within
is to keep sub-menu open when an user cycles the focus on sub-menus:Coming back here after reading all three published posts about accessible forms. As someone who is working at a company that develops software for specially abled people, these articles helped me learn many new things today. So, thanks a lot Chris for writing them!
One input I have here is to also make smart use of em and rem units for fonts and in page layouts. They, while helping to create consistent-looking responsive layouts, also help with accessibility.
We have noticed that many people who have half vision use their browsers with increased default font size.
So always check your designs for a higher root size than the standard 16px.
It could be a bit of hassle to calculate px and rem values back and forth at different root font sizes, but there are online calculators to make that task easy – https://cssunitconverter.com/rem-to-px/
Happy coding!