GODRICH
#css-animation#button#loader#transition#scroll#dashboard#ui#design-trends

CSS corner-shape: 9 Corner Cutting Patterns

css corner-shape, live. Nine corner-shape patterns: one sweeps a superellipse exponent from circle to square, one interpolates a card corner along the squircle

Auto-plays · click a tile to jump to its section · all nine in one zip

Every card, chip, and panel below gets its corner from the css corner-shape property working together with border-radius, and each of the nine items detects support at runtime with CSS.supports before it writes anything, falling back to a border-radius approximation where the property is not available. A visitor watching the grid sees one number move per card — an exponent, an angle, a ratio, an inset — and the corner curve change with it, never a random flicker, so there is no need to reach for an external css corner shape generator when the value driving each curve is already printed under the card.

Anatomy of nine patterns — which value bends the corner curve

The table below holds three measured values per item: how much of the frame the moving corner work filled cumulatively, how strong the per-pixel change was on average, and in how many of 23 sampled frames the pixels actually moved.

Item Cumulative area Avg intensity Moving frames
01 1.36% 109.8 23/23
02 0.33% 73.2 23/23
03 1.99% 90.0 21/23
04 3.21% 94.7 8/23
05 1.01% 109.7 23/23
06 3.25% 107.9 13/23
07 0.80% 107.2 15/23
08 1.42% 82.0 23/23
09 0.43% 82.8 23/23

The widest cumulative area belongs to item 06 alone, and the narrowest to item 02 alone, while the highest intensity sits with item 01 at 109.8 — a hair above item 05's 109.7, close enough that only the measured number separates them. The lowest intensity is item 02's, and the fewest moving frames is item 04's 8 of 23, because its notch only moves while a tab handover is actually in flight and sits fully still between handovers.

Grouped by the calculation that drives the value, the nine fall into four clusters.

01 · 02 — a time fraction bent through a function before it becomes geometry

Item 01 feeds elapsed time over SWEEP_MS into a triangle wave, then bends that triangle through a fifth-order smootherstep before mapping it onto the exponent range MIN_N to SUPER_N. Item 02 converts its angle value through Math.tan to get the horizontal radius from the fixed BEVEL_RY, then measures the facet with Math.hypot. Both turn a plain elapsed-time fraction into corner geometry through an explicit function rather than letting a CSS transition decide the in-between values.

03 · 04 · 09 — eased and springing values that overshoot or ease toward a target

Item 03 maps its press ratio through a cubic ease-out on the way up and a cubic ease-in on the way down, so the scoop radius rises fast then settles. Item 04's notch depth follows a springOvershoot function that passes the target and swings back before resting. Item 09 releases to a target through exponential decay, 1 - Math.exp(-INSET_SPRING_K * dt), rather than a fixed-duration tween.

05 · 07 · 08 — waves and cycles computed per frame

Item 05 computes four sine values at once, one per corner, each offset by Math.PI / 2 in phase, so the four radii never swell in lockstep. Item 07 walks a fixed five-rung ladder RUNGS with a cubic ease-in-out between rungs. Item 08 sweeps its radius through (1 - Math.cos(t * Math.PI * 2)) / 2 — a phase-matched cosine that starts at the minimum at t = 0 rather than at the midpoint.

06 — an interpolation ratio chased with inertial lerp

Item 06 never teleports its ratio to the target: each frame it closes a fraction 1 - Math.exp(-LERP_K * dt) of the remaining distance, so the same hover reads identically at 60 and 144 frames per second.

Code per pattern

01Squircle card — a superellipse exponent value flows between circle and square while the card's corner ridge changes

An exponent value rides a smootherstep-bent triangle wave from MIN_N (1) to SUPER_N (4.0) and back every SWEEP_MS, and each value lands as cornerShape = superellipse(n) with a fixed 40px radius, so the same card streams from a near-circle through a true squircle toward a square. A fit for an app-icon preview card or a gallery thumbnail card.

What the numbers say

Item 01 fills 1.36% of the frame cumulatively at the highest average intensity among the nine, 109.8, while moving in 23 of 23 sampled frames — the exponent sweep almost never pauses, and because the whole card edge re-rounds on every step, nearly every sampled frame carries a pixel change, with item 05 one tenth of an intensity point below at 109.7 so the top spot belongs to 01 by the measured number alone.

