Frontend Masters Boost RSS Feed https://frontendmasters.com/blog Helping Your Journey to Senior Developer Wed, 13 Mar 2024 21:36:37 +0000 en-US hourly 1 https://wordpress.org/?v=6.5.2 225069128 You Want border-color: transparent, Not border: none https://frontendmasters.com/blog/you-want-border-color-transparent-not-border-none/ https://frontendmasters.com/blog/you-want-border-color-transparent-not-border-none/#comments Wed, 13 Mar 2024 21:36:37 +0000 https://frontendmasters.com/blog/?p=1120 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;

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

outline-color: transparent;

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;
  }
}

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.

]]>
https://frontendmasters.com/blog/you-want-border-color-transparent-not-border-none/feed/ 5 1120
Safari Gets a Toggle Switch Input https://frontendmasters.com/blog/safari-gets-a-toggle-switch-input/ https://frontendmasters.com/blog/safari-gets-a-toggle-switch-input/#comments Wed, 06 Mar 2024 21:33:11 +0000 https://frontendmasters.com/blog/?p=1118 Safari 17.4 dropped an interesting an unexpected feature, a native UI toggle switch control! It’s so new it’s not even in the HTML spec yet. While that might be a blocker for your project, you can use it today as a progressive enhancement on top of the standard <input type="checkbox">.

<input type="checkbox" switch>
<input type="checkbox" checked switch>

Adding a switch attribute to a normal <input type="checkbox"> changes the visual affordance in Safari 17.4+ to a switch toggle input:

Switch toggle inputs in Safari 17.4, set in rebeccapurple
Switch toggle inputs in Safari 17.4, set in rebeccapurple

The “Active” state is the default Apple blue input color (like checkboxes) but accepts the CSS accent-color property so you can make it more on brand with minimal effort. There’s even more good news because the styling story isn’t limited to accent colors, there are some new pseudo-elements to make even more customizations.

The new ::thumb and ::track pseudo-elements?

Along with the new input[switch] control, Safari is experimenting with ::thumb and ::track pseudo elements as a replacement for the old proprietary ::-webkit prefixed pseudo-elements. They are current behind a flag in Safari Technical Preview 189+.

I was excited for input[switch] but having standardized pseudo-elements for styling form controls is probably my favorite part of this feature release. It solves a minor pain point, but makes for much more approachable and maintainable CSS.

The Webkit blog demos for input[switch] show what’s possible with new CSS and get pretty wild including a Light/Dark toggle with some embedded animations. I’m excited to see what people come up with but it’s a good time to talk about some UX concerns with switch toggle inputs.

UX Concerns

The good minds at Axess Lab had some strong words for switch toggle inputs in their post “Toggles Suck!” The post is worth a read, but the gist is that there are a lot of shoddy implementations where it would be more clear to use a button, a radio, or a checkbox instead of a fancy toggle. So before you rollout a brand new settings page UI, check with your customers to see if the current checkboxes and radios are working just fine.

Reading through some of the common complaints, there’s two major concerns you need to pay attention to with toggles:

  1. You need clear labelling
  2. You need clear “Active” and “Inactive” states

If your toggle is floating in space disconnected from any sort of label or context, that’s a clear fail. If your toggle has a weird label like “Don’t not unsubscribe”, that’s a fail. If your active state looks more disabled than your inactive state, you failed.

Webkit gives the following advice which is reflected in their demos:

Generally, we recommend using a switch when the end user understands the user interface element as a setting that is either “on” or “off”.

I hate nuance, but a lot of it depends on your situation and the context in which you’re using switch toggle inputs.

Internationalization Concerns

From an internationalization standpoint, you need to think in logical properties. The idea that “thumb to the right == active” is not always true. In rtl languages “thumb to the left” is the active state. That’s where working in CSS logical properties helps you, you can use the keyword inline-end instead and you get the correct behavior in both language directions in one line of code.

Screenshot with devtools open showing the HTML element with `dir="rtl"`
Switch toggle inputs in RTL (right-to-left) direction.

Accessibility Concerns

As far as accessibility goes, from a screen reader perspective there’s a few things happening under the hood. Adding the switch attribute to a checkbox in Safari upgrades role="checkbox" to role="switch" and it announces its state in VoiceOver as “On” or “Off”, as opposed to either “checked” or “unchecked”. The can both be interacted with using the Spacebar.

VoiceOver announcement of switch inputs

One more difference to be aware of is that input[type="checkbox"] can have an indeterminate state while input[switch] cannot, it’s a boolean value.

If you’re thinking about polyfilling this feature, be aware of some notes in how screen readers announce role="switch", but if you’re comfortable using input[switch] with the fallback being a checkbox for unsupported browsers, it might make a great progressive enhancement for your page.

Detecting switch input support

