28 CSS Close Buttons21 / 28
Neon Etch Close Button
A gas-tube × on midnight glass: layered drop-shadow() filters build the inner-glow-plus-halo of real neon, and hovering powers the tube on with a flickering strike sequence — two dim pre-flashes, then full brightness — exactly like fluorescent tubes igniting. One custom property carries the entire glow color.
Published Updated
The code
<section class="ccb-21" aria-label="Neon close button demo">
<button class="ccb-21__close" type="button" aria-label="Close">
<span class="ccb-21__x" aria-hidden="true"></span>
</button>
</section><section class="ccb-21" aria-label="Neon close button demo">
<button class="ccb-21__close" type="button" aria-label="Close">
<span class="ccb-21__x" aria-hidden="true"></span>
</button>
</section>.ccb-21,
.ccb-21 *,
.ccb-21 *::before,
.ccb-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-21 {
--neon: oklch(0.78 0.2 330);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 120% at 50% 10%,oklch(0.2 0.03 300),oklch(0.12 0.015 290));
}
.ccb-21 .ccb-21__close {
position: relative;
display: grid;
place-items: center;
width: 84px;
height: 84px;
border: 1px solid oklch(0.78 0.2 330 / .22);
border-radius: 18px;
background: linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.01));
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
cursor: pointer;
transition: border-color .25s ease;
box-shadow: 0 20px 44px -22px rgba(0,0,0,.9),inset 0 1px 0 rgba(255,255,255,.07);
}
.ccb-21 .ccb-21__close::after {
content: "";
position: absolute;
inset: auto 14px 10px;
height: 10px;
border-radius: 50%;
background: var(--neon);
filter: blur(14px);
opacity: .12;
transition: opacity .3s ease;
}
.ccb-21 .ccb-21__x {
position: relative;
width: 28px;
height: 28px;
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
transition: opacity .2s ease;
}
.ccb-21 .ccb-21__x::before,
.ccb-21 .ccb-21__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 28px;
height: 3px;
border-radius: 3px;
background: color-mix(in oklab,var(--neon) 60%,white);
}
.ccb-21 .ccb-21__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-21 .ccb-21__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: ccb-21-strike .9s ease-out forwards;
}
.ccb-21 .ccb-21__close:hover::after {
opacity: .4;
}
.ccb-21 .ccb-21__close:hover {
border-color: oklch(0.78 0.2 330 / .5);
}
@keyframes ccb-21-strike {
0% {
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
}
8% {
opacity: .7;
}
11%,
18% {
opacity: .35;
}
21% {
opacity: .8;
}
24%,
30% {
opacity: .4;
}
55%,
100% {
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}
.ccb-21 .ccb-21__close:active {
transform: scale(.95);
}
.ccb-21 .ccb-21__close:focus-visible {
outline: 2.5px solid var(--neon);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: none;
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}.ccb-21,
.ccb-21 *,
.ccb-21 *::before,
.ccb-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-21 {
--neon: oklch(0.78 0.2 330);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 120% at 50% 10%,oklch(0.2 0.03 300),oklch(0.12 0.015 290));
}
.ccb-21 .ccb-21__close {
position: relative;
display: grid;
place-items: center;
width: 84px;
height: 84px;
border: 1px solid oklch(0.78 0.2 330 / .22);
border-radius: 18px;
background: linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.01));
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
cursor: pointer;
transition: border-color .25s ease;
box-shadow: 0 20px 44px -22px rgba(0,0,0,.9),inset 0 1px 0 rgba(255,255,255,.07);
}
.ccb-21 .ccb-21__close::after {
content: "";
position: absolute;
inset: auto 14px 10px;
height: 10px;
border-radius: 50%;
background: var(--neon);
filter: blur(14px);
opacity: .12;
transition: opacity .3s ease;
}
.ccb-21 .ccb-21__x {
position: relative;
width: 28px;
height: 28px;
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
transition: opacity .2s ease;
}
.ccb-21 .ccb-21__x::before,
.ccb-21 .ccb-21__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 28px;
height: 3px;
border-radius: 3px;
background: color-mix(in oklab,var(--neon) 60%,white);
}
.ccb-21 .ccb-21__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-21 .ccb-21__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: ccb-21-strike .9s ease-out forwards;
}
.ccb-21 .ccb-21__close:hover::after {
opacity: .4;
}
.ccb-21 .ccb-21__close:hover {
border-color: oklch(0.78 0.2 330 / .5);
}
@keyframes ccb-21-strike {
0% {
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
}
8% {
opacity: .7;
}
11%,
18% {
opacity: .35;
}
21% {
opacity: .8;
}
24%,
30% {
opacity: .4;
}
55%,
100% {
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}
.ccb-21 .ccb-21__close:active {
transform: scale(.95);
}
.ccb-21 .ccb-21__close:focus-visible {
outline: 2.5px solid var(--neon);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: none;
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}/* No JavaScript — three stacked drop-shadow shells build the tube glow; a ballast-misfire keyframe strikes the light on hover. */
/* No JavaScript — three stacked drop-shadow shells build the tube glow; a ballast-misfire keyframe strikes the light on hover. */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: Neon Etch Close Button
Source: https://codefronts.com/components/css-close-buttons/neon-etch/
A gas-tube × on midnight glass: layered drop-shadow() filters build the inner-glow-plus-halo of real neon, and hovering powers the tube on with a flickering strike sequence — two dim pre-flashes, then full brightness — exactly like fluorescent tubes igniting. One custom property carries the entire glow color.
## HTML
```html
<section class="ccb-21" aria-label="Neon close button demo">
<button class="ccb-21__close" type="button" aria-label="Close">
<span class="ccb-21__x" aria-hidden="true"></span>
</button>
</section>
```
## CSS
```css
.ccb-21,
.ccb-21 *,
.ccb-21 *::before,
.ccb-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-21 {
--neon: oklch(0.78 0.2 330);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 120% at 50% 10%,oklch(0.2 0.03 300),oklch(0.12 0.015 290));
}
.ccb-21 .ccb-21__close {
position: relative;
display: grid;
place-items: center;
width: 84px;
height: 84px;
border: 1px solid oklch(0.78 0.2 330 / .22);
border-radius: 18px;
background: linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.01));
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
cursor: pointer;
transition: border-color .25s ease;
box-shadow: 0 20px 44px -22px rgba(0,0,0,.9),inset 0 1px 0 rgba(255,255,255,.07);
}
.ccb-21 .ccb-21__close::after {
content: "";
position: absolute;
inset: auto 14px 10px;
height: 10px;
border-radius: 50%;
background: var(--neon);
filter: blur(14px);
opacity: .12;
transition: opacity .3s ease;
}
.ccb-21 .ccb-21__x {
position: relative;
width: 28px;
height: 28px;
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
transition: opacity .2s ease;
}
.ccb-21 .ccb-21__x::before,
.ccb-21 .ccb-21__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 28px;
height: 3px;
border-radius: 3px;
background: color-mix(in oklab,var(--neon) 60%,white);
}
.ccb-21 .ccb-21__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-21 .ccb-21__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: ccb-21-strike .9s ease-out forwards;
}
.ccb-21 .ccb-21__close:hover::after {
opacity: .4;
}
.ccb-21 .ccb-21__close:hover {
border-color: oklch(0.78 0.2 330 / .5);
}
@keyframes ccb-21-strike {
0% {
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
}
8% {
opacity: .7;
}
11%,
18% {
opacity: .35;
}
21% {
opacity: .8;
}
24%,
30% {
opacity: .4;
}
55%,
100% {
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}
.ccb-21 .ccb-21__close:active {
transform: scale(.95);
}
.ccb-21 .ccb-21__close:focus-visible {
outline: 2.5px solid var(--neon);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: none;
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}
```
## JavaScript
```js
/* No JavaScript — three stacked drop-shadow shells build the tube glow; a ballast-misfire keyframe strikes the light on hover. */
```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: Neon Etch Close Button
Source: https://codefronts.com/components/css-close-buttons/neon-etch/
A gas-tube × on midnight glass: layered drop-shadow() filters build the inner-glow-plus-halo of real neon, and hovering powers the tube on with a flickering strike sequence — two dim pre-flashes, then full brightness — exactly like fluorescent tubes igniting. One custom property carries the entire glow color.
## HTML
```html
<section class="ccb-21" aria-label="Neon close button demo">
<button class="ccb-21__close" type="button" aria-label="Close">
<span class="ccb-21__x" aria-hidden="true"></span>
</button>
</section>
```
## CSS
```css
.ccb-21,
.ccb-21 *,
.ccb-21 *::before,
.ccb-21 *::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
.ccb-21 {
--neon: oklch(0.78 0.2 330);
font-family: 'Segoe UI',system-ui,sans-serif;
width: 100%;
min-height: 100vh;
display: grid;
place-items: center;
padding: 48px 24px;
background: radial-gradient(100% 120% at 50% 10%,oklch(0.2 0.03 300),oklch(0.12 0.015 290));
}
.ccb-21 .ccb-21__close {
position: relative;
display: grid;
place-items: center;
width: 84px;
height: 84px;
border: 1px solid oklch(0.78 0.2 330 / .22);
border-radius: 18px;
background: linear-gradient(160deg,rgba(255,255,255,.05),rgba(255,255,255,.01));
backdrop-filter: blur(6px);
-webkit-backdrop-filter: blur(6px);
cursor: pointer;
transition: border-color .25s ease;
box-shadow: 0 20px 44px -22px rgba(0,0,0,.9),inset 0 1px 0 rgba(255,255,255,.07);
}
.ccb-21 .ccb-21__close::after {
content: "";
position: absolute;
inset: auto 14px 10px;
height: 10px;
border-radius: 50%;
background: var(--neon);
filter: blur(14px);
opacity: .12;
transition: opacity .3s ease;
}
.ccb-21 .ccb-21__x {
position: relative;
width: 28px;
height: 28px;
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
transition: opacity .2s ease;
}
.ccb-21 .ccb-21__x::before,
.ccb-21 .ccb-21__x::after {
content: "";
position: absolute;
top: 50%;
left: 50%;
width: 28px;
height: 3px;
border-radius: 3px;
background: color-mix(in oklab,var(--neon) 60%,white);
}
.ccb-21 .ccb-21__x::before {
transform: translate(-50%,-50%) rotate(45deg);
}
.ccb-21 .ccb-21__x::after {
transform: translate(-50%,-50%) rotate(-45deg);
}
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: ccb-21-strike .9s ease-out forwards;
}
.ccb-21 .ccb-21__close:hover::after {
opacity: .4;
}
.ccb-21 .ccb-21__close:hover {
border-color: oklch(0.78 0.2 330 / .5);
}
@keyframes ccb-21-strike {
0% {
opacity: .35;
filter: drop-shadow(0 0 2px var(--neon));
}
8% {
opacity: .7;
}
11%,
18% {
opacity: .35;
}
21% {
opacity: .8;
}
24%,
30% {
opacity: .4;
}
55%,
100% {
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}
.ccb-21 .ccb-21__close:active {
transform: scale(.95);
}
.ccb-21 .ccb-21__close:focus-visible {
outline: 2.5px solid var(--neon);
outline-offset: 3px;
}
@media (prefers-reduced-motion: reduce) {
.ccb-21 .ccb-21__close:hover .ccb-21__x {
animation: none;
opacity: 1;
filter: drop-shadow(0 0 2px var(--neon)) drop-shadow(0 0 6px var(--neon)) drop-shadow(0 0 14px var(--neon));
}
}
```
## JavaScript
```js
/* No JavaScript — three stacked drop-shadow shells build the tube glow; a ballast-misfire keyframe strikes the light on hover. */
```How this works
Neon depth needs stacked glows at increasing radii: the glyph gets filter:drop-shadow(0 0 2px c) drop-shadow(0 0 6px c) drop-shadow(0 0 14px c) — three shells sharing var(--neon), so one variable recolors tube, glow and halo together. drop-shadow (not box-shadow) hugs the ×'s actual strokes rather than its bounding box.
The power-on flicker is a keyframe with authentic strike behaviour: brief 40%-brightness blips at 8% and 21% of the timeline separated by dark holds, then a sustained ramp — copied from how real ballasts misfire before igniting. At rest the tube idles at 35% opacity with a faint single shadow (off but catching ambient light); an ::after ellipse beneath paints the wall-wash the tube casts on its backing panel.
Make it yours
- Recolor the entire sign with
--neon— all three glow shells inherit. - More menace: lengthen the dark holds in the strike keyframe.
- Steady-state buzz: add a 3s subtle opacity oscillation after ignition with a second animation.
- Pair two hues (pink tube, blue wall-wash) by giving ::after its own color.
Gotchas — read before shipping
- Stack multiple drop-shadows small-to-large — one big shadow reads as blur, not glow.
- drop-shadow filters rasterise per frame; confine them to the glyph, never the whole card.
- Keep the resting tube visible (~35% opacity) — a fully dark button is an undiscoverable control.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 111+ | 16.4+ | 113+ | 111+ |
filter:drop-shadow is universal; oklch hues give neon its out-of-sRGB punch on P3 displays.