Squircle card — a superellipse exponent value flows between circle and square while the card's corner ridge changes
Open in a new tab

01 · Squircle card — a superellipse exponent value flows between circle and square while the card's corner ridge changes — Measured area 1.36% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

SUPER_NSWEEP_MS$subject-blue
  // Math layer: a smootherstep (5th-order polynomial, Perlin) unfolds the round-trip triangle wave into a smooth flow — not a linear tween
  function smootherstep(u) { return u * u * u * (u * (u * 6 - 15) + 10); }
  function triangle(x) { var f = x - Math.floor(x); return f < 0.5 ? f * 2 : (1 - f) * 2; }

  function human() { if (isDemo) { wrap.classList.remove('is-demo'); isDemo = false; } }

  function setN(n) {
    if (SUPPORTS) {
      card.style.cornerShape = 'superellipse(' + n.toFixed(3) + ')';
      card.style.borderRadius = '40px';
    } else {
      // Approximate fallback: the higher the superellipse exponent, the narrower the radius, imitating a squarer look (not the exact curve)
      card.style.borderRadius = (40 / n).toFixed(2) + 'px';
    }
    readout.textContent = 'Exponent value ' + n.toFixed(2);
  }

02Bevel chip — as the bevel angle value grows, the chip corner's facet width value grows with it

While the angle value climbs from MIN_DEG (8) toward BEVEL_DEG (18), the horizontal radius is computed as BEVEL_RY × Math.tan(rad) and the facet width as Math.hypot(rx, BEVEL_RY), so the cut face grows from a thin line into a real plane along the tangent rather than linearly. A fit for a price tag or label chip, or a status badge.

What the numbers say

Item 02 has both the lowest cumulative area among the nine, 0.33%, and the lowest average intensity, 73.2, while still moving in 23 of 23 sampled frames — a chip is a small object to begin with, and only one corner of it carries the bevel, so the facet keeps repainting almost every frame across a tiny area.

Bevel chip — as the bevel angle value grows, the chip corner's facet width value grows with it
Open in a new tab

02 · Bevel chip — as the bevel angle value grows, the chip corner's facet width value grows with it — Measured area 0.326% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

BEVEL_DEGBEVEL_RY$subject-blue-deep
  // Math layer: derives the horizontal radius from the bevel angle with trigonometry, and takes the hypotenuse of the two radii as the facet width
  function applyAngle(deg) {
    var rad = deg * Math.PI / 180;
    var rx = BEVEL_RY * Math.tan(rad);
    var facetWidth = Math.hypot(rx, BEVEL_RY);
    if (SUPPORTS) {
      chip.style.borderTopRightRadius = rx.toFixed(2) + 'px ' + BEVEL_RY + 'px';
    } else {
      // Approximate fallback: imitates with a rounded corner of the same radius size instead of a diagonal facet
      chip.style.borderTopRightRadius = facetWidth.toFixed(2) + 'px';
    }
    readout.textContent = 'Facet width ' + facetWidth.toFixed(1);
  }

03Scoop button — an inward-cut scoop curve value moves and the button outline changes with it

The scoop radius rises from SCOOP_MIN (4) toward SCOOP_MAX (28) under a cubic ease-out while the button is held and falls back under a cubic ease-in after release, so the concave cut deepens quickly then relaxes rather than moving at one flat speed. A fit for a next-step call button or a tag-remove button.

What the numbers say

Item 03 fills 1.99% of the frame cumulatively at a 90.0 average intensity while moving in 21 of 23 sampled frames, because the hold and release phases each run a full ease curve, and the three frames that sit still are the moments the radius rests at one end of its range between phases.

Scoop button — an inward-cut scoop curve value moves and the button outline changes with it
Open in a new tab

03 · Scoop button — an inward-cut scoop curve value moves and the button outline changes with it — Measured area 1.99% · moving frames 21/23Original by GODRICH · SCSS and React ship in the zip · See the password

