28 CSS Close Buttons21 / 28

Pure CSSMIT licensed

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

Live Demo
Try it

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>
.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. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
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

ChromeSafariFirefoxEdge
111+16.4+113+111+

filter:drop-shadow is universal; oklch hues give neon its out-of-sRGB punch on P3 displays.

Techniques used in this demo

Search CodeFronts

Loading…