Select Page

Nesting The pointer-events Property In CSS

Ben Nadel
Published: May 23, 2024

The pointer-events CSS property can be used to disable mouse interactions on a given DOM (Document Object Model) element. When an element has pointer-events set to none, it instructs the browser to let the mouse events “fall through” the given DOM element and target / effect whichever next element is stacked below the user’s cursor. I’ve barely ever used this particular CSS property because—for the most part—when I create a UI (User Interface) element, I want the user to have access to it. Yesterday, however, I learned that you can nest the pointer-events property within the DOM tree. This creates an interesting confluence of interaction behaviors.

Run this demo in my JavaScript Demos project on GitHub.

View this code in my JavaScript Demos project on GitHub.

By nesting elements with different pointer-events settings, it allows us to use an outer element purely for layout purposes without disrupting the normal behavior of the page. Granted this is somewhat of a strange edge-case; but, consider positioning something in the center of the user’s screen.

If we wanted to do this without blocking the background content, we might try to position the element at 50% of the top/left; and then, use something like translate3D(-50%,-50%,0) to move the element into the center. But, this is usually not a viable option due to the fact that a 50% translation will often create blurry, sub-pixel rendering.

CSS Flexbox makes centering elements significantly more simple. However, in order to use Flexbox to center an element on the screen, we’d have to create a fixed-position parent element that covers the entire viewport. Which, as a second order effect, would create a “mouse sink” that essentially blocks access to the background page.

And this is where pointer-events comes into play. We can disable pointer-events on the Flexbox parent, allowing the user to click-through to the background page; and then, enable pointer-events on the Flexbox child in order to make the centered element interactive and user-consumable:

.flexbox-parent {
	pointer-events: none ; /* No clicking! */
}
.flexbox-child {
	pointer-events: auto ; /* Yes clicking! */
}

To see this in action, I’ve put together a demo in which there is a semi-modal element centered in the user’s viewport. Both the background page and the semi-modal window have