SCOOP_MAXHOLD_MS$subject-mint
  // Math layer: bends the press-time ratio with a cubic ease-out and maps it onto the scoop radius — not a linear rise
  function easeOutCubic(t) { return 1 - Math.pow(1 - t, 3); }
  function easeInCubic(t) { return t * t * t; }

  function applyScoop(r) {
    if (SUPPORTS) {
      btn.style.cornerShape = 'scoop';
      btn.style.borderRadius = r.toFixed(2) + 'px';
    } else {
      // Approximate fallback: imitates with a rounded corner of the same radius instead of a concave scoop (only concave and convex differ)
      btn.style.borderRadius = r.toFixed(2) + 'px';
    }
    readout.textContent = 'Scoop radius ' + r.toFixed(1);
  }

04Notch tab — a groove is cut into the selected tab's corner by a notch-depth value

On every tab handover the notch depth follows springOvershoot, so the groove briefly cuts past NOTCH_MAX (14) and settles back, and the active tab reads from its outline alone. A fit for a document editor tab bar or a browser-tab UI.

What the numbers say

Item 04 has the fewest moving frames among the nine, 8 of 23, at a 94.7 average intensity and 3.21% cumulative area — the notch only travels during the spring after a handover, and the auto loop parks the depth at its settled value between handovers, so most sampled frames hold the same outline.

Notch tab — a groove is cut into the selected tab's corner by a notch-depth value
Open in a new tab

04 · Notch tab — a groove is cut into the selected tab's corner by a notch-depth value — Measured area 3.212% · moving frames 8/23Original by GODRICH · SCSS and React ship in the zip · See the password

NOTCH_MAXSPRING_MS$subject-sky
  // Math layer: on a tab change the notch depth moves in a damped oscillation (spring overshoot) that passes the target slightly, then settles
  function springOvershoot(t) {
    if (t <= 0) return 0;
    if (t >= 1) return 1;
    var c4 = (2 * Math.PI) / 3;
    return Math.pow(2, -10 * t) * Math.sin((t * 10 - 0.75) * c4) + 1;
  }

  function applyDepth(tab, depth) {
    if (SUPPORTS) {
      tab.style.cornerShape = 'notch';
      tab.style.borderRadius = Math.max(0, depth).toFixed(2) + 'px';
    } else {
      // Approximate fallback: imitates with a rounded corner of the same size instead of a cut notch (only cut and round differ)
      tab.style.borderRadius = Math.max(0, depth).toFixed(2) + 'px';
    }
  }

05Wave panel — the four corners' curve values sway in sequence with a phase offset

Each corner computes its own radius as BASE_R + AMP × Math.sin(t × 2π + i × π/2), so the four values are staggered by a quarter cycle each and the bulge travels around the panel like a wave making one full lap every WAVE_MS. A fit for a hero-section backdrop panel or an intro card.

What the numbers say

Item 05 fills 1.01% of the frame cumulatively at a 109.7 average intensity while moving in 23 of 23 sampled frames — second in intensity by 0.1 behind item 01 — because four corners each repaint on their own phase, so the outline is mid-swell somewhere around the panel in nearly every sampled frame.

Wave panel — the four corners' curve values sway in sequence with a phase offset
Open in a new tab

05 · Wave panel — the four corners' curve values sway in sequence with a phase offset — Measured area 1.01% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

AMPWAVE_MS$subject-lilac
  // Math layer: computes four sine waves at once, each corner's phase offset by PI/2, swelling them in turn like a wave
  function corners(t) {
    var out = [];
    for (var i = 0; i < 4; i++) {
      var phase = i * (Math.PI / 2);
      var r = BASE_R + AMP * Math.sin(t * Math.PI * 2 + phase);
      out.push(Math.max(2, r));
    }
    return out;
  }

  function applyCorners(rs) {
    for (var i = 0; i < 4; i++) {
      if (SUPPORTS) panel.style.cornerShape = 'superellipse(2.2)';
      panel.style['border' + CORNERS[i] + 'Radius'] = rs[i].toFixed(2) + 'px';
    }
    readout.textContent = 'Phase offset ' + (rs[0] - rs[2]).toFixed(1);
  }

06Hover morph — the corner curve value interpolates between the idle state and the hover state

Each hover change moves an interpolation ratio toward 0 or 1 through exponential decay rather than snapping it, and the radius rides that ratio between ROUND_R (48) and BEVEL_R (6) while the shape keyword itself crosses from round to bevel at the halfway point. A fit for a navigation item or a filter button.

What the numbers say

