npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

tailwind-srounded

v0.1.1

Published

Opt-in superellipse/squircle rounded utilities for Tailwind CSS v4

Readme

tailwind-srounded

Opt-in superellipse / squircle corner utilities for Tailwind CSS v4.

Use srounded-* anywhere you would use rounded-*. Supporting browsers get iOS-style smooth corners via CSS corner-shape. Everyone else gets normal border-radius. Your existing rounded-* classes are left alone.

<div class="srounded-xl bg-neutral-900 p-6">
  Smooth corners in Chrome. Regular rounding everywhere else.
</div>

What this plugin does

border-radius draws circular arcs. That is the familiar Tailwind rounded look. A squircle (a superellipse) keeps more of the straight edge and blends into the corner more gradually — the shape used on iOS icons, many system controls, and a lot of contemporary UI.

This plugin:

  • Adds srounded utilities that mirror Tailwind’s rounded API (sizes, sides, corners, logical properties, full, none, arbitrary values).
  • Applies corner-shape: superellipse(...) only inside @supports, so unsupported browsers fall back to ordinary rounding.
  • Scales the radius in supporting browsers (--srounded-scale) so the squircle doesn’t look tighter than the rounded-* size you picked.
  • Is opt-in. Nothing global is restyled. You choose which elements get the superellipse.

It is a CSS-first Tailwind v4 plugin (@utility + @theme). There is no JavaScript plugin file and no @plugin directive.

Browser support

| Browser | Superellipse corners | Fallback | | --- | --- | --- | | Chrome / Edge 139+ | Yes | — | | Opera 123+ | Yes | — | | Safari | Not yet | border-radius | | Firefox | Not yet | border-radius |

The fallback is the point: srounded-xl looks like rounded-xl where corner-shape does not exist. Layout, shadows, and borders stay intact.

Check live support: Can I use — superellipse().

Requirements

  • Tailwind CSS v4 (^4.0.0)
  • A setup that processes CSS with Tailwind (Vite, Next.js, PostCSS, CLI, etc.)

This will not work with Tailwind v3. v3 has no CSS-first @utility / @theme pipeline.

Install

npm install tailwind-srounded
pnpm add tailwind-srounded
yarn add tailwind-srounded
bun add tailwind-srounded

Import it after Tailwind in the stylesheet Tailwind already compiles:

@import "tailwindcss";
@import "tailwind-srounded";

Both of these resolve to the same file:

@import "tailwind-srounded";
@import "tailwind-srounded/index.css";

Do not use @plugin "tailwind-srounded". That directive is for JavaScript plugins. This package is CSS.

Configuration (optional)

Skip this if the defaults work. The plugin already sets --srounded-n: 1.6 and --srounded-scale: 1.6. Override them in your CSS after the plugin import only when you want a different shape or optical size.

@import "tailwindcss";
@import "tailwind-srounded";

@theme {
  --srounded-n: 1.6; /* default — superellipse exponent (2 = squircle) */
  --srounded-scale: 1.6; /* default — radius compensation in supporting browsers */
}

| Variable | Default | What it does | | --- | --- | --- | | --srounded-n | 1.6 | Superellipse exponent passed to superellipse(n) | | --srounded-scale | 1.6 | Multiplier applied to border-radius only in supporting browsers |

--srounded-n (shape)

This is the K in CSS superellipse(K):

| n | Shape | | --- | --- | | 1 | Same as normal border-radius (round) | | 1.6 | Plugin default — between round and squircle | | 2 | Classic squircle (corner-shape: squircle) | | > 2 | Flatter sides, tighter corners (approaches a square) |

Negative values scoop inward. This plugin is aimed at convex squircles; stay in the 12 range unless you know you want a scoop.

--srounded-scale (optical size)

At the same border-radius, a superellipse looks smaller than a circular arc because more of the edge stays straight. The plugin multiplies the radius by --srounded-scale inside @supports so srounded-xl still reads as “xl”.

  • Raise it if corners feel too tight compared to rounded-*.
  • Lower it if the shape eats too much of the box.
  • It has no effect in Safari/Firefox (they never enter the @supports block).

Per-element overrides

Theme variables are CSS custom properties, so you can override them on a node:

<div class="srounded-xl [--srounded-n:2] [--srounded-scale:2]">
  Stronger squircle, larger compensation.
</div>

Usage

