DEV Community

Cover image for Building UI using CSS shapes
Ehsan Pourhadi
Ehsan Pourhadi

Posted on

Building UI using CSS shapes

I'm a total sucker for that cyberpunk, high-tech, neon aesthetic. You know the vibe, angular shapes, diagonal cuts, glowing borders, the kind of UI that looks like it came straight out of a sci-fi movie. My portfolio already has that look, and honestly, getting it working on the web was harder than I expected.

A few years ago I found augmented-ui, which was perfect for making gaming cards and flashy components. But trying to use it for actual web content? Different story. I spent hours making random stuff that looked cool but didn't work for real layouts. Eventually, I grabbed some clip-path inspiration from it, modified everything to fit an 8-point grid (percentage values were driving me nuts), and made 3-4 CSS classes that I still use in my site.

It worked. It looked unique. But it was hard.

Then one day I was lurking around the internet and stumbled onto CSS Shapes.

Wait. This is a thing?

The Figma → CSS Pipeline That Actually Worked

I already had tons of cyberpunk UI inspiration bookmarked (you can see them all here), so I did a quick search and found this Figma cyberpunk UI kit. Naturally, I tried copying the shapes.

Except... the groups weren't flat vectors. And flattening them in Figma changed the shapes. Ugh.

So I tried something wild:

  1. Export the shape as SVG from Figma
  2. Flatten the SVG using lean-svg.netlify.app
  3. Convert it to CSS shape using css-generators.com/svg-to-css

And OMG. It worked. Like, shockingly well.

I sat there in disbelief for a minute, then immediately started building CyberTechUI, a full UI component library made entirely with CSS shapes.

/* A cyberpunk button shape generated from SVG */
.bu1 { 
  clip-path: shape(
    from 10.53% 100%,
    line to 0% 75.38%,
    vline to 0%,
    hline by 10.53%,
    vline by 100%,
    close,
    move by 0% -100%,
    hline by 78.95%,
    vline by 100%,
    hline to 10.53%,
    close,
    move by 89.47% 0%,
    hline by -10.53%,
    vline by 100%,
    hline by 10.53%,
    vline to 75%,
    line by -2.63% -6.25%,
    vline to 31.25%,
    line by 2.63% -6.25%,
    vline to 0%,
    close
  ); 
}
Enter fullscreen mode Exit fullscreen mode

I made cards, buttons, tabs, checkboxes, everything you'd need for a complete kit. Integrated it with shadcn so you can install components with one click. The buttons alone have 7 different shape variants (bu1-bu7). Added the shapes as inline CSS in each component. It felt like magic.

The Firefox Betrayal

And then I tested it in Firefox.

Nothing.

CSS shapes. Don't. Work. In. Firefox.

I sat there staring at my screen like... what? Safari supports it. Chrome supports it. Edge supports it. But Firefox? Nope. Can I Use confirmed it, Firefox has zero support for CSS Shapes.

This was genuinely the first time I'd hit a feature that Safari had but Firefox didn't. Usually it's the other way around! I'd built this whole thing assuming cross-browser support was fine because MDN documented it and Chrome/Safari were good. Wrong assumption.

Lesson learned: Check Can I Use before you build the whole thing, not after.

For now, CyberTechUI gracefully degrades in Firefox (aka: it just shows regular boxes). Not ideal, but it works.

The Tab Component Hell

I made each component individually first, buttons, cards, inputs, all looking sharp. Then I tried putting them together into a cohesive design system.

Cue: hours of tiny adjustments while i watching Youtube.

The worst offender? The Tab component. I wanted each tab to have a unique cyberpunk shape. Not just one shape for all tabs, no, I wanted seven different shapes depending on the tab position and state.

It was absurd. I spent way too much time on it. But when it finally worked, it looked so good.

Lesson learned: Build the system first, components second. Or at least test how they fit together before you commit to seven different clip-paths.

The Fake Border Hack That Saved Everything

Here's the thing about CSS shapes: borders don't play nice with clip-path. The border gets clipped too, which means you lose half of it or it looks janky.

I knew this from my own site. It's always been annoying.

But for the checkbox component, I needed borders. The design didn't work without them.

So I faked it.

I tried two approaches:

Option 1: The ::before pseudo-element

.cyber-checkbox {
  position: relative;
  background: var(--primary);
  clip-path: polygon(0% 0%, 90% 0%, 100% 10%, 100% 100%, 0% 100%);
}

.cyber-checkbox::before {
  content: '';
  position: absolute;
  inset: 2px; /* The "border" width */
  background: var(--background);
  clip-path: polygon(0% 0%, 90% 0%, 100% 10%, 100% 100%, 0% 100%);
}
Enter fullscreen mode Exit fullscreen mode

The main div is the "border" color. The ::before is slightly smaller and sits on top as the background.

Option 2: Nested divs with calc (this is what I went with)

const CLIP_PATH = "polygon(0 0, 100% 0, 100% calc(100% - 8px), calc(100% - 8px) 100%, 0 100%)";

<div className="w-5 h-5 bg-primary" style={{ clipPath: CLIP_PATH }}>
  <div 
    className="w-[calc(100%-2px)] h-[calc(100%-2px)] bg-background"
    style={{ clipPath: CLIP_PATH }}
  >
    {/* Inner content */}
  </div>
</div>
Enter fullscreen mode Exit fullscreen mode

The second approach worked way better for me. More control over the border width, easier to adjust per component, and plays nicer with dynamic states (checked, focus, error).

What's Next

This started as a UI component library, but honestly, I'm just getting started. The same technique, converting vectors to CSS shapes, works for way more than buttons and cards.

I'm definitely making high-tech HUDs, game interfaces, sci-fi displays. The kind of stuff you'd see in a space simulator or a cyberpunk dashboard. Now that I know the pipeline works, I can crank these out.

Also, CSS aspect-ratio is a lifesaver for keeping shapes looking good across responsive layouts. Pair that with CSS shapes and you can make some genuinely wild stuff that still works on mobile.


If you're into this aesthetic, check out CyberTechUI. It's open source, it's weird, and it definitely doesn't work in Firefox yet.

But hey, it looks cool.

Top comments (0)