Item 06 has the largest cumulative area among the nine, 3.25%, at a 107.9 average intensity while moving in 13 of 23 sampled frames — the exponential decay closes most of the distance to the target in the first moments after each hover flip, then the outline barely changes for the rest of the half-cycle, so its area concentrates in short fast bursts rather than spreading evenly.

Hover morph — the corner curve value interpolates between the idle state and the hover state
Open in a new tab

06 · Hover morph — the corner curve value interpolates between the idle state and the hover state — Measured area 3.251% · moving frames 13/23Original by GODRICH · SCSS and React ship in the zip · See the password

LERP_KROUND_R$subject-blue-deep
  // Math layer: never snaps the ratio to its target but follows it with exponential decay (dt-based inertial lerp) — the interpolation ratio between the two shapes
  var last = 0;
  function stepRatio(ts) {
    var dt = last ? (ts - last) / 1000 : 0;
    last = ts;
    var follow = 1 - Math.exp(-LERP_K * dt);
    ratio += (target - ratio) * follow;
    if (Math.abs(ratio - target) < 0.001) ratio = target;
  }

  function applyMorph() {
    var r = ROUND_R + (BEVEL_R - ROUND_R) * ratio;
    var shape = ratio < 0.5 ? (SUPPORTS_ROUND ? 'round' : null) : (SUPPORTS_BEVEL ? 'bevel' : null);
    if (shape) card.style.cornerShape = shape;
    card.style.borderRadius = r.toFixed(2) + 'px';
    readout.textContent = 'Interpolation ratio ' + Math.round(ratio * 100) + '%';
  }

07Radius ladder — one card's radius value steps up and down a fixed five-rung ladder within the same curve kind

The card walks the RUNGS list [4, 12, 20, 28, 36], and goTo captures the current interpolated radius as the new starting point so a rung change never snaps the value mid-step. A fit for a design system's corner-token spec page.

What the numbers say

Item 07 fills 0.80% of the frame cumulatively at a 107.2 average intensity while moving in 15 of 23 sampled frames — the card dwells on each rung for AUTO_MS before the next 380 ms step, so the sampled frames split between brief interpolated climbs and quiet holds at a rung.

Radius ladder — one card's radius value steps up and down a fixed five-rung ladder within the same curve kind
Open in a new tab

07 · Radius ladder — one card's radius value steps up and down a fixed five-rung ladder within the same curve kind — Measured area 0.797% · moving frames 15/23Original by GODRICH · SCSS and React ship in the zip · See the password

RUNGSSTEP_MS$subject-pink
  // Math layer: interpolates between ladder rungs with a cubic ease-in-out — the value never snaps even when the rung changes
  function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : 1 - Math.pow(-2 * t + 2, 3) / 2; }

  function goTo(nextIdx, ts) {
    nextIdx = Math.max(0, Math.min(RUNGS.length - 1, nextIdx));
    if (nextIdx === idx) return;
    fromR = currentR(ts);
    idx = nextIdx;
    toR = RUNGS[idx];
    stepStart = ts;
    rungEl.textContent = String(idx + 1);
  }

  function currentR(ts) {
    var t = STEP_MS > 0 ? Math.min(1, (ts - stepStart) / STEP_MS) : 1;
    return fromR + (toR - fromR) * easeInOutCubic(t);
  }

08Fallback side-by-side — two panes take the same radius value, the native result beside a border-radius approximation

Both panes receive the same cosine-swept radius between R_MIN (6) and R_MAX (34), but the left pane adds cornerShape = superellipse(2.6) when supported while the right pane always stays a plain border-radius approximation, so the eye can find exactly where the two renderings split. A fit for a browser-support notice screen or a compatibility table.

What the numbers say

Item 08 fills 1.42% of the frame cumulatively at an 82.0 average intensity while moving in 23 of 23 sampled frames, because two panes repaint together on one cosine sweep — the motion is continuous, and the intensity sits in the lower half of the nine since each pane's corner change per frame is modest.

Fallback side-by-side — two panes take the same radius value, the native result beside a border-radius approximation
Open in a new tab

08 · Fallback side-by-side — two panes take the same radius value, the native result beside a border-radius approximation — Measured area 1.415% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

