Skip to main content

Tagged “buttons”

Use CSS :has to set root-level styles based on a button’s state

Great tip here from Jhey. He advises using a button with ARIA and a little JavaScript for your dark-mode toggle. And to apply the dark styles, use a CSS selector which targets the :root parent of the button when in “pressed” state and sets a root-level custom property to “on”.

:root:has([aria-pressed=true]) {
  --dark:1;
}

Seriously clever stuff!

And aside from the CSS, I really like the way Jhey advocates using a button rather than a form element such as a checkbox for this kind of interface, much like Léonie did recently.

Perceived affordances and the functionality mismatch (by Léonie Watson)

Léonie tackles the prickly subject of “element re-purposing” in web development. This post follows a fantastic Twitter exchange started by Lea Verou regarding whether the common visual design request for “adjacent but mututally exclusive buttons” should be built as radio buttons or using <button> elements.

Using one element or set of elements (usually because of their functionality) and styling them to look like something else is a common pattern […but…] it creates a mismatch between the actions people expect they can take and the ones they actually can.

Relatedly, Lea has also gathered her post-discussion thoughts and decisions into a blog post What is the best way to mark up an exclusive button group? and shared a new button-group web component!

Meanwhile, Léonie already has a theme-toggle web component on her personal website which demonstrates the use of buttons and aria-pressed.

Thank you so much, Lea and Léonie.

(via @LeonieWatson)

Update July 19/7/22

I just had a twitter conversation with Adrian Roselli where I suggested that the reasons for developers considering radio inputs over buttons for Lea’s use case might be more nuanced than simply misunderstanding HTML. I’m not sure we agreed on that one in the end, however Adrian shared some helpful heuristics when choosing betweeen JS-powered buttons and forms:

A checkbox, radio button, select menu are meant to gather information. The submit button sends the form (whether get, post, or an AJAX call). A button (non-submit) causes a change on the page, such as toggling a control, showing or hiding something, etc. Different context/use.

I think it would help to think of form fields as for forms. Forms that users intentionally submit (no matter if processed client- or server-side). Forms that gather info. Buttons that have states (expanded, pressed, etc) are for manipulation of the current view.

Takeaways:

  • Pick the HTML solution that is generally intended for your use case.
  • Use a form if you’re gathering information but if you’re not, don’t. There will be exceptions like “filter forms” but that’s an edge case and most forms are not like that.
  • Forms are ideally things that users intentionally submit, via a submit button. This helps rule out “clever forms” as an option.
  • Use a button to cause a change on, or manipulate, the current page.

Modern CSS Solutions

Modern CSS Solutions for Old CSS Problems

Stephanie Eckles with a beautifully presented series of articles on how to use modern CSS to tackle some of the enduring challenges of web development including dropdown navigation, centring and styling buttons.

Block Links: A tricky UI Problem

You have a “card” component which includes a heading, some text, an image, and a link to the full article, and it’s working great. Then along comes a UX requirement that the full card (not just the button or link) should be clickable. This is where things get complicated.

TL;DR

I was recently faced with this challenge while building a component at work and opted to implement a tailored version of Heydon Pickering’s Redundant Click Trick. This felt like the best approach, or perhaps more accurately “the lesser of three evils”. I’ll be monitoring how that performs, but in light of the knowledge and experience gained carrying out this task I’m also starting to think that – like Chris Coyier recently suggested – maybe full-card clickable regions are a bad idea.

Setting the Scene

Let’s say our starting HTML is this:

<div class="card">
  <h2>Card Title</h2>
  <img src="/path/to/img.jpg" />
  <p>This is the body copy for the card. It it is comprised of a few sentences.</p>
  <a href="/">Read more</a>
</div>

And the requirement we’ve been given is to make the whole card clickable rather than just the “Read more” link.

Option 1: Stuff everything inside an anchor

Here’s the thing – since the dawn of HTML5 we’ve been able to wrap the inline anchor (<a>) element around block-level content such as headings, paragraphs, and <div>s… so isn’t the answer just to do that?

<a href="/">
  <div class="card">
    <h2>Card Title</h2>
    <img src="/path/to/img.jpg" />
    <p>This is the body copy for the card. It it is comprised of a few sentences.</p>
  </div>
</a>

Well, as with many HTML challenges, just because you can do something doesn’t mean you should. I always had a nagging doubt about stuffing all that disparate content inside a single anchor, and Adrian Roselli has recently confirmed that for screen reader users this approach is harmful.

Perhaps the worst thing you can do for a block link is to wrap everything in the <a href>… for a screen reader user the entire string is read when tabbing through controls… taking about 25 seconds to read before announcing it as a link.

Furthermore, images nested in this way are not clearly announced as they normally would be.

So if you care about the user experience for those people, this feels like a no-no.

Option 2: Stretch a standard anchor using pseudo-content

An alternate approach that’s gained traction over the last couple of years involves leaving the anchor or button in its initial position within the card (thereby avoiding the above mentioned accessibility problem) and using pseudo-content to stretch it to cover the entire card. This CSS-only trick involves setting the card to position:relative then giving the anchor (or button) :after pseudo-content and absolutely positioning that to the card’s four corners. This makes the whole card clickable like a button.

The problem with this approach is that any text in the card is no longer selectable.

Some might say that this is OK. Personally I feel that it is a fundamental usability requirement that text on a web page be selectable. Not being able to do so calls to mind the bad old days before web fonts where we used images for headings, and I like to think we’ve evolved from those kind of practices. Also, I feel any statement by us developers and designers that “losing the ability to select text is OK” lacks validity because we are biased; happy to justify taking away something fundamental from our users because we’re more concerned with getting a (frankly non-essential) feature over the line.

If we don’t like this compromise but are still determined to make the full card clickable, there’s one further option.

Option 3: The Redundant Click Trick

This technique, conceived by Heydon Pickering, uses JavaScript rather than CSS to make the card clickable.

Essentially we add an EventListener for a click on the Card and when one is detected, trigger a faux click on the inner anchor or button.

One challenge inherent in this approach is that a user attempting to select text would unintentionally trigger our faux link click. However we can again use JavaScript (using the onmousedown and onmouseup events) to detect the length of their press to infer whether they are selecting text or clicking, then take appropriate action.

The pros of this approach are that we avoid the screen reader problems and the inability to select text.

The cons are i) that it requires a more complicated, JavaScript-based approach; and ii) that the need for a “check how long the mouse has been pressed down” part isn’t ideal.

With this approach, if Analytics tracking is part of your mix I’d make sure to check that that works as expected across browsers and devices.

Summing up

So there we go – three ways to achieve a “block link” or button. But given the compromises they involve, perhaps the question should be – is it worth it? And given the tools we currently have available, I lean towards “no”.

References

Block Links, Cards, Clickable Regions etc by Adrian Roselli.

Cards by Heydon Pickering (in Inclusive Components).

Block Links are a pain and maybe just a bad idea by Chris Coyier on CSS-Tricks.

Don’t set cursor: pointer on buttons

For many years I’ve been applying cursor: pointer to buttons because it felt right and would improve the user experience.

As Florens Verschelde explains, that approach is probably best avoided. I was going against the W3C’s spec that cursor: pointer should be reserved for links, and was adding to the usability antipattern where “everything resembles a link”.

I’ll leave button cursor behaviour as it is from here on in.

See all tags.

External Link Bookmark Note Entry Search