You Want border-color: transparent, Not border: none

If you find yourself removing a border from an element that has a border and are tempted to use border: 0 , border: none, or outline: none, I’d urge you to stop for a moment and reconsider. It’s like the old G.K. Chesterton saying about fences:

Do not remove a fence until you know why it was put up in the first place.

In the case of interactive form controls (inputs, textareas, buttons, etc.), those pesky borders were put there because they have an accessibility benefit when using High Contrast Mode, a feature used by 30.6% of low-vision users. Usually when we’re talking about High Contrast Mode in web development we’re specifically referencing Windows High Contrast Mode, but nearly every desktop and mobile operating system has contrast settings, each behaving a little differently. Windows High Contrast flattens all colors to black on white with blue accents (or white on black with yellow accents) and remove all background images from the document.

If we look at some thing more interactive like the comment form on the Boost blog, we can see how the “Post Comment” button loses a bit of punch in High Contrast Mode and might be mistaken as text floating on the page.

To make that button look more like a button in high-contrast mode, we remove the border: 0 and instead use border-color: transparent we get a control that looks like a button for low-vision users as well.

Sighted users will never know the difference! So instead of removing the border, try setting border-color to transparent instead:

border-color: transparent;Code language: CSS (css)

The same trick works for overriding outline , set outline-color to transparent:

outline-color: transparent;Code language: CSS (css)

Oops! I’ve already nuked my borders

If you’ve already removed borders everywhere and want to support High Contrast Mode (you do) but don’t want to re-architect your entire CSS, you can use the forced-colors media query to detect High Contrast Mode and layer in styling as necessary:

/* Example code, do not use */
@media (forced-colors: active) {
  input, textarea, button {
    border: 1px solid transparent!important;
  }
}Code language: CSS (css)

There are other places (e.g. text on images) where the forced-colors media query can get you out of a jam.

Testing forced-colors

To test forced-colors the easiest way is to emulate forced-colors inside Chrome DevTools. There are two easy ways in any version of Chromium browser and an even easier way in Microsoft Edge.

  1. Chrome DevTools > Three Dots Menu > More Tools > Rendering > Emulate CSS media feature forced-colors
  2. Chrome DevTools > Open Command Palette (CMD + Shift + P) > Search for “Emulate CSS forced-colors: active”

Edge DevTools has an easy way to access color emulation from the Device Emulation Screen as well.

  • Edge DevTools > Device Emulation > Open Eye Droppers dropdown in top toolbar > forced-colors: active

One other aspect to consider is that folks using high-contrast mode are often using it with a screen magnifier or 200%~400% browser zoom as well. So be sure to test those situations as well.

High-Contrast Mode keeps you honest about color usage

Testing in High-Contrast Mode is probably something you’re not doing, but that’s okay because you can start today. While it’s worthwhile to test High-Contrast Mode just to support low-vision users, because it aggressively flattens and removes colors it has a knock-on effect of showing places where you’ve over-relied on color to make elements or states distinct, which is another accessibility error in itself (§1.4.1).

High-Contrast Mode may seem like a far out edge case, but it’s not. Lots of folks depend on it. Understanding High-Contrast Mode and its limitations are a step on the pathway to becoming a better front-end developer.

Thanks Melanie Sumner for the inspiration for this post and check out her work on Continuous Accessibility.

5 responses to “You Want border-color: transparent, Not border: none”

  1. Avatar Chris Coyier says:

    jeez dave you can just DM me

    screenshot of it working

  2. Testing this in Polypane is even easier, it just takes two clicks! I mentioned this tip and a bunch of others in an (evergreen) article I wrote a few years ago over on my blog: https://polypane.app/blog/forced-colors-explained-a-practical-guide/

    Check it out for more tips, like dealing with icons and focus styles. Using outline-color: transparent instead of outline:none is equally as important.

    Also exceptional use of the “You want X, not Y” title format 😉 https://css-tricks.com/you-want/

  3. Avatar Curtis Wilcox says:

    Another forced-colors tip: test with both dark-on-light and light-on-dark colors. This can help you spot a different issue with forced-colors, SVGs and other images with transparency that assume the background color will be light (or dark), like the Codepen logo (sorry).

    This can be done using Chrome DevTools combining “Emulate CSS media feature forced-colors” and “Emulate CSS media feature prefers-color-scheme.”

Leave a Reply

Your email address will not be published. Required fields are marked *