R_MAXSWEEP_MS$subject-lilac
  // Math layer: sweeps the radius back and forth with a cosine — a phase-matched cosine rather than a sine, so it starts at the minimum at t = 0
  function radiusAt(t) {
    var c = (1 - Math.cos(t * Math.PI * 2)) / 2;
    return R_MIN + (R_MAX - R_MIN) * c;
  }

  function applyBoth(r) {
    if (SUPPORTS) {
      nativeBox.style.cornerShape = 'superellipse(' + SUPER_N.toFixed(1) + ')';
      nativeBox.style.borderRadius = r.toFixed(2) + 'px';
    } else {
      nativeBox.style.borderRadius = r.toFixed(2) + 'px';
    }
    // The right pane always uses only the border-radius approximation — the two renderings sit side by side for comparison
    shimBox.style.borderRadius = r.toFixed(2) + 'px';
    readout.textContent = 'Current radius ' + r.toFixed(1);
  }

09Inset frame — an outer curve value and an inner curve value sit apart, forming a double border

The outer frame holds a fixed OUTER_R (40) radius while the inner curve is computed as Math.max(2, OUTER_R − inset) from an inset value that breathes between INSET_MIN (6) and INSET_MAX (22), so the gap between the two outlines varies along the corner and the double border flows. A fit for a profile-card border or a verified-mark frame.

What the numbers say

Item 09 fills 0.43% of the frame cumulatively at an 82.8 average intensity while moving in 23 of 23 sampled frames — only the inner curve moves while the outer frame holds still, so a thin ring of pixels changes almost every sampled frame while the rest of the card stays painted.

Inset frame — an outer curve value and an inner curve value sit apart, forming a double border
Open in a new tab

09 · Inset frame — an outer curve value and an inner curve value sit apart, forming a double border — Measured area 0.428% · moving frames 23/23Original by GODRICH · SCSS and React ship in the zip · See the password

OUTER_RINSET_MAX$subject-mint
  // Math layer: inset arithmetic — inner radius = outer radius − inset; the larger the inset, the deeper the inner curve is cut
  function innerRadius(inset) { return Math.max(2, OUTER_R - inset); }

  function applyInset(inset) {
    var r = innerRadius(inset);
    if (SUPPORTS) {
      frame.style.cornerShape = 'superellipse(3)';
      inner.style.cornerShape = 'superellipse(3)';
    }
    frame.style.borderRadius = OUTER_R + 'px';
    inner.style.borderRadius = r.toFixed(2) + 'px';
    readout.textContent = 'Inset ' + inset.toFixed(1);
  }

Where it breaks — unsupported browsers, fallback, reduced motion

Three spots show where a css corner-shape demo like this stops being smooth.

The property is missing and the approximation takes over

Every item checks CSS.supports once at startup, and where the check fails the code writes border-radius approximations instead — item 01 narrows the radius as the exponent grows, items 03 and 04 swap the concave scoop and cut notch for rounded corners of the same size. The outline keeps moving in every fallback, but the character changes: a scoop reads as convex, a notch reads as round, so a css squircle seen through a border-radius fallback is a cousin of the real shape, not the shape itself. Item 08 exists precisely to put that gap on screen, and its left caption rewrites itself to Unsupported fallback when the check fails, so the comparison still tells the truth on a browser without support.

A tab handover that lands mid-spring

Item 04's notch depth follows the spring only for SPRING_MS after a handover, and a second handover that arrives while the spring is still ringing restarts the clock from a new phaseStart rather than blending from the current depth — the groove jumps to the new tab and rings again from the beginning of its curve.

Reduced motion pins each item at one state, differently

Each of the nine carries its own prefers-reduced-motion branch, and what the branch pins differs by item: 01 fixes the exponent at SUPER_N, 02 fixes the angle at BEVEL_DEG, 03 applies the scoop radius at its full SCOOP_MAX immediately, 04 sets the notch depth straight to NOTCH_MAX without the spring, 05 freezes the wave phase at a fixed t, 06 sets the ratio straight to the hover target, 07 climbs straight to the top rung, 08 pins t at 0.5 which is the R_MAX state of the cosine sweep, and 09 fixes the inset at INSET_MAX. The Sass side pairs every one of these with transition: none under the same media query.

Where values change ridges and facets — exponent, angle, and ratio basis

