Anchor Tags Can Contain Block-Level Elements As Of HTML5
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.
Run this demo in my JavaScript Demos project on GitHub.
View this code in my JavaScript Demos project on GitHub.
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 href="https://www.bennadel.com" class="block">
<span class="block">
Ben Nadel
</span>
<span class="block">
Lover of JavaScript, HTML, and CSS.....
</span>
</a>
Here, the <a>
is semantically "correct" in that it only contains the inline elements <span>
, even though both the <a>
and <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
a
element to only containing phrasing content (essentially, what was in previous versions referred to as "inline" content), thea
element is now transparent; that is, an instance of thea
element 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:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>
Anchor Tags Can Contain Block-Level Elements As Of HTML5
</title>
<link rel="stylesheet" type="text/css" href="./style.css" />
</head>
<body>
<h1>
Anchor Tags Can Contain Block-Level Elements As Of HTML5
</h1>
<!--
NOTE: This is an Anchor tag that contains the BLOCK Elements, Div and P. Prior
to HTML5, this was not valid; however, as of HTML5, the Anchor tag can now
contain both INLINE and BLOCK elements. Woot woot!
-->
<a href="https://www.bennadel.com" target="_blank" class="card">
<img
src="https://www.gravatar.com/avatar/f9bbc701ca6770ef482cc1e172344e25?s=120"
alt="Avatar of Ben Nadel"
class="avatar"
/>
<div class="name">
Ben Nadel
</div>
<p class="description">
Lover of JavaScript and Movies and Dogs and all things pudding. Free spirit
with a rigid sense of timing.
</p>
</a>
</body>
</html>
As you can see, the <a>
tag contains the block-level elements, <div>
and <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.
Want to use code from this post? Check out the license.
Reader Comments
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.
@Stephan,
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:
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.
@Samiullah,
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,
@Claudia Da,
The code should be:
<pre>
<ul>
<a href="#"><li>This item inside the hyperlink tag</li>
</ul>
</pre>
@Claudia,
I suppose that block-level elements are not arbitrarily exchangeable. Just because an Anchor tag can now contain block-level elements, I don't think that it means an Anchor can go anywhere.
@Sean,
That's very interesting. I'm relatively new to thinking about accessability at this level. I will give your link a reading. I am wondering if we could perhaps using something like
title
to override the contents? Just thinking out-loud. I also see that there is a book by the author of that content, will definitely check that out!