惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

The Cloudflare Blog
A
About on SuperTechFans
腾讯CDC
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Google Online Security Blog
Google Online Security Blog
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
小众软件
小众软件
酷 壳 – CoolShell
酷 壳 – CoolShell
H
Heimdal Security Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Jina AI
Jina AI
爱范儿
爱范儿
D
DataBreaches.Net
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
Security Archives - TechRepublic
Security Archives - TechRepublic
P
Proofpoint News Feed
P
Privacy International News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Palo Alto Networks Blog
S
SegmentFault 最新的问题
U
Unit 42
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
美团技术团队
T
Tenable Blog
V
V2EX
M
MIT News - Artificial intelligence
Recorded Future
Recorded Future
A
Arctic Wolf
Hacker News - Newest:
Hacker News - Newest: "LLM"
Last Week in AI
Last Week in AI
P
Proofpoint News Feed
Stack Overflow Blog
Stack Overflow Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
G
GRAHAM CLULEY
P
Privacy & Cybersecurity Law Blog
Martin Fowler
Martin Fowler
人人都是产品经理
人人都是产品经理
Google DeepMind News
Google DeepMind News
L
LINUX DO - 热门话题
博客园 - 【当耐特】
博客园 - 叶小钗
S
Securelist
T
Tor Project blog
Forbes - Security
Forbes - Security
O
OpenAI News
IT之家
IT之家
博客园 - Franky

CSS-Tricks

writing-mode | CSS-Tricks pointer-events | CSS-Tricks What’s !important #15: Boundary-aware CSS, Time-based CSS, Full-bleed CSS, and More | CSS-Tricks Get Ready For the Powerful CSS border-shape Property! | CSS-Tricks What’s !important #14: Gap Decorations, random(), <select> field sizing, and More | CSS-Tricks The Shifting Line Between CSS States and JavaScript Events | CSS-Tricks translateZ() | CSS-Tricks translateY() | CSS-Tricks translateX() | CSS-Tricks translate() | CSS-Tricks Using Scroll-Driven Animations for Opposing Scroll Directions | CSS-Tricks A First Look at Scroll-Triggered Animations | CSS-Tricks The Siren Song of  ariaNotify() | CSS-Tricks Prop For That | CSS-Tricks What’s !important #13: @function, alpha(), CSS Wordle, and More | CSS-Tricks There’s no need to include ‘navigation’ in your navigation labels | CSS-Tricks Why Isn't My 3D View Transition Working? | CSS-Tricks Creating Memorable Web Experiences: A Modern CSS Toolkit | CSS-Tricks Scroll-Driven, Scroll-Triggered, Scroll States, and View Transitions | CSS-Tricks Another Stab at the Perfect CSS Pie Chart... Sans JavaScript! | CSS-Tricks offset-path | CSS-Tricks @custom-media | CSS-Tricks @function | CSS-Tricks ::search-text | CSS-Tricks Astro Markdown Component Utility for Any Framework | CSS-Tricks What’s !important #12: Safari Testing, ::checkmark, HTML Anchor Positioning, and More | CSS-Tricks Revealing Text With CSS letter-spacing | CSS-Tricks Technical Writing in the AI Age | CSS-Tricks Cross-Document View Transitions: Scaling Across Hundreds of Elements | CSS-Tricks The State of CSS Centering in 2026 | CSS-Tricks Stack Overflow: When We Stop Asking | CSS-Tricks Cross-Document View Transitions: The Gotchas Nobody Mentions | CSS-Tricks What’s !important #11: 3D Voxel Scenes, Flying Focus, CSS Syntaxes, and More | CSS-Tricks Computing and Displaying Discounted Prices in CSS | CSS-Tricks rotateX() | CSS-Tricks rotateY() | CSS-Tricks rotateZ() | CSS-Tricks rotate() | CSS-Tricks Soon We Can Finally Banish JavaScript to the ShadowRealm | CSS-Tricks contrast() | CSS-Tricks contrast-color() | CSS-Tricks hypot() | CSS-Tricks saturate() | CSS-Tricks justify-self | CSS-Tricks
Using CSS corner-shape For Folded Corners | CSS-Tricks
Daniel Schwarz · 2026-05-08 · via CSS-Tricks

