DEV Community

Sri Kadimisetty
Sri Kadimisetty

Posted on

Affecting a parent element in CSS using pointer-events

CSS has a multitude of relational selectors, none of which let you target a parent from a child, at least not as of today. To be fair, not having a parent selector is not the most inhibiting of problems necessarily; but there are situations where having one might spare us from depending on Javascript modifications. Of course, this is only going to be appealing if you also hold the view that little dependence on javascript is a good thing.

The problem

Consider the following scenario: You need to change the background-color of <body> to hotpink when the mouse hovers upon an inner element say, a <button>. This isn't possible without resorting to using a script to modify <body>, with said script set to trigger when the mouse hovers over <button>. There isn't an ideal pure CSS relational selectors solution, but let me introduce you to one involving pointer-events. It's pretty much today-ready as the caniuse coverage is quite decent, so it's worth learning about, if nothing else.

Pointer events?

A brief explanation of what pointer-event is first and then we can use it to solve our problem. Lingo-wise, here's some context on a pointer via the MDN docs"A pointer is a hardware agnostic representation of input devices (such as a mouse, pen or contact point on a touch-enable surface) ..." And so unsurprisingly, a pointer event is the event that transpires when that contact is made. CSS provides pointer-events to dictate what can happen when an element receives such an event. I feel like I'm making this more complicated than it needs to be, so here's a super quick example from the MDN docs of leveraging that selector to make a link "unclickable": a {pointer-event: none}. The default is auto which allows pointer events to flow through but none blocks them right then and there and thus for all intents and purposes makes the link "unclickable". There's a bit more to them, especially involving SVGs, but I got a mission to get you a solution, so read them docs later.

The solution

Given this simple DOM structure:

<body>
    <button>Submit</button>
</body>
Enter fullscreen mode Exit fullscreen mode

we need to change body's background-color property on button:hover. Here's the solution followed by an explanation:

body {
    pointer-events: none; /* 1 */
}

button {
    pointer-events: auto; /* 2 */
}

body:hover { /* 3 */
    background-color: hotpink;
}
Enter fullscreen mode Exit fullscreen mode
  1. We begin by making the parent element body unresponsive to pointer events with: body { pointer-events: none } and at this point a body:hover selector would not work. But note something important here - pointer-events: none is applied to every single child element inside body here onwards, because they implicitly inherit that none as well.

  2. So we are at a point where button:hover doesn't respond now either; but we need it to, hence: button { pointer-events: auto; } and the button:hover selector is back in play again.

  3. Finally we set body:hover { background-color: hotpink; } and that works because, here's the thing, body-hover now only happens with button:hover because body's pointer-events-related-selectors now only trigger on the first child's pointer events.

</solution>

Sure, this is not the most elegant of solutions, and has a bunch of caveats, even in this simple application here — but you do now know, at least in certain cases, how to affect a parent element in CSS using pointer events! Thanks for reading!

Top comments (0)