28 CSS Close Buttons17 / 28
Trash Compactor Close Button
An industrial squeeze: the × sits between two heavy press plates that slam vertically inward on hover, crushing the glyph — bars compress via scaleY, bow outward via scaleX, and the whole assembly settles into a flattened bar with a satisfying clunk bezier. Great for delete-flavored dismissals.
Published Updated
The code
<section class="ccb-17" aria-label="Trash compactor close button demo">
<button class="ccb-17__close" type="button" aria-label="Close">
<span class="ccb-17__plate ccb-17__plate--top" aria-hidden="true"></span>
<span class="ccb-17__x" aria-hidden="true"></span>
<span class="ccb-17__plate ccb-17__plate--bot" aria-hidden="true"></span>
</button>
</section><section class="ccb-17" aria-label="Trash compactor close button demo">
<button class="ccb-17__close" type="button" aria-label="Close">
<span class="ccb-17__plate ccb-17__plate--top" aria-hidden="true"></span>
<span class="ccb-17__x" aria-hidden="true"></span>
<span class="ccb-17__plate ccb-17__plate--bot" aria-hidden="true"></span>
</button>
</section>.ccb-17,
.ccb-17 *,
.ccb-17 *::before,
.ccb-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-17 {
--crush: .22;
--steel: oklch(0.75 0.02 250);
--ease: cubic-bezier(.6,-.28,.55,1.32);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,oklch(0.32 0.02 255),oklch(0.22 0.015 250));
}
.ccb-17 .ccb-17__close {
position: relative;
display: grid;
place-items: center;
width: 76px;
height: 76px;
border: 1px solid oklch(0.5 0.02 250 / .6);
border-radius: 14px;
background: linear-gradient(180deg,oklch(0.4 0.02 250),oklch(0.3 0.02 250));
cursor: pointer;
overflow: hidden;
box-shadow: 0 16px 36px -18px rgba(0,0,0,.85),inset 0 1px 0 oklch(0.55 0.02 250 / .5);
}
.ccb-17 .ccb-17__plate {
position: absolute;
inset-inline: 10px;
height: 8px;
border-radius: 3px;
background: linear-gradient(180deg,var(--steel),oklch(0.55 0.02 250));
box-shadow: 0 2px 4px rgba(0,0,0,.5);
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__plate--top {
top: 8px;
}
.ccb-17 .ccb-17__plate--bot {
bottom: 8px;
}
.ccb-17 .ccb-17__x {
position: relative;
width: 24px;
height: 24px;
transform-origin: center;
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__x::before,
.ccb-17 .ccb-17__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 24px;
height: 3px;
border-radius: 2px;
background: oklch(0.92 0.01 250);
transition: border-radius .34s var(--ease);
}
.ccb-17 .ccb-17__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-17 .ccb-17__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--top {
transform: translateY(15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--bot {
transform: translateY(-15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x {
transform: scaleY(var(--crush)) scaleX(1.25);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x::before,
.ccb-17 .ccb-17__close:hover .ccb-17__x::after {
border-radius: 4px;
}
.ccb-17 .ccb-17__close:active {
transform: scale(.95);
}
.ccb-17 .ccb-17__close:focus-visible {
outline: 3px solid oklch(0.8 0.1 250);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-17 .ccb-17__plate,
.ccb-17 .ccb-17__x {
transition: none;
}
}.ccb-17,
.ccb-17 *,
.ccb-17 *::before,
.ccb-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-17 {
--crush: .22;
--steel: oklch(0.75 0.02 250);
--ease: cubic-bezier(.6,-.28,.55,1.32);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,oklch(0.32 0.02 255),oklch(0.22 0.015 250));
}
.ccb-17 .ccb-17__close {
position: relative;
display: grid;
place-items: center;
width: 76px;
height: 76px;
border: 1px solid oklch(0.5 0.02 250 / .6);
border-radius: 14px;
background: linear-gradient(180deg,oklch(0.4 0.02 250),oklch(0.3 0.02 250));
cursor: pointer;
overflow: hidden;
box-shadow: 0 16px 36px -18px rgba(0,0,0,.85),inset 0 1px 0 oklch(0.55 0.02 250 / .5);
}
.ccb-17 .ccb-17__plate {
position: absolute;
inset-inline: 10px;
height: 8px;
border-radius: 3px;
background: linear-gradient(180deg,var(--steel),oklch(0.55 0.02 250));
box-shadow: 0 2px 4px rgba(0,0,0,.5);
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__plate--top {
top: 8px;
}
.ccb-17 .ccb-17__plate--bot {
bottom: 8px;
}
.ccb-17 .ccb-17__x {
position: relative;
width: 24px;
height: 24px;
transform-origin: center;
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__x::before,
.ccb-17 .ccb-17__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 24px;
height: 3px;
border-radius: 2px;
background: oklch(0.92 0.01 250);
transition: border-radius .34s var(--ease);
}
.ccb-17 .ccb-17__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-17 .ccb-17__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--top {
transform: translateY(15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--bot {
transform: translateY(-15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x {
transform: scaleY(var(--crush)) scaleX(1.25);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x::before,
.ccb-17 .ccb-17__close:hover .ccb-17__x::after {
border-radius: 4px;
}
.ccb-17 .ccb-17__close:active {
transform: scale(.95);
}
.ccb-17 .ccb-17__close:focus-visible {
outline: 3px solid oklch(0.8 0.1 250);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-17 .ccb-17__plate,
.ccb-17 .ccb-17__x {
transition: none;
}
}/* No JavaScript — plates translate inward while the × scaleY-crushes and scaleX-bows; one anticipation bezier unifies the machine. */
/* No JavaScript — plates translate inward while the × scaleY-crushes and scaleX-bows; one anticipation bezier unifies the machine. */Here's a working CSS Close Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Trash Compactor Close Button
Source: https://codefronts.com/components/css-close-buttons/trash-compactor/
An industrial squeeze: the × sits between two heavy press plates that slam vertically inward on hover, crushing the glyph — bars compress via scaleY, bow outward via scaleX, and the whole assembly settles into a flattened bar with a satisfying clunk bezier. Great for delete-flavored dismissals.
## HTML
```html
<section class="ccb-17" aria-label="Trash compactor close button demo">
<button class="ccb-17__close" type="button" aria-label="Close">
<span class="ccb-17__plate ccb-17__plate--top" aria-hidden="true"></span>
<span class="ccb-17__x" aria-hidden="true"></span>
<span class="ccb-17__plate ccb-17__plate--bot" aria-hidden="true"></span>
</button>
</section>
```
## CSS
```css
.ccb-17,
.ccb-17 *,
.ccb-17 *::before,
.ccb-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-17 {
--crush: .22;
--steel: oklch(0.75 0.02 250);
--ease: cubic-bezier(.6,-.28,.55,1.32);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,oklch(0.32 0.02 255),oklch(0.22 0.015 250));
}
.ccb-17 .ccb-17__close {
position: relative;
display: grid;
place-items: center;
width: 76px;
height: 76px;
border: 1px solid oklch(0.5 0.02 250 / .6);
border-radius: 14px;
background: linear-gradient(180deg,oklch(0.4 0.02 250),oklch(0.3 0.02 250));
cursor: pointer;
overflow: hidden;
box-shadow: 0 16px 36px -18px rgba(0,0,0,.85),inset 0 1px 0 oklch(0.55 0.02 250 / .5);
}
.ccb-17 .ccb-17__plate {
position: absolute;
inset-inline: 10px;
height: 8px;
border-radius: 3px;
background: linear-gradient(180deg,var(--steel),oklch(0.55 0.02 250));
box-shadow: 0 2px 4px rgba(0,0,0,.5);
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__plate--top {
top: 8px;
}
.ccb-17 .ccb-17__plate--bot {
bottom: 8px;
}
.ccb-17 .ccb-17__x {
position: relative;
width: 24px;
height: 24px;
transform-origin: center;
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__x::before,
.ccb-17 .ccb-17__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 24px;
height: 3px;
border-radius: 2px;
background: oklch(0.92 0.01 250);
transition: border-radius .34s var(--ease);
}
.ccb-17 .ccb-17__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-17 .ccb-17__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--top {
transform: translateY(15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--bot {
transform: translateY(-15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x {
transform: scaleY(var(--crush)) scaleX(1.25);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x::before,
.ccb-17 .ccb-17__close:hover .ccb-17__x::after {
border-radius: 4px;
}
.ccb-17 .ccb-17__close:active {
transform: scale(.95);
}
.ccb-17 .ccb-17__close:focus-visible {
outline: 3px solid oklch(0.8 0.1 250);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-17 .ccb-17__plate,
.ccb-17 .ccb-17__x {
transition: none;
}
}
```
## JavaScript
```js
/* No JavaScript — plates translate inward while the × scaleY-crushes and scaleX-bows; one anticipation bezier unifies the machine. */
```Here's a working CSS Close Button from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: Trash Compactor Close Button
Source: https://codefronts.com/components/css-close-buttons/trash-compactor/
An industrial squeeze: the × sits between two heavy press plates that slam vertically inward on hover, crushing the glyph — bars compress via scaleY, bow outward via scaleX, and the whole assembly settles into a flattened bar with a satisfying clunk bezier. Great for delete-flavored dismissals.
## HTML
```html
<section class="ccb-17" aria-label="Trash compactor close button demo">
<button class="ccb-17__close" type="button" aria-label="Close">
<span class="ccb-17__plate ccb-17__plate--top" aria-hidden="true"></span>
<span class="ccb-17__x" aria-hidden="true"></span>
<span class="ccb-17__plate ccb-17__plate--bot" aria-hidden="true"></span>
</button>
</section>
```
## CSS
```css
.ccb-17,
.ccb-17 *,
.ccb-17 *::before,
.ccb-17 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-17 {
--crush: .22;
--steel: oklch(0.75 0.02 250);
--ease: cubic-bezier(.6,-.28,.55,1.32);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: linear-gradient(180deg,oklch(0.32 0.02 255),oklch(0.22 0.015 250));
}
.ccb-17 .ccb-17__close {
position: relative;
display: grid;
place-items: center;
width: 76px;
height: 76px;
border: 1px solid oklch(0.5 0.02 250 / .6);
border-radius: 14px;
background: linear-gradient(180deg,oklch(0.4 0.02 250),oklch(0.3 0.02 250));
cursor: pointer;
overflow: hidden;
box-shadow: 0 16px 36px -18px rgba(0,0,0,.85),inset 0 1px 0 oklch(0.55 0.02 250 / .5);
}
.ccb-17 .ccb-17__plate {
position: absolute;
inset-inline: 10px;
height: 8px;
border-radius: 3px;
background: linear-gradient(180deg,var(--steel),oklch(0.55 0.02 250));
box-shadow: 0 2px 4px rgba(0,0,0,.5);
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__plate--top {
top: 8px;
}
.ccb-17 .ccb-17__plate--bot {
bottom: 8px;
}
.ccb-17 .ccb-17__x {
position: relative;
width: 24px;
height: 24px;
transform-origin: center;
transition: transform .34s var(--ease);
}
.ccb-17 .ccb-17__x::before,
.ccb-17 .ccb-17__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 24px;
height: 3px;
border-radius: 2px;
background: oklch(0.92 0.01 250);
transition: border-radius .34s var(--ease);
}
.ccb-17 .ccb-17__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-17 .ccb-17__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--top {
transform: translateY(15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__plate--bot {
transform: translateY(-15px);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x {
transform: scaleY(var(--crush)) scaleX(1.25);
}
.ccb-17 .ccb-17__close:hover .ccb-17__x::before,
.ccb-17 .ccb-17__close:hover .ccb-17__x::after {
border-radius: 4px;
}
.ccb-17 .ccb-17__close:active {
transform: scale(.95);
}
.ccb-17 .ccb-17__close:focus-visible {
outline: 3px solid oklch(0.8 0.1 250);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-17 .ccb-17__plate,
.ccb-17 .ccb-17__x {
transition: none;
}
}
```
## JavaScript
```js
/* No JavaScript — plates translate inward while the × scaleY-crushes and scaleX-bows; one anticipation bezier unifies the machine. */
```How this works
Three synchronized transforms sell the crush. The plates (two absolutely-positioned bars at the button's top and bottom edges) translate toward centre. The × wrapper compresses with scaleY(.22) — and simultaneously bows with scaleX(1.25), because real crushed material displaces sideways; that conservation-of-volume detail is what makes it physical rather than just "shrinking".
Every piece shares one cubic-bezier(.6,-.28,.55,1.32) — a slight anticipation dip then overshoot — so plates and glyph move as one machine. The bars' border-radius grows during the crush (squashed things get blunt edges). Release runs the same transition in reverse automatically.
Make it yours
- Crush depth via
--crush(scaleY target, .22 default). - Plate thickness/color via
--platevars for lighter or heavier machinery. - Trigger on :active for crush-on-press (fits destructive delete confirmation).
- Slow to .6s and the effect turns comedic — good for playful empty-state dismissals.
Gotchas — read before shipping
- Scale the wrapper, not each bar independently — independent scaling desyncs the crossing point of the ×.
- The sideways bow (scaleX) must be subtle (≤1.3) or the glyph reads as melting, not crushing.
- Set
transform-origin:centerexplicitly on the wrapper; inherited origins from earlier layout tweaks are the classic cause of lopsided crushes.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 113+ | 111+ |
Pure transform choreography — runs on anything; oklch steel tones are the only modern syntax.