Typical block-level links
A block-level link or button is one that wraps block-level content. An extremely simple example is as follows:
<a href="/"><div></div></a>. This type of link is incredibly useful when creating a tactile user interface, with large click targets for complex items that have their own internal structures.
Take an e-commerce site’s product listing page. Products could be laid out in a grid of boxes, with each box containing a product’s name, details, and image. We could simply make the product name a link, but this would provide a relatively small touch target. If the box provides a visual affordance that it links to the product page, we could wrap each product listing in an
Addressing the downsides
Although wrapping a whole block item in a link quickly produces a rough version of the desired behavior, it has two main pitfalls:
- CSS side effects: Any elements within a link inherit the browser’s default
text-decoration: underline;. To remove this, we need to add a style to any container component that might be used as a block-level link. The components would need to be aware they’re be used as block-level links. That’s alright, but it starts to get more complicated when we need to remove all of the default styling from a block-level
<button>element and add a specific border or background back onto the component. Removing default styles and having custom, component-specific styles are at odds with each other.
- Screen reader overload: Lengthy content within a link or button may be read aloud when a screen reader user focuses on that link. It would be preferential to read only a short title and allow the user to engage with it to hear more.
Faux block-level links
Taking into account the utility of this sort of link or button, what can we do to make it more robust — to work around the disadvantages of nesting a large amount of content inside a single link?
We’ll need to identify and style two elements:
- The containing area: a
position: relative;positioning context element that replaces what would otherwise be a block-level link. This element may or may not have other visual styles, independent of its role as the containing link area.
- The link area: an invisible
position: absolute;link filling the containing area. Pay attention to the order of this element in the document outline, as if it is placed above its corresponding heading, a screen reader user may not notice its presence.
I like to have two implementations of this at the ready: one for links, and one for buttons. Both can be necessary due to their subtly different semantics. For brevity, the following example uses a link:
Product NameView Product NameProduct description.
// Demo styles for product box:.card// The link area / positioning context:.isContext// Text content for screen readers to identify the link:.isVisuallyHidden// The faux block-level link:.blockLink.blockLink:focus