I’m partial to going down the rabbit-hole on a niche aspect of front-end development. For example a few years ago I got the urge to dig into what’s going on with containers and items in Flexbox-powered layouts and noted my findings in Flexbox-fu. I do it to go beyond the thing’s theory and into its practical application for solving real web development challenges; to gain a deeper understanding of why things behave the way they do. These deep dives take time but are rewarding; usually I’ll learn about more than I expected.
Recently I dug into the characteristics and behaviour of the CSS outline property. The catalyst was seeing Heydon Pickering’s clever use of outline to automate divider lines within a flexbox powered navigation menu. I couldn’t fathom how it works so decided to reverse-engineer it. More on Heydon’s trick later, but I’ll start with a recap of what outline is good for.
Focus indicators
The classic use case for outline is to provide a visible focus indicator on interactive elements such as links, buttons and form fields. This supports accessibility by telling people who navigate with their keyboard where they are on the page, or to be more precise that “this element has focus”. Handily, browsers do it for us by default – the user agent supplied :focus-visible {} selector uses outline to apply a one pixel wide “focus ring” around the currently focused element.
I recall that for a while many developers and designers took exception firstly to focus indicators appearing during mouse interactions, and secondly to how they looked. They started setting :focus { outline: none; }, not realising the accessibility implications. Lea Verou offered a smart compromise which applies the focus indicator selectively. Nowadays we don’t need to apply Lea’s trick. Modern browsers employ heuristics to only show the default focus indicator when it is needed, namely when the user is navigating the page with a keyboard.
I consider browsers’ handling of focus indication to be a very sensible default so – call me sensible or call me lazy – I tend not to mess with it.
Debugging
I’ve often reached for outline as a debugging tool. Everything generated by CSS is a box and during development it’s often handy to debug your boxes’ characteristics by drawing lines around them. And while I’ll typically use border: 1px solid red for this (it’s a years-old habit), I occasionally use outline instead. That’s handy because the outline property has no impact on layout. So, I get the lines I want but without the risk of causing elements to move and break layout arrangements.
Creative uses of outline
I can’t recall seeing many “real” uses of outline beyond focus indication, but one that springs to mind is in EveryLayout’s Box component. If you configure your box to be distinguished by a background colour alone rather than with a border, the component automatically adds a transparent outline. This measure deals with high contrast themes such as Windows High Contrast. They often eliminate backgrounds which would cause a border-free box to lose its shape, but they apply a colour to outlines so our previously-transparent outline becomes visible, preserving the box shape. Clever stuff.
Automated dividers
The most creative use of outline I’ve seen is on the horizontal local navigation menu on Heydon Pickering’s website. There’s a flex container, configured to support intrinsic responsiveness via flex-wrap: wrap, and its flex items apply outline: .125rem solid. The magical aspect is that whereas outline normally appears on all edges of an element, here the outlines only appear as keyline dividers between nav items. Lots of the outlines you’d expect to see are somehow invisible.
This is a really neat trick because it offers the combination of a common design need: dividing lines – with an intrinsically-responsive approach: flexbox with no media queries. Intrinsically-responsive layouts use less code, and adapt to their content rather than a container, and are more reusable.
Peeling back the layers
So how does that trick work? To find out, I began by playing around with something simple – two elements stacked vertically in normal flow, both with outline applied, and no gap between them. It’s all in my pen Adjacent outlines.
Here’s what I learned:
Learning 1: the outlines of immediately adjacent elements do not occupy the same space
They relate to different spaces on the page, so you see both. Based on some misguided instinct I had expected the outline on the bottom-edge of the top element to merge into the same 1px space as the outline on the top-edge of the bottom element.
Learning 2: immediately adjacent outlines appear in reverse order
This is because they exist outside the borders of the element box they relate to, to the extent that they encroach into the immediately adjacent element’s box!
If the top element has a blue outline and the bottom element has a red outline, you’ll see the the bottom element’s red top edge outline appear above the top element’s blue bottom edge outline.
Learning 3: you can hide the outermost outlines using a container
You can visually remove outermost outlines by introducing a container element and setting its overflow to hidden. The container element now hides any content that overflows its box, which in this case includes the outlines applied to child elements. So, those outermost outlines disappear.
Learning 4: avoid double-width dividers by using flexbox and a background colour
By making the container a flex container and setting the background colour of items to a value other than transparent, you can ensure your divider lines don’t double-up.
Recreating and adapting the trick
Having started by putting two elements with outlines together and strengthened my knowledge of what’s going on and why, I was ready to try recreating Heydon’s trick. Check out my pen Flex grid with auto-dividers.
One of the cool aspects is that regardless of whether it displays in vertically-stacked mode (as it does on narrow viewports) or in horizontal mode, the outline-powered dividers are in exactly the place you would expect them to be.
Is it suitable for production?
Maybe, maybe not. I’d probably use it and experiment with it on my own personal website.
Pros:
- lets you keep your layouts intrinsic
- handles multiple items automatically. While I admire Ahmad’s Shadeed’s flexbox-separator technique, it uses pseudo elements and requires you to manually manage their
orderin the flexbox arrangement
Cons:
- maintainability: it’s clever, so potentially confusing to colleagues. You could work around that with well-commented code
- ghost outlines. My colleague Josh noticed that when you resize your screen you sometimes notice “ghost outlines” – very thin, perhaps subpixel-width lines that appear temporarily. That’d be something to watch out for, or try to fix.
Wrapping up
Well, that dive went deeper than expected, but I’m glad to have learned more about outline, better focus indicators, CSS box behaviours and a few tricks along the way.
If you have any thoughts on this post, feel free to get in touch.