I got here throughout Kitty Giraudel’s folded corners method. It leverages CSS clip-path, and I believed that that was such a cool approach to do it. clip-path has been trending currently, most probably as a result of internet browsers help the form() perform now.
Nonetheless, I’ve been on a little bit of a corner-shape kick currently (take a look at my introduction to corner-shape in addition to these scroll-driven corner-shape animations), so I figured that corner-shape might be used to create folded corners as properly, and that is what I got here up with:

So open Chrome, which helps corner-shape, and let’s dig in (in case you’re taking a look at this in different browsers, it principally falls again to a rounded nook).
Step 1: Set some CSS variables
Parts have 4 corners, however after we use border-radius, every nook is cut up into two coordinates. The x-axis coordinate strikes alongside the x-axis, away from its related nook, whereas the y-axis coordinate does the identical factor alongside the y-axis. It’s from these coordinates that border-radius attracts the curvature of the rounded corners.

First, retailer the coordinates as CSS variables. We’ll want the values that they maintain greater than as soon as, so this simplifies issues, makes the fold animatable, and maintains some extent of realism.
:root {
/* x-axis coordinate */
--x-coord: 9rem;
/* y-axis coordinate */
--y-coord: 5rem;
}
Step 2: Establishing the fold
Given what we now find out about border-radius, it must be apparent what border-top-right-radius does. As for corner-top-right-shape: bevel, that ensures {that a} straight line is drawn between the coordinates as an alternative of rounded corners (corner-top-right-shape: spherical). That’s proper, border-radius contains corner-shape: spherical by default (behind the scenes, in fact).
/* Sq. */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
}

Step 3: Creating the flip aspect
Now that we’ve established the fold, it’s time to create the flip aspect. Begin by choosing ::earlier than, then declare content material: "" to create the aspect with out content material. The background may be inherited from the sq., and the size ought to leverage the coordinates that we saved. As you possibly can see, I’ve additionally added a box-shadow the place the blur radius scales with --x-coord and --y-coord, however you’re welcome to adapt the method as you see match.
/* Sq. */
div {
/* Place coordinates */
border-top-right-radius: var(--x-coord) var(--y-coord);
/* Draw line between coordinates */
corner-top-right-shape: bevel;
/* Flip aspect */
&::earlier than {
/* Generate empty aspect */
content material: "";
/* Inherit background */
background: inherit;
/* Similar as coordinates */
width: var(--x-coord);
top: 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;
}
}

Step 4: Positioning the flip aspect (::earlier than)
Subsequent, we have to shift ::earlier than to the (top-)proper nook. We’re avoiding anchor positioning, as a result of there’s no want for contemporary options if extra supported options work properly utilizing the identical quantity of code. So, declare place: relative on the sq. and place: absolute on ::earlier than. This makes ::earlier than place relative to the sq., and is a trick that solely works for parent-child relationships. Really, this shortcoming is why anchor positioning was invented, however we simply don’t want it on this case.
As well as, declare inset: 0 0 auto auto on ::earlier than to align it to the top-right nook of the sq., and overflow: clip on the sq. to clip the half of ::earlier than that overflows it.
/* Sq. */
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 */
place: relative;
/* Flip aspect */
&::earlier than {
/* Generate empty aspect */
content material: "";
/* Inherit background */
background: inherit;
/* Similar as coordinates */
width: var(--x-coord);
top: 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 */
place: absolute;
/* Align to top-right */
inset: 0 0 auto auto;
}
}

You’ll be able to cease right here if you need, however there’s room for enchancment…
Step 5: Sculpting the flip aspect
To make the result look a bit extra reasonable, we’ll use corner-bottom-left-shape: bevel to make yet one more straight lower, this time to ::earlier than. There are, most probably, some ways to sort out this relying on how sharply we need to crease the fold, how elevated we wish the flip aspect to be, and the angle from which we need to view the sq., however I don’t suppose it issues so long as the impact appears to be like respectable, so we’re aiming for a pointy crease, the flip aspect sticking up, and an aerial view. When you’d moderately one thing completely different, remember the fact that the shadow additionally impacts the result, and that you just’d be dealing with a trickier implementation.
The one diploma of complexity that I recommend is that this:
/* Guarantee reasonable fold */
@container type(--x-coord < --y-coord) {
border-bottom-left-radius: 100% calc(100% - var(--x-coord));
}
@container type(--x-coord >= --y-coord) {
border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
}
These are container type queries utilizing the vary syntax, the place if the worth of --x-coord is lower than the worth of --y-coord, we subtract the worth of --x-coord from 100% and use it because the y-axis coordinate for the related border radius (border-bottom-left-radius, on this case). The opposite axis is about to 100%. Adversely, if the worth of --x-coord is extra than (or equal to) the worth of --y-coord, we subtract the worth of --y-coord from 100% and use it because the x-axis coordinate. As soon as once more, the opposite axis is about to 100%.
The result’s that the crease, shadow, and now perspective of the fold is calculated utilizing solely --x-coord and --y-coord to look reasonable (or reasonable sufficient, anyway). Utilizing the slideVars toggles within the top-right nook of the demo, you possibly can see for your self by testing numerous mixtures of coordinates:
If you wish to implement a failsafe to make sure that the coordinates don’t exceed the size of the sq., breaking the impact, you should utilize min(). The modified coordinate variables beneath set --y-coord to an inconceivable 999999999rem, however caps it on the top of the sq. (though I can’t think about that you just’d really want this, to be fully trustworthy):
--x-coord: min(--square-width, 9rem);
--y-coord: min(--square-height, 999999999rem);

All in all, now we have not solely a folded nook impact however a utility that builds the impact primarily based on solely two coordinates.
The complete code:
:root {
/* x-axis coordinate */
--x-coord: 9rem;
/* y-axis coordinate */
--y-coord: 5rem;
/* Sq. */
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 */
place: relative;
/* Flip aspect */
&::earlier than {
/* Generate empty aspect */
content material: "";
/* Inherit background */
background: inherit;
/* Similar as coordinates */
width: var(--x-coord);
top: 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 */
place: absolute;
/* Align to top-right */
inset: 0 0 auto auto;
/* Draw line between coordinates */
corner-bottom-left-shape: bevel;
/* Guarantee reasonable fold */
@container type(--x-coord < --y-coord) {
border-bottom-left-radius: 100% calc(100% - var(--x-coord));
}
@container type(--x-coord >= --y-coord) {
border-bottom-left-radius: calc(100% - var(--y-coord)) 100%;
}
}
}
}
Observe: We might swap container type queries for if() capabilities, that are shorter however much less readable.
Folded corners utilizing clip-path vs. corner-shape
Kitty’s Giraudel’s folded corners work in all browsers, and since clip-path is used, which is a extra versatile shaping function, there are extra methods to customise the form. It’s additionally the extra right strategy, for no matter that’s price. Nonetheless, my corner-shape strategy is cleaner and sure wouldn’t require any additional customization anyway, however lacks Safari and Firefox help for now. So except you want folded corners at present, I’d bookmark each:









