A press effect, shadow on rest, lifted on hover, depressed on active, is not central to buttons. It can be used on cards, image gallery photos, and other elements. The same goes for animations and other behaviors. This leaves me to question "why aren't they decoupled from the component?
In my own code I experimented with a dedicated behaviors layer. Each interaction pattern is its own class, independent of any component. You can even stack multiple behaviors together.
Let's create a simple one that adds more click affordance.
Press Example
Adding b-press gives any flat element a physical depth through shadow states. It lifts on hover and depresses on active, giving users a clear sense that something is clickable. Disabled elements will lose the shadow entirely so the affordance disappears with the interaction.
CSS
@layer behaviors {
.b-press {
box-shadow:
var(--wisp-shadow,
0 1px 2px rgba(0, 0, 0, 0.10),
0 1px 3px rgba(0, 0, 0, 0.06)
);
cursor: pointer;
}
.b-press:hover {
box-shadow:
var(--wisp-shadow-hover,
0 4px 6px rgba(0, 0, 0, 0.12),
0 2px 4px rgba(0, 0, 0, 0.10)
);
}
.b-press:active {
box-shadow:
var(--wisp-shadow-active,
0 1px 2px rgba(0, 0, 0, 0.16),
0 1px 1px rgba(0, 0, 0, 0.12)
);
transform: translateY(1px);
}
.b-press:disabled,
.b-press[aria-disabled="true"] {
box-shadow: 0 0 0 rgba(0, 0, 0, 0);
cursor: not-allowed;
}
}
HTML
<div class="o-card b-press">
...
</div>
Finally
When we think of OOCSS we think of visual repeating patterns, but behaviors are patterns too and deserve the same love that objects and components get.
You can find the decoupled behaviors in my framework source here:
https://github.com/wispcode/wisp-css/tree/main/src/behaviors
Top comments (0)