About
A state layer is the translucent wash a component paints over itself to show that you are hovering it, that it has focus, or that you are pressing it. Material 3 uses it in place of the ink ripple, and it is a foundation: you never write markup for one. Components paint it behind themselves, and these tokens decide how strong it is.
Because the opacity lives in one place, changing it changes every component at once, at runtime, with no rebuild.
Opacities
| Token | Value | Applies when |
|---|---|---|
--md-sys-state-hover-state-layer-opacity | 0.08 | The pointer is over the control. |
--md-sys-state-focus-state-layer-opacity | 0.1 | The control has visible focus. |
--md-sys-state-pressed-state-layer-opacity | 0.1 | The control is being pressed. |
--md-sys-state-dragged-state-layer-opacity | 0.16 | The control is being dragged. |
These are the md.sys.state values from the Material 3 token set. Focus and
pressed are both 0.1.
Overriding
Set the token on :root to change every component, or on a subtree to change
only what is inside it.
<style>
:root { --md-sys-state-hover-state-layer-opacity: 0.12; }
</style>
Components that expose their own state layer token read from these, so you can still reach for one component without touching the rest. The component token is the override point; the value behind it comes from the foundation.
<style>
.my-panel { --md-comp-card-hover-state-layer-opacity: 0.04; }
</style>
Two shapes
Most components draw the layer as an overlay filling the control. Checkboxes and radio buttons have no room for one, so they draw it as a ring growing out from the control's edge to the state layer size. Both read the same opacity, so they stay in step.