Three items answer three different bases. Item 01's ridge answers an exponent value: the same 40px radius renders as a near-circle at exponent 1 and as a squircle at 4.0 — this is the css corner shape squircle case in its purest form — so the exponent alone decides how square the corner reads. Item 02's facet answers an angle value: BEVEL_RY stays fixed at 14px while Math.tan widens only the horizontal radius, so the facet width follows the tangent of the angle and doubles more than linearly when the angle doubles. Item 06's outline answers a ratio value: neither the round shape nor the bevel shape moves on its own — only the interpolation ratio between them does, so the same card carries two fixed endpoints and one traveling value. All nine items are in one zip behind one password, x4zdvxz7, so there is no separate unlock per pattern.

These corner cutting patterns slot next to three earlier sets. 9 CSS Card Hover Effects — One Line, Copy-Paste lifts a whole card on hover with one property change, where item 06 here morphs the corner curve instead of the card's position. 9 CSS Badge Design Ideas — New, Sale, Verified builds badge shapes as static compositions, while item 02 turns one bevel facet into a live value. Avatar UI Design: 9 Parts, No Image Files composes a profile block from parts, and item 09's inset frame is the border layer such a block could carry.

Three variants and accessibility

Variant What changes What it stays away from
Raise the squircle exponent 01 SUPER_N 4.0 → 8.0 MIN_N, SWEEP_MS, the 40px radius
Widen the bevel angle 02 BEVEL_DEG 18 → 36 MIN_DEG, BEVEL_RY, BEVEL_MS
Speed up the exponent sweep 01 SWEEP_MS 2400 → 1200 SUPER_N, MIN_N, the preset list

Raising 01's SUPER_N from 4.0 to 8.0 pushes the flow's ridge deeper toward the square, since the source streams the exponent from MIN_N (1) up to the ceiling through the smooth interpolation, so changing the ceiling alone re-textures the whole flow. Raising 02's BEVEL_DEG from 18 to 36 opens the facet wider than linear, because the horizontal depth is computed as BEVEL_RY × tan(angle) and measured with hypot, so doubling the angle more than doubles the facet. Halving 01's SWEEP_MS from 2400 ms to 1200 ms makes the circle-to-square flow exactly twice as fast, since the source feeds the exponent from a triangle wave of elapsed time over SWEEP_MS.

On the input side, grep across the nine files shows the listeners split three ways: items 01 and 02 listen for click alone; items 04, 05, 07, and 08 pair click with keydown; item 03 adds pointerdown, pointerup, pointercancel, and pointerleave to keydown and keyup because it tracks a held press; item 06 reads pointerenter and pointerleave with focus and blur and click; item 09 wires pointerdown, pointerup, and pointerleave with keydown and keyup. Every button carries a readable label or text content, each readout paragraph is marked aria-live="polite" so the number under the card is announced as it changes, and the toggle-style buttons in 01, 02, 03, 05, 06, and 09 expose their state through aria-pressed. The automatic playback in every item runs only while the is-demo class is present and the reduced-motion media query is unset, and the first real pointer or key input strips that class, so the corner never keeps dancing after a visitor takes over.

FAQ

Does css corner shape work everywhere, or do these css corner shape examples need a fallback?

Each item runs the same one-line check, CSS.supports with a corner-shape pair, at startup and writes a border-radius approximation when it fails — so in a supporting environment you get the property itself, and anywhere else the outline still moves on the same numbers, just as an approximation. Item 08 puts the two renderings side by side so the difference is visible rather than described.

Are these css squircle border radius patterns one file each, or nine settings of one component?

Nine independent files — each keeps its own constants and its own apply function, and every fence above is a direct excerpt from that item's file rather than output of a shared generator. The zip carries all nine html, scss, and js files together, so you can lift one pattern without dragging the other eight along.

Why does item 08 call its approximation pane a fallback instead of a polyfill?

Because it does not install the property where it is missing — it only draws a border-radius stand-in next to the native rendering and compares them. A real polyfill would have to synthesize the corner curve itself, while this pane simply shows what a browser without the property would paint for the same radius value.

Sources: MDN — corner-shape · MDN — border-radius · MDN — superellipse() · MDN — @supports

Enter the archive password

The password is inside this article. You will find it as you read.