Is there any other way to achieve this in CSS while explicitly specifying the relationship between elements?
You already are, with the use of the descendant combinator.
Combinators express relationships between two elements, each represented by a compound selector. And a compound selector is made up of one or more simple selectors that all represent some aspects of an element's state. Selectors does not require you to separate an element's state, and that same element's relationship with another element. This works both to its elegance, but also to its detriment as it creates many limitations such as not being able to traverse from a descendant to its ancestors, from a later sibling to its previous siblings, and so on. But that's a separate issue.
In the selector .menu-item:hover a
, there are two compound selectors: .menu-item:hover
, and a
. Each of the three simple selectors represents a certain state, but two of them apply to the same element by appearing in a single compound selector. In this case, the :hover
pseudo-class indicates that it's representing .menu-item
, albeit only when it is in the hover state.
This doesn't mean or imply that a
only descends from .menu-item
when it's in the hover state. Instead, it means that the a
element will only match when it descends from at least one element (in other words: has at least one ancestor) that matches .menu-item:hover
. In fact, if you changed .menu-item:hover
to :hover.menu-item
, it would still match, because the order between classes and pseudo-classes in a compound selector doesn't matter, they're on equal footing. You could alternatively think of that, then, as "explicitly saying that a
is a descendant of an element that's in the hover state", and attempting to write something like :hover.menu-item :hover a
, which evidently doesn't work either. That might help you understand why the relationship is already explicitly specified through use of the descendant combinator itself.
Therefore the selector .menu-item:hover a
(and, by extension, :hover.menu-item a
) means
Apply this rule to any a
element
that descends from (or: has an ancestor that is) a .menu-item
element that's in the :hover
state.
And, since a relationship is already explicitly specified when you use the descendant combinator, it follows that the selector .menu-item:hover .menu-item a
, with two descendant combinators, means
Apply this rule to any a
element
that descends from a .menu-item
element
that, itself, descends from another .menu-item
element, one that's in the :hover
state.
That's why it doesn't work. Additionally, as A Haworth says, since there aren't any nested .menu-item
s in your markup, it won't match any a
elements at all.
For a much more in-depth explanation to how combinators and element states work in Selectors, see my answer to this question:
↪ How do I select an element based on the state of another element in the page with CSS?