srounded-* follows the same naming as rounded-*. Swap the prefix.

Sizes

| Class | Same idea as | Radius source | | --- | --- | --- | | srounded | rounded | --radius | | srounded-xs | rounded-xs | --radius-xs | | srounded-sm | rounded-sm | --radius-sm | | srounded-md | rounded-md | --radius-md | | srounded-lg | rounded-lg | --radius-lg | | srounded-xl | rounded-xl | --radius-xl | | srounded-2xl | rounded-2xl | --radius-2xl | | srounded-3xl | rounded-3xl | --radius-3xl | | srounded-4xl | rounded-4xl | --radius-4xl | | srounded-full | rounded-full | pill / circle | | srounded-none | rounded-none | 0 (and resets corner-shape) |

Any --radius-* token you add in @theme is picked up automatically:

@theme {
  --radius-card: 1.25rem;
}
<article class="srounded-card">…</article>

Sides and corners

Physical:

<div class="srounded-t-xl">top</div>
<div class="srounded-b-xl">bottom</div>
<div class="srounded-l-xl">left</div>
<div class="srounded-r-xl">right</div>
<div class="srounded-tl-xl">top-left</div>
<div class="srounded-tr-xl">top-right</div>
<div class="srounded-bl-xl">bottom-left</div>
<div class="srounded-br-xl">bottom-right</div>

Logical (follow writing direction, same as rounded-s / rounded-ss):

<div class="srounded-s-xl">inline-start</div>
<div class="srounded-e-xl">inline-end</div>
<div class="srounded-ss-xl">start-start</div>
<div class="srounded-se-xl">start-end</div>
<div class="srounded-ee-xl">end-end</div>
<div class="srounded-es-xl">end-start</div>

Each of those also has -full and -none (srounded-t-full, srounded-tl-none, …).

Arbitrary values

<div class="srounded-[12px]"></div>
<div class="srounded-[1.5rem]"></div>
<div class="srounded-[50%]"></div>
<div class="srounded-t-[20px]"></div>

Variants

These are real Tailwind utilities, so variants work:

<button class="srounded-lg hover:srounded-xl md:srounded-2xl">
  …
</button>

With @apply

.card {
  @apply srounded-2xl bg-white p-6 shadow-sm;
}

Do not mix with rounded-* on the same corners

Both families set border-radius. On one element they will fight. Pick one:

<!-- yes -->
<div class="srounded-xl"></div>

<!-- no — both set border-radius -->
<div class="rounded-xl srounded-xl"></div>

Mixing on different corners is fine (rounded-tl-lg srounded-br-xl).

How it works

For srounded-xl, the generated CSS is roughly:

.srounded-xl {
  border-radius: var(--radius-xl);
}

@supports (corner-shape: superellipse(1)) {
  .srounded-xl {
    corner-shape: superellipse(var(--srounded-n));
    border-radius: calc(var(--radius-xl) * var(--srounded-scale));
  }
}
  1. Every browser gets a real border-radius from your Tailwind radius scale.
  2. If the engine understands corner-shape, the corner curve becomes a superellipse and the radius is scaled.
  3. srounded-none sets radius 0 and resets corner-shape to round so a previous srounded-* does not leak.

Side and corner utilities set the matching longhands (border-top-left-radius, corner-top-left-shape, logical equivalents, and so on).

Debugging

1. Confirm the class is in the compiled CSS

Search the built stylesheet for .srounded-xl (or whichever class you used).

Not there?

  • Tailwind v4 is required. tailwindcss@3 will ignore @utility.
  • The import must live in a CSS file Tailwind actually processes (the same file as @import "tailwindcss", or a file that file imports).
  • You used @plugin "tailwind-srounded" instead of @import. Switch to @import.
  • The class never appears in a scanned source file. Tailwind only emits utilities it sees. Put the class in HTML/JSX, or add a @source path.
  • In a monorepo / UI kit, the consuming app must import this CSS. Installing the package is not enough.

There, but unused in DevTools?

  • A later rounded-* or inline border-radius is winning.
  • A third-party component stylesheet is beating the utility on specificity. Try ! (next section).
  • The class is misspelled (sround-xl, s-rounded-xl).

2. Force the utility with !

srounded-* is a normal Tailwind utility, so the important modifier works. Put ! at the end of the class (Tailwind v4):

<div class="srounded-xl!">
  Wins against most third-party `border-radius` rules.