Experimenting with input[switch] I found myself wanting a different layout for regular checkboxes and when input[type="checkbox"][switch] was enhanced. One nuanced difference I’ve noticed in settings screens is I like is the following:

  • Checkboxes go at the inline-start (before the label)
  • Switches go at the inline-end (after the label)

This is not a hard and fast rule, but there are a couple different ways we can achieve this in our little example. Let’s start with JavaScript.

Use JavaScript to detect switch inputs

One way to detect switch toggle input support is to use JavaScript. I wrote a little script that checks for support and adds a class to the <html> element.

// Remember Modernizr?!? lol.
function supportsSwitchInput() {
  const switchInput = document.createElement('input');
  switchInput.type = 'checkbox'
  if('switch' in switchInput) return true;

  return false
}

if(supportsSwitchInput()) document.documentElement.classList.add('supports-switch');

In your CSS you’d do something like the following to flip the presentation of the checkbox row.

div:has(input[type="checkbox"]) {
  display: flex;
  flex-direction: row;
}

.supports-switch div:has(input[type="checkbox"][switch]) {
  flex-direction: row-reverse;
}

Experimental CSS detection for switch inputs

If JavaScript is not your thing and you want to only use CSS you could try something a little more experimental…

/* ::thumb only supported in Safari TP which supports input[switch] */
@supports selecotor(::thumb) {
  div:has(input[type="checkbox"][switch]) {
    flex-direction: row-reverse;
  }
}

We can’t detect support for input[switch] exactly but does sniff for the ::thumb pseudo-element support, which is supported in Safari TP along with input[switch].

Have you tried turning it off and on again?

Over the years I’ve coded a few toggle switches by moving a <span> or ::after pseudo-element inside a <button> or <label> based on a piece of state. It never felt like a good solution and it always felt clumsy. <input type="checkbox" switch> is an elegant way to solve a commonly requested UI element.

And best of all, it’s a progressive enhancement. That means low-risk for testing and experimenting. Your mileage may vary with your users and you may want to wait for another browser to roll this out, but I already can tell this will save me a few dozen lines of weird CSS in my application.

]]>
https://frontendmasters.com/blog/safari-gets-a-toggle-switch-input/feed/ 3 1118
Capo.js: A five minute web performance boost https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/ https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/#comments Fri, 01 Mar 2024 16:25:08 +0000 https://frontendmasters.com/blog/?p=1086 You want a quick web performance win at work that’s sure to get you a promotion? Want it to only take five minutes? Then I got you.

Screenshot of the Capo.js console output showing rows of colored rectangles for the Actual order and Sorted order of elements in the head.

Capo.js is a tool to get your <head> in order. It’s based on some research by Harry Roberts that shows how something seemingly insignificant as the elements in your <head> tag can make your page load up to 7 seconds slower! From pragma directives, to async scripts, to stylesheets, to open graph tags, it’s easy to mess up and can have consequences. Capo.js will show you the specific order of elements to make your <head> and your page a little (or a lotta) bit faster.

Usage

  1. Head over to Capo.js homepage
  2. Install the Capo.js Chrome Extension (you can also use it as a DevTools Snippet or bookmarklet)
  3. Run Capo.js

Capo.js will log two colored bar charts in your JS console; your “Actual” <head> order and a “Sorted” <head> order. You can expand each chart to see more details. If you see a big gray bar in the middle of your “Actual” bar chart, then you’re leaving some quick wins on the table. The “Sorted” dropdown will show you the corrected order and even give you the code. But in the real world you probably need to futz with a layout template or your _header.php to get it reorganized.

Installing Capo.js takes about a minute, rearranging your <head> takes another minute. Honestly the longest part is making the Pull Request.

EDITOR INTERVENTION

[Chris busts through the door.]

OK fine Dave, I’ll give it a shot right here on Boost itself.

I installed the Chrome Extension and ran it and got this little popup:

"Before" sort order, scattered rectangles of various colors

At first I was a little confused, like this was some fancy code that Web Perf people immediately understand but I was out of the loop on. But actually it’s just a visualization of the order of things (top: actual, bottom: ideal). As a little UX feedback, it should say “Open your console for more information” because that’s where all the useful stuff is.

I found it most useful to look at the “Sorted” output (which is what you should be doing) and then try to get my source code to match that. I think I generally did OK:

"After" sort order, scattered rectangles of various colors, slightly less scattered than the previous image

I wasn’t able to get it perfect because of WordPress. A decent chunk of what goes into your <head> in WordPress comes from the output of the <php wp_head(); ?> function. I’m sure it’s technically possible to re-order output in there, but that was a more effort that I felt was worth it right at this minute.

Take your wins, that’s what I always say.

]]>
https://frontendmasters.com/blog/capo-js-a-five-minute-web-performance-boost/feed/ 7 1086