1

I wanted to create an anchor that would popup a div with anchor children when hovered. In order to achieve that, I created something like this:

.dropdown-content {
  display: none;
}

.dropdown:hover .dropdown-content {
  display: block;
}
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <title>Dropdown</title>
</head>

<body>
  <a class="dropdown" href="#">
    <span>Community</span>
    <div class="dropdown-content">
      <a href="contact.html">Contact</a>
      <a href="faq.html">FAQ</a>
    </div>
  </a>
</body>

</html>

However, it failed to work.

While trying to find a solution, I found this similar issue, where it was suggested to create a div wrapper around the root anchor, and use that as the target of :hover. However, I wanted to keep looking into it, in order to understand why the original code would not work. After some trial and error, I discovered that:

1. Using any type (at least from those I tried) other than anchor as children of .dropdown-content made the above code work as intended. However, as soon as an anchor child is inserted into .dropdown-content, it stops working again. So this works:

<div class="dropdown-content">
  <p href="contact.html">Contact</p>
  <p href="faq.html">FAQ</p>
</div>

While this does not:

<div class="dropdown-content">
  <p href="contact.html">Contact</p>
  <a href="faq.html">FAQ</a>
</div>

2. The .dropdown-content can be displayed properly with anchor children, if the descendant selector is replaced by an adjacent sibling combinator. That is, doing this:

.dropdown:hover + .dropdown-content {
  display: block;
}

instead of this:

.dropdown:hover .dropdown-content {
  display: block;
}

effectively solves the original issue.

Having tested this in various browsers (Chrome, Firefox, Edge, IE11), I can safely assume that this is not a browser-specific bug. However, this has led me to the following questions:

  1. It may be cross-browser compliant, but is it normal behavior? That is, is it stated or implied somewhere (e.g. W3C) that this is how anchors should work? I searched various sources, but I could not find an answer.
  2. If it is a normal behavior, why is .dropdown-content treated as a sibling when it contains an anchor element, whereas it is treated as a child without one.
  3. Is it possible to make .dropdown-content (or a div in general) have consistent behavior (i.e. treat nested elements as children), regardless of its parent and child elements?
SASUPERNOVA
  • 141
  • 1
  • 11

1 Answers1

2

That is, is it stated or implied somewhere (e.g. W3C) that this is how anchors should work?

See the a element which says "Content model: Transparent, but there must be no interactive content or a element descendants."

You cannot put an anchor inside another anchor.

If it is a normal behavior, why is .dropdown-content treated as a sibling when it contains an anchor element, whereas it is treated as a child without one.

Browsers rearrange the DOM to try to make it valid. You can see the resulting structure using the developer tools in your browser.

Is it possible to make .dropdown-content (or a div in general) have consistent behavior (i.e. treat nested elements as children), regardless of its parent and child elements?

It does … the problem is that your attempt to make an a a descendant of another a is failing in the first place.

Quentin
  • 914,110
  • 126
  • 1,211
  • 1,335
  • Wow, that was fast! I thought it would be legal to have an anchor inside another one if it was a grandchild, but your source clearly states that there must be no interactive _descendant_, which is good to know. Thanks for the help! – SASUPERNOVA Aug 31 '19 at 12:30