</div>

That compiles to border-radius and corner-shape with !important — including the scaled radius inside @supports. Variants still stack: hover:srounded-2xl!, md:srounded-xl!.

Use this when a library component (datepicker, modal, card, input) ships its own radius and your class shows up in the DOM but the corners stay circular. Do not make ! the default; it is a specificity escape hatch.

! will not help if:

  • The painted box is a child (or pseudo-element) the library styles. Put srounded-* / srounded-*! on the node that actually has border-radius, or wrap and round the wrapper if that is the visible edge.
  • A parent uses overflow, clip-path, or mask that clips to a circular arc.
  • The library also sets border-radius: … !important and wins on source order. Then you need a more specific override, or to stop the library class from applying.

The v3-style prefix (!srounded-xl) still works in v4 but is deprecated; prefer srounded-xl!.

3. Confirm the browser can draw superellipses

In DevTools console:

CSS.supports("corner-shape", "superellipse(1)")
  • true — you should see squircles. Inspect the element; corner-shape should be superellipse(1.6) (or your --srounded-n).
  • false — you will only see normal rounding. That is the fallback, not a plugin bug. Test in Chrome 139+ or Edge 139+.

On a supporting engine, computed styles look like:

border-radius: /* token * --srounded-scale, e.g. ~19px if --radius-xl is 12px */
corner-shape: superellipse(1.6)

On Safari/Firefox you should see the unscaled radius and no corner-shape.

4. The shape is there but looks wrong

| What you see | Likely cause | What to try | | --- | --- | --- | | Looks exactly like rounded-* in Chrome | @supports block missing from CSS, or an overlay/overflow clip hiding the corner | Confirm compiled CSS contains corner-shape. Check parent overflow / clip-path / mask. | | Library component ignores srounded-* | Their stylesheet sets border-radius with higher specificity | srounded-xl!. Confirm you classed the painted node. | | Corners look too circular | --srounded-n too close to 1 | Set --srounded-n: 2 | | Corners look too boxy | --srounded-n too high | Drop toward 1.41.8 | | Corners look smaller than rounded-xl | Scale compensation too low | Raise --srounded-scale (1.82.2 is a common range) | | Corners eat the content | Scale too high, or radius larger than half the shortest side | Lower --srounded-scale, or use a smaller size token | | One corner is round, others squircles | Mixed rounded-* / srounded-*, or a *-none reset | Use one family per corner | | srounded-full still looks like a circle | Expected — infinite radius + superellipse still reads as a pill/circle | Use a large but finite radius (srounded-3xl / srounded-[2rem]) for a squircle “disc” |

Tweak live on one node while iterating:

<div class="srounded-2xl [--srounded-n:2] [--srounded-scale:1.8]">
  …
</div>

When it looks right, move those values into @theme.

5. Custom radius tokens not generating

srounded-* reads --radius-* from @theme. A token named --srounded-card will not match. Name it --radius-card and use srounded-card.

Arbitrary values must be lengths or percentages: srounded-[12px] works, srounded-[var(--my-radius)] needs a type hint if Tailwind cannot infer it (srounded-(length:--my-radius)).

6. Still stuck

Minimal reproduction:

@import "tailwindcss";
@import "tailwind-srounded";
<div class="srounded-2xl bg-black size-32"></div>
  1. Open in Chrome 139+.
  2. CSS.supports("corner-shape", "superellipse(1)")true.
  3. The box should not look like a plain rounded-2xl disc-corner.

If that works in isolation but not in the app, compare import order, CSS modules (@reference vs a real import), and any global border-radius / corner-shape rules.

FAQ

Does this replace rounded-*? No. It is a parallel, opt-in set. Keep using rounded-* where circular arcs are what you want.

Is this a polyfill? No. Unsupported browsers get border-radius only. There is no SVG mask or clip-path.

Will box-shadow / border follow the squircle? Yes, in supporting browsers. corner-shape changes the used box shape, unlike clip-path.

Can I change n per breakpoint? Yes. --srounded-n is a custom property:

<div class="srounded-xl [--srounded-n:1.6] md:[--srounded-n:2]"></div>

Why is the default n 1.6 instead of 2? 2 is a textbook squircle. 1.6 is a bit softer — closer to “smooth rounded” than “iOS icon”. Override to 2 if you want the classic squircle.

License

MIT