The pointer-events property controls whether an element can become the target of pointer events like clicks, hover states, and other pointer-based events. In other words, it lets you decide whether the browser should treat an element as interactive when the pointer is over it.
.no-pointer-events {
pointer-events: none;
}
To understand how the property works, it helps to know what the browser does before it fires a pointer event. First, it has to determine which element is under the pointer. This process is known as hit-testing.
Normally, the browser chooses the topmost element under the pointer. But if that element has pointer-events set to none, the browser skips it and continues looking for the next eligible element underneath.
Once you think about pointer-events this way, most of its behavior starts to make sense. Rather than disabling events, it simply changes which element (or, in the case of SVG, which part of an element) becomes the event target in the first place.
Syntax
pointer-events: auto | bounding-box | visiblePainted | visibleFill | visibleStroke | visible | painted | fill | stroke | all | none;
- Initial: auto
- Applies to: All elements. In SVG, it applies to container elements, graphics elements, and the element.
- Inherited: Yes
- Computed value: Specified keyword
- Animation type: discrete
Values
pointer-events: auto;
pointer-events: none;
/* SVG values */
pointer-events: visiblePainted;
pointer-events: visibleFill;
pointer-events: visibleStroke;
pointer-events: visible;
pointer-events: painted;
pointer-events: fill;
pointer-events: stroke;
pointer-events: bounding-box;
pointer-events: all;
/* Global values */
pointer-events: inherit;
pointer-events: initial;
pointer-events: revert;
pointer-events: revert-layer;
pointer-events: unset;
Besides the standard CSS global values shown above, pointer-events defines eleven keyword values. You’ll use auto and none with both HTML and SVG elements, while the other nine are SVG-only and provide finer control over which parts of a graphic can receive pointer events.
auto: The default value. The element behaves normally and can receive pointer events. In SVG, this behaves the same asvisiblePainted.none: The element itself can’t become the target of pointer events, meaning it can’t be clicked or hovered. Instead, the browser targets whatever is underneath it.
SVG-only values
visiblePainted: The element only receives pointer events when it’s visible (visibility: visible) and the pointer is over a painted part of the graphic. In other words, it’s over a filled area (fillis notnone) or a stroked edge (strokeis notnone).visibleFill: The element only receives pointer events when it’s visible and the pointer is over its fill, regardless of the value of thefillproperty, meaning it can even be set tonone.visibleStroke: The element only receives pointer events when it’s visible and the pointer is over its stroke, regardless of the value of thestrokeproperty.- visible: The element only receives pointer events when it’s visible and the pointer is over either its fill or stroke, regardless of the values of the
fillandstrokeproperties. painted: The element only receives pointer events when the pointer is over a painted part of the graphic (its fill or stroke), regardless of the value of thevisibilityproperty.fill: The element only receives pointer events when the pointer is over its fill, regardless of the values of thefillorvisibilityproperties.stroke: The element only receives pointer events when the pointer is over its stroke, regardless of the values of thestrokeorvisibilityproperties.bounding-box: The element receives pointer events anywhere inside its bounding box—the smallest rectangle that completely surrounds it—regardless of its shape, even if parts of that area aren’t painted.all: The element receives pointer events when the pointer is over either its fill or stroke, regardless of the values of thefill,stroke, orvisibilityproperties.
Children can opt back in
One thing that’s easy to miss is that pointer-events is an inherited property. Setting pointer-events to none on a parent means its children inherit that value as well. However, any child can override the inherited value by setting pointer-events back to auto (or another valid value).
.parent {
pointer-events: none;
}
.child {
pointer-events: auto;
}
In this example, the parent ignores pointer events, but the child can still become their target.
A common use case is a modal. You might use a full-page container to center the modal, but that container also covers the entire viewport. Without changing its pointer-events value, it prevents pointer events from reaching the elements underneath it. Setting pointer-events to none on the container fixes that, but because the property is inherited, you’ll also need to restore the modal itself with pointer-events set to auto.
In the following demo, when the pointer-events property is specified as none you can interact with the background buttons even though they are behind the overlay.
Event propagation still works
The pointer-events property only determines which element becomes the event target. It doesn’t change how events travel through the DOM afterward.
For example, if a child with pointer-events: auto is clicked inside a parent with pointer-events: none, the child still becomes event.target. From there, the event follows its normal capture and bubble phases, so event listeners attached to the parent still run.
In other words, pointer-events affects target selection, not event propagation.
In the following demo, you can see how the parent with pointer-events: none can still receive click, pointerenter, and pointerleave when you click or move the pointer into or out of its interactive child.
pointer-events doesn’t disable an element
The pointer-events property only prevents the element from becoming the target of pointer events. Therefore, the element can still receive keyboard focus with the Tab key, and users can continue interacting with it using the keyboard if it’s otherwise focusable.
If you need to disable a native form control, use the disabled attribute instead. And if your goal is to make an entire section of the page completely non-interactive—including pointer input, keyboard focus, and the accessibility tree—the inert attribute is a better choice.
pointer-events doesn’t prevent text selection
Setting the pointer-events property to none doesn’t stop users from selecting text. For example, users can still select the text by pressing Ctrl/Cmd + A on the keyboard.
That’s because text selection isn’t determined by whether an element can become the target of pointer events.
If your goal is to prevent text from being selected, use the user-select property instead.
.avoid-user-selection {
user-select: none;
}
Try selecting the text in each block below:
Demo
When building a navigation menu, a common pattern is to hide a submenu by setting its opacity to 0 and then make it visible when the user hovers over its parent menu item. The problem is that the submenu is still there, so it can still receive pointer events even though you can’t see it.
Below, you can see two identical menus. One hides its submenu using only opacity, while the other also uses pointer-events. Hover over the hidden submenu area and try interacting with the content behind it to see how pointer-events prevents invisible elements from getting in the way.
Also, to better understand how each SVG value of this property works, pick one from the dropdown and move your pointer around the ring: over its filled band, inside its hollow center, and over the empty corners of the dashed bounding box. Notice how the interactive area changes with each value.
Browser Support
Related properties
pointer-events originally handwritten and published with love on CSS-Tricks. You should really get the newsletter as well.