I came across Kitty Giraudel’s folded corners technique. It leverages CSS clip-path, and I thought that that was such a cool way to do it. clip-path has been trending lately, most likely because web browsers support the shape() function now.

However, I’ve been on a bit of a corner-shape kick lately (have a look at my introduction to corner-shape as well as these scroll-driven corner-shape animations), so I figured that corner-shape could be used to create folded corners as well, and this is what I came up with:

White paper with the top-right corner folded in.

So open Chrome, which supports corner-shape, and let’s dig in (if you’re looking at this in other browsers, it basically falls back to a rounded corner).

Step 1: Set some CSS variables

Elements have four corners, but when we use border-radius, each corner is split into two coordinates. The x-axis coordinate moves along the x-axis, away from its associated corner, while the y-axis coordinate does the same thing along the y-axis. It’s from these coordinates that border-radius draws the curvature of the rounded corners.

Diagramming the shape showing border-radius applied to the bottom-left corner. The rounded corner is 50% on the y-axis and 50% on the x-axis.

First, store the coordinates as CSS variables. We’ll need the values that they hold more than once, so this simplifies things, makes the fold animatable, and maintains some degree of realism.

:root {
  /* x-axis coordinate */
  --x-coord: 9rem;

  /* y-axis coordinate */
  --y-coord: 5rem;
}

Step 2: Establishing the fold

Given what we now know about border-radius, it should be obvious what border-top-right-radius does. As for corner-top-right-shape: bevel, that ensures that a straight line is drawn between the coordinates instead of rounded corners (corner-top-right-shape: round). That’s right, border-radius includes corner-shape: round by default (behind the scenes, of course).

/* Square */
div {
  /* Place coordinates */
  border-top-right-radius: var(--x-coord) var(--y-coord);

  /* Draw line between coordinates */
  corner-top-right-shape: bevel;
}
White paper with a diagonal cut in the top-right corner.

Step 3: Creating the flip side

Now that we’ve established the fold, it’s time to create the flip side. Start by selecting ::before, then declare content: "" to create the element without content. The background can be inherited from the square, and the dimensions should leverage the coordinates that we saved. As you can see, I’ve also added a box-shadow where the blur radius scales with --x-coord and --y-coord, but you’re welcome to adapt the formula as you see fit.

/* Square */
div {
  /* Place coordinates */
  border-top-right-radius: var(--x-coord) var(--y-coord);

  /* Draw line between coordinates */
  corner-top-right-shape: bevel;

  /* Flip side */
  &::before {
    /* Generate empty element */
    content: "";

    /* Inherit background */
    background: inherit;

    /* Same as coordinates */
    width: var(--x-coord);
    height: var(--y-coord);

    /* Scale blur radius with --x-coord and --y-coord */
    box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;
  }
}
White paper with s white rectangle in the top-left corner and a diagonal cut in the top-right corner.

Step 4: Positioning the flip side (::before)

Next, we need to shift ::before to the (top-)right corner. We’re avoiding anchor positioning, because there’s no need for modern features if more supported features work well using the same amount of code. So, declare position: relative on the square and position: absolute on ::before. This makes ::before position relative to the square, and is a trick that only works for parent-child relationships. Actually, this shortcoming is why anchor positioning was invented, but we just don’t need it in this case.

In addition, declare inset: 0 0 auto auto on ::before to align it to the top-right corner of the square, and overflow: clip on the square to clip the half of ::before that overflows it.

/* Square */
div {
  /* Place coordinates */
  border-top-right-radius: var(--x-coord) var(--y-coord);

  /* Draw line between coordinates */
  corner-top-right-shape: bevel;

  /* Clip any overflow */
  overflow: clip;

  /* For alignment */
  position: relative;

  /* Flip side */
  &::before {
    /* Generate empty element */
    content: "";

    /* Inherit background */
    background: inherit;

    /* Same as coordinates */
    width: var(--x-coord);
    height: var(--y-coord);

    /* Scale blur radius with --x-coord and --y-coord */
    box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;

    /* For alignment */
    position: absolute;

    /* Align to top-right */
    inset: 0 0 auto auto;
  }
}
White paper with the top-right corner folded in.

