Skip to content

Commit 85e0ca0

Browse files
noamrtabatkins
andauthored
[css-borders-4] Specify corner-shape based on superellipse (#11606)
* [css-borders-4] Specify `corner-shape` based on superellipse This specifies the `corner-shape` group, including: - general description and interaction with border-radius - all the individual corners, side shorthands, and overall shorthand - multiple keywords, and how they translate to a `superellipse()` - The superellipse formula, and how it is rendered - How the exponent of the superellipse interpolates Open issues (will open separately): - Add a few examples - Resolve on "straight" vs "none" for the convex angle. - Resolve on the exact interpolation formula - Define restrictions for border rendering Closes #10993 Based on resolution #10993 (comment) Co-authored-by: Tab Atkins Jr. <[email protected]>
1 parent 947cd87 commit 85e0ca0

File tree

1 file changed

+155
-43
lines changed

1 file changed

+155
-43
lines changed

css-borders-4/Overview.bs

+155-43
Original file line numberDiff line numberDiff line change
@@ -336,29 +336,168 @@ The 'border-radius' shorthand</h4>
336336
See [[CSS3BG]].
337337

338338
<h3 id=corner-shaping>
339-
Corner Shaping: the 'corner-shape' property</h3>
339+
Corner Shaping</h3>
340+
341+
By default, non-zero border-radii define a quarter-ellipse that rounds the affected corners.
342+
However in some cases, other corner shapes are desired.
343+
The 'corner-shape' property group specifies a reinterpretation of the radii to define other corner shapes.
344+
345+
The different shapes applicable to 'corner-shape' can be expressed as different parameters to a superellipse.
346+
A superellipse is a closed curve resembling an ellipse, and based on its `k` parameter can express all the shapes between a square, an ellipse, and a notch.
347+
348+
To allow full expression as well as interpolation, the 'corner-shape' properties can provide its own superellipse parameter using the 'superellipse()' function,
349+
or use one of the supplied keywords which represent commonly used parameters. See the <<corner-shape-value>> definition for details.
350+
351+
<h4 id=corner-shape-rendering>
352+
Rendering 'corner-shape'</h4>
353+
'corner-shape' works alongside 'border-radius', and does not have any visual effect with a 'border-radius' of 0.
354+
It acts as an alteration on top of the default round 'border-radius', and thus can be used as progressive enhancement.
355+
356+
Like 'border-radius', 'corner-shape' clips elements according to the [=overflow=] rules, and applies to the rendering of the border.
357+
Since stroking a superellipse accurately may be computationally intensive, user agents may approximate the path using bezier curves,
358+
as well as account for sharp edges and overlaps.
359+
360+
Issue: 'border-radius' already handles *adjacent* corners overlapping by shrinking the radiuses proportionally.
361+
A negative ''superellipse()'' parameter allows for *opposite* corners to sometimes overlap, and needs additional restrictions defined.
362+
363+
Issue <a href="https://github.com/w3c/csswg-drafts/issues/11610">#11610</a>: check if we need additional rendering restrictions.
364+
365+
<h4 id=corner-shape-value>
366+
'corner-shape' values</h4>
367+
368+
<pre class=prod>
369+
<dfn><<corner-shape-value>></dfn> = ''round'' | ''scoop'' | ''bevel'' | ''notch'' | ''straight'' | ''squircle'' | superellipse(<<number [0,&infin;]>>)
370+
</pre>
371+
372+
<dl dfn-type="value" dfn-for="<corner-shape-value>">
373+
<dt><dfn>round</dfn>
374+
<dd>
375+
Border radii define a convex elliptical curve at the corner. Equivalent to <css>superellipse(2)</css>.
376+
377+
Note: this is the initial value of 'corner-shape' properties, as elements with 'border-radius' would be rounded.
378+
379+
<dt><dfn>scoop</dfn>
380+
<dd>Border radii define a concave elliptical curve at the corner. Equivalent to <css>superellipse(0.5)</css>.
381+
<dt><dfn>bevel</dfn>
382+
<dd>Border radii define a diagonal slice at the corner. Equivalent to <css>superellipse(1)</css>.
383+
<dt><dfn>notch</dfn>
384+
<dd>Border radii define a concave 90deg angle at the corner. Equivalent to <css>superellipse(0)</css>.
385+
<dt><dfn>straight</dfn>
386+
<dd>Border radii define a convex 90deg angle at the corner.
387+
This would have the same visual effect as a 'border-radius' of 0. This is different from having a 'border-radius' of 0 when animating.
388+
Equivalent to <css>superellipse(infinity)</css>.
389+
<dt><dfn>squircle</dfn>
390+
<dd>Border radii define a convex curve between an ellipse and an convex angle, equivalent to <css>superellipse(4)</css>.
391+
</dl>
392+
393+
Issue <a href="https://github.com/w3c/csswg-drafts/issues/11607">#11607</a>: resolve on ''straight'' vs <css>none</css>.
394+
395+
The <dfn>superellipse( <<number>> | infinity )</dfn> function describes the curvature of the corner.
396+
It accepts a <dfn>superellipse exponent</dfn>, which defines the curvature of the corner, or the exponent of the formula.
397+
The [=superellipse exponent=] accepts values between 0 (a straight concave angle) and <css>infinity</css> (a straight convex angle),
398+
with the values in between representing the curvatures in between.
399+
400+
The ''superellipse()'' formula can be described in cartesian coordinates, as follows,
401+
where <code>a</code> is the horizontal ''border-radius''
402+
<code>b</code> is the vertical ''border-radius'', and <code>k</code> is the [=superellipse exponent=]:
403+
404+
<pre>
405+
|x/a|^k + |y/b|^k = 1
406+
</pre>
407+
408+
<h4 id=corner-shape-shorthand>
409+
Corner Shaping: the 'corner-shape' and 'corner-*-shape' properties</h4>
340410

341411
<pre class="propdef">
342412
Name: corner-shape
343-
Value: [ round | angle ]{1,4}
413+
Value: <<corner-shape-value>>{1,2} / [ <<corner-shape-value>>{1,2} ]?
344414
Initial: round
345-
Applies to: all elements, except table element when 'border-collapse' is ''collapse''
415+
Applies to: all elements where 'border-radius' can apply
346416
Inherited: no
347-
Animation type: discrete
417+
Animation type: see individual properties
348418
</pre>
349419

350-
By default, non-zero border-radii define
351-
a quarter-ellipse that rounds the affected corners.
352-
However in some cases, other corner shapes are desired.
353-
The 'corner-shape' property specifies a reinterpretation of the radii
354-
to define other corner shapes.
355-
356-
<dl dfn-type="value" dfn-for="corner-shape">
357-
<dt><dfn>''round''</dfn>
358-
<dd>Border radii define a convex elliptical curve at the corner.
359-
<dt><dfn>''angle''</dfn>
360-
<dd>Border radii define a diagonal slice at the corner.
361-
</dl>
420+
Applies the shape to all corners, following the same rules as ''border-radius''.
421+
422+
<pre class=propdef>
423+
Name: corner-top-left-shape, corner-top-right-shape, corner-bottom-right-shape, corner-bottom-left-shape, corner-start-start-shape, corner-start-end-shape, corner-end-start-shape, corner-end-end-shape
424+
Value: <<corner-shape-value>>
425+
Initial: round
426+
Applies to: all elements where 'border-radius' can apply
427+
Inherited: no
428+
Logical property group: corner-shape
429+
Computed value: the corresponding ''superellipse()'' value
430+
Animation Type: see [=superellipse interpolation=]
431+
</pre>
432+
433+
The [=flow-relative=] properties
434+
'corner-start-start-shape',
435+
'corner-start-end-shape',
436+
'corner-end-start-shape',
437+
and 'corner-end-end-shape'
438+
correspond to the [=physical=] properties
439+
'corner-top-left-shape',
440+
'corner-bottom-left-shape',
441+
'corner-top-right-shape',
442+
and 'corner-bottom-right-shape'.
443+
The mapping depends on the element’s 'writing-mode', 'direction', and 'text-orientation',
444+
with the first start/end giving the block axis side,
445+
and the second the inline-axis side
446+
(i.e. patterned as 'corner-<var>block</var>-<var>inline</var>-shape').
447+
448+
<pre class=propdef>
449+
Name: corner-top-shape, corner-right-shape, corner-bottom-shape, corner-left-shape,
450+
corner-block-start-shape, corner-block-end-shape, corner-inline-start-shape, corner-inline-end-shape
451+
Value: <<corner-shape-value>> [ / <<corner-shape-value>> ]
452+
Initial: round
453+
Applies to: all elements where 'border-radius' can apply
454+
Inherited: no
455+
Computed value: see individual properties
456+
Animation type: see individual properties
457+
</pre>
458+
459+
<p>The 'corner-*-shape' shorthands set the two 'corner-*-*-shape'
460+
longhand properties of the related side. If values are given before
461+
and after the slash, then the values before the slash set the
462+
horizontal radius and the values after the slash set the vertical radius.
463+
If there is no slash, then the values set both radii equally.
464+
The two values for the radii are given in the order
465+
top-left, top-right for 'corner-top-shape',
466+
top-right, bottom-right for 'corner-right-shape',
467+
bottom-left, bottom-right for 'corner-bottom-shape',
468+
top-left, bottom-left for 'corner-left-shape',
469+
start-start, start-end for 'corner-block-start-shape',
470+
end-start, end-end for 'corner-block-end-shape'
471+
start-start, end-start for 'corner-inline-start-shape',
472+
and start-end, end-end for 'corner-inline-end-shape'.
473+
If the second value is omitted it is copied from the first.
474+
475+
476+
<h4 id=corner-shape-interpolation>
477+
Interpolating corner shapes</h4>
478+
479+
Since a <<corner-shape-value>> can always be expressed by a ''superellipse()'' with an [=superellipse exponent=] variable, interpolating between two
480+
<<corner-shape-value>>s is done by interpolating the [=superellipse exponent=] itself.
481+
Since it's an exponent, interpolating it linearly would result in an effect where concave corners interpolate at a much higher velocity than convex corners.
482+
To balance that, the <dfn>superellipse interpolation</dfn> formula describes how a [=superellipse exponent=] is converted to a value between 0 and 1, and vice versa:
483+
484+
<div algorithm="superellipse-exponent-to-interpolation-value">
485+
To interpolate a <<number [0,&infin;]>> |exponent| to an interpolation value between 0 and 1:
486+
1. If |exponent| is 0, return 0.
487+
1. If |exponent| is &infin;, return 1.
488+
1. Return <code>1/(2^(1/|exponent|))</code>.
489+
490+
To convert a <<number [0,1]>> |interpolationValue| back to a [=superellipse exponent=]:
491+
1. If |interpolationValue| is 0, return 0.
492+
1. If |interpolationValue| is 1, return &infin;.
493+
1. Return <code>ln(0.5)/ln(|interpolationValue|)</code>.
494+
</div>
495+
496+
<a href="https://github.com/w3c/csswg-drafts/issues/11608">Issue #11608</a>: resolve on this or another interpolation formula.
497+
498+
<pre>
499+
500+
</pre>
362501

363502
<div class="example">
364503
For example, the following declarations create a right-pointing next button.
@@ -398,33 +537,6 @@ Corner Shaping: the 'corner-shape' property</h3>
398537
How to allow custom corners? Perhaps a ''path()'' function? Or a ''cubic-bezier()''?
399538
Something else?
400539

401-
<h3 id="corners-shorthand">
402-
Corner Shape and Size: the 'corners' shorthand</h3>
403-
404-
<pre class="propdef shorthand">
405-
Name: corners
406-
Value: <<'corner-shape'>> || <<'border-radius'>>
407-
</pre>
408-
409-
The 'corners' shorthand sets 'corner-shape' and 'border-radius' in the same declaration.
410-
If either is omitted, it is reset to its initial value.
411-
412-
<div class="example">
413-
For example, the following declaration creates a diamond shape.
414-
<pre>corners: angle 50%;</pre>
415-
In UAs that don't support 'corner-shape', the declaration is ignored
416-
(falls back to a rectangle).
417-
</div>
418-
419-
<div class="example">
420-
In this example, the first declaration creates tabs with vertical sides and rounded corners using 'border-radius',
421-
while the second example makes them trapezoid-shaped in UAs that support 'corners'.
422-
<pre>
423-
border-radius: 0.25em 0.25em 0 0;
424-
corners: angle 0.25em 0.25em 0 0 / 50% 50% 0 0;
425-
</pre>
426-
</div>
427-
428540
<h2 id="partial-borders">
429541
Partial borders</h2>
430542

0 commit comments

Comments
 (0)