The world of web development moves quickly; and, it is often be hard for me to keep my mental model in alignment with the current trends and standards. Today, I learned that one of my internal rules was critically out of date. As of HTML5 - which was released years ago - it is OK to wrap block-level elements inside of an Anchor tag. In fact, pretty much the only thing you can't put inside of an Anchor tag is another Anchor tag. This new understanding is going to completely change my HTML markup choices.
Prior to HTML5, Anchor tags -
<a> - could only contain "inline" elements (aka, "phrasing content"). To live comfortably within this specification, I often reached for embedded
<span> tags that were styled to behave like block-level elements:
<a> is semantically "correct" in that it only contains the inline elements
<span>, even though both the
<span> tags are styled to behave like block-level elements.
As of HTML5, however, such finagling is no longer needed. From the W3C specification for the Anchor tag:
Changes in HTML5
Although previous versions of HTML restricted the
aelement to only containing phrasing content (essentially, what was in previous versions referred to as "inline" content), the
aelement is now transparent; that is, an instance of the
aelement is now allowed to also contain flow content (essentially, what was in previous versions referred to as "block" content) - if the parent element of that instance of the a element is an element that is allowed to contain flow content.
This means that I can use just about anything that makes sense inside of an Anchor tag. To demonstrate, here's a "User Card" that is an Anchor tag that contains block-level elements:
As you can see, the
<a> tag contains the block-level elements,
<p>. If we run this page in the browser, we get the following output:
And, what's more, if we run this through the W3C Markup Validator, we get:
Document checking completed. No errors or warnings to show.
I know I'm like 5-10 years behind on this knowledge; which is to say, somewhat embarrassing. I think back to how many
<span> tags have been used needlessly in an effort to author "correct" HTML. But no more! This particular gap in my mental model has been fixed. And, I will start reaching for more semantically correct elements, even when embedded within a block-styled Anchor tag.
Be sure not to overlook that qualifier in the last part of the quoted spec: "... if the parent element of that instance of the a element is an element that is allowed to contain flow content."
i.e. an A which is a child of a SPAN or am EM cannot legally contain block elements.
That's a really good catch / point! My primary use-case for something like this is probably going to be in a list-item scenario like:
<li> <a href="#"> <div class="some-blocky-thing"> <!-- ... --> </div> </a> </li>
So, for me, that's a limitation that I'll be able to work with.
The last line in spec about the containing element to be flow was also new for me. Sometimes we learn from the comments as well.
It's a group effort to learn all this stuff, am I right?! Too much for any one person to keep in their head, by far!
Its useful but also can be used in the wrong way, I know the user card is an example but consider accessibility, wrapping lots of content in a single anchor can create issues for users of screen readers.
Have a read of this https://inclusive-components.club/cards/ there are techniques out there that can make a card completely clickable like everything is wrapped in an anchor when really it is only the necessary text,
But it seems that this is still invalid:
- <a href="#">
- This item inside a link </a>
The code should be:
<a href="#"><li>This item inside the hyperlink tag</li>