You can stop here if you want, but there’s room for improvement…

Step 5: Sculpting the flip side

To make the outcome look a bit more realistic, we’ll use corner-bottom-left-shape: bevel to make one more straight cut, this time to ::before. There are, most likely, many ways to tackle this depending on how sharply we want to crease the fold, how elevated we want the flip side to be, and the angle from which we want to view the square, but I don’t think it matters as long as the effect looks decent, so we’re aiming for a sharp crease, the flip side sticking up, and an aerial view. If you’d rather something different, keep in mind that the shadow also impacts the outcome, and that you’d be facing a trickier implementation.

The only degree of complexity that I suggest is this:

/* Ensure realistic fold */
@container style(--x-coord < --y-coord) {
  border-bottom-left-radius: 100% calc(100% - var(--x-coord));
}

@container style(--x-coord >= --y-coord) {
  border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
}

These are container style queries using the range syntax, where if the value of --x-coord is less than the value of --y-coord, we subtract the value of --x-coord from 100% and use it as the y-axis coordinate for the relevant border radius (border-bottom-left-radius, in this case). The other axis is set to 100%. Adversely, if the value of --x-coord is more than (or equal to) the value of --y-coord, we subtract the value of --y-coord from 100% and use it as the x-axis coordinate. Once again, the other axis is set to 100%.

The result is that the crease, shadow, and now perspective of the fold is calculated using only --x-coord and --y-coord to look realistic (or realistic enough, anyway). Using the slideVars toggles in the top-right corner of the demo, you can see for yourself by testing various combinations of coordinates:

If you want to implement a failsafe to ensure that the coordinates don’t exceed the dimensions of the square, breaking the effect, you can use min(). The modified coordinate variables below set --y-coord to an impossible 999999999rem, but caps it at the height of the square (although I can’t imagine that you’d actually need this, to be completely honest):

--x-coord: min(--square-width, 9rem);
--y-coord: min(--square-height, 999999999rem);
White paper with the top-right corner folded in.

All in all, we have not only a folded corner effect but a utility that builds the effect based on only two coordinates.

The full code:

:root {
  /* x-axis coordinate */
  --x-coord: 9rem;

  /* y-axis coordinate */
  --y-coord: 5rem;

  /* Square */
  div {
    /* Place coordinates */
    border-top-right-radius: var(--x-coord) var(--y-coord);

    /* Draw line between coordinates */
    corner-top-right-shape: bevel;

    /* Clip any overflow */
    overflow: clip;

    /* For alignment */
    position: relative;

    /* Flip side */
    &::before {
      /* Generate empty element */
      content: "";

      /* Inherit background */
      background: inherit;

      /* Same as coordinates */
      width: var(--x-coord);
      height: var(--y-coord);

      /* Scale blur radius with --x-coord and --y-coord */
      box-shadow: 0 0 calc((var(--x-coord) + var(--y-coord)) / 3) #00000050;

      /* For alignment */
      position: absolute;

      /* Align to top-right */
      inset: 0 0 auto auto;

      /* Draw line between coordinates */
      corner-bottom-left-shape: bevel;

      /* Ensure realistic fold */
      @container style(--x-coord < --y-coord) {
        border-bottom-left-radius: 100% calc(100% - var(--x-coord));
      }

      @container style(--x-coord >= --y-coord) {
        border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
      }
    }
  }
}

Note: We could swap container style queries for if() functions, which are shorter but less readable.

Folded corners using clip-path vs. corner-shape

Kitty’s Giraudel’s folded corners work in all browsers, and because clip-path is used, which is a more versatile shaping feature, there are more ways to customize the shape. It’s also the more correct approach, for whatever that’s worth. However, my corner-shape approach is cleaner and likely wouldn’t require any further customization anyway, but lacks Safari and Firefox support for now. So unless you need folded corners today, I’d bookmark both: