<pre class='metadata'>
Title: CSS Borders and Box Decorations Module Level 4
Shortname: css-borders
Level: 4
Status: WD
Prepare for TR: yes
Date: 2025-12-16
Work Status: Exploring
Group: csswg
ED: https://drafts.csswg.org/css-borders-4/
TR: https://www.w3.org/TR/css-borders-4/
Editor: Elika J. Etemad / fantasai, Apple, http://fantasai.inkedblade.net/contact, w3cid 35400
Editor: Lea Verou, Invited Expert, http://lea.verou.me/about/, w3cid 52258
Editor: Sebastian Zartner, Invited Expert, sebastianzartner@gmail.com, w3cid 64937
Editor: Noam Rosenthal, Google, w3cid 121539
Former Editor: Bert Bos, W3C, bert@w3.org, w3cid 3343
Abstract: This module contains the features of CSS relating to the borders and decorations of boxes on the page.
Ignored Terms: border-*-*-radius, border-*-clip, box-shadow-*, corner-*-shape, corner-*-*-shape, corner-*-*, corner-*
Ignored Vars: block, inline, Li, Ltop, Lbottom, Lleft, Lright, spread, total width, W, Wside, Wleft, Wright, Wtop, Wbottom
Repository: w3c/csswg-drafts
WPT Path Prefix: css/css-borders/
WPT Display: open
</pre>

<pre class="link-defaults">
spec:css-overflow-3; type:value; for:overflow; text:visible
spec:css-shapes-2;
	type:function; text:path()
	type:property; text:shape-inside
spec:css-text-4; type:value; text:collapse
spec:dom; type: dfn; text: element;
spec:geometry-1; type: dfn;
	text: height dimension
	text: width dimension
	text: rectangle
	text: x coordinate; for: rectangle
	text: y coordinate; for: rectangle
spec:css-sizing-3; type:dfn;
	text:height
	text:size
	text:width
</pre>

<h2 id="intro">
Introduction</h2>

	The properties of this module deal with the decoration of the [=border area=].
	It also defines decorations that can be applied to the box.

<h3 id="placement">
Module Interactions</h3>

	This specification extends the parts related to borders and box decorations
	of CSS Backgrounds and Borders Module Level 3 [[CSS3BG]].

	It provides specifications for the added 'corner-*-shape' and 'border-shape' properties, as well as
	logical shorthands for 'border-*-radius', 'box-shadow-*' longhands,
	and partial borders via the 'border-limit' and 'border-*-clip' properties.

	All properties in this module apply to the ''::first-letter'' [=pseudo-element=].
	The <a href="#corners">border-radius properties</a> also apply
	to the ''::first-line'' [=pseudo-element=].
	The UA may (but is not required to)
	apply the 'border-image' or 'box-shadow' properties to ''::first-line''.
	The UA must not
	apply the <a href="#borders">border-color/style/width properties</a>
	to ''::first-line''.
	[[!CSS2]]

<h3 id="values">
Value Definitions</h3>

	This specification follows the <a href="https://www.w3.org/TR/CSS2/about.html#property-defs">CSS property definition conventions</a> from [[!CSS2]]
	using the <a href="https://www.w3.org/TR/css-values-3/#value-defs">value definition syntax</a> from [[!CSS-VALUES-3]].
	Value types not defined in this specification are defined in CSS Values &amp; Units [[!CSS-VALUES-3]].
	Combination with other CSS modules may expand the definitions of these value types.
	For example, combining with <a href="https://www.w3.org/TR/css-images/">CSS Images</a>
	allows for using CSS gradients as 'background-image' or 'border-image' values.
	[[CSS-IMAGES-3]]

	In addition to the property-specific values listed in their definitions,
	all properties defined in this specification
	also accept the <a>CSS-wide keywords</a> as their property value.
	For readability they have not been repeated explicitly.

<h2 id="borders">
Borders</h2>

	The [=border=] can either be a predefined style
	(solid line, double line, dotted line, pseudo-3D border, etc.)
	or it can be an image.
	In the former case, various properties define
	the style ('border-style'),
	color ('border-color'),
	and thickness ('border-width')
	of the border.

<wpt title="Tests for features Not yet incorporated from Backgrounds 3">
	border-image-gradient-zero-size-transform-crash.html
	border-image-width-interpolation-math-functions.html
</wpt>

<h3 id="border-color" oldids="the-border-color">
Line Colors: the 'border-color' properties</h3>

	<pre class="propdef">
	Name: border-top-color, border-right-color, border-bottom-color, border-left-color, border-block-start-color, border-block-end-color, border-inline-start-color, border-inline-end-color
	Value: <<color>> | <<image-1D>>
	Initial: currentcolor
	Applies to: all elements except [=ruby base containers=] and [=ruby annotation containers=]
	Inherited: no
	Logical property group: border-color
	Percentages: N/A
	Computed Value: the computed color and/or a one-dimensional image function
	Animation type: see prose
	</pre>

	These properties set the foreground <dfn noexport lt="border color" id="border-color-dfn">color</dfn>
	of the [=border=] specified by the 'border-style' properties.

	The stripes defined by <<image-1D>> follow the shape of the border
	on the side to which they apply,
	and are drawn in bands starting from the [=padding edge=] and progressing outwards.
	The border width at each point
	defines the |total width| of the stripes at that point.

	<div class="example">
		Using multiple colors for each side:

		<pre class=lang-css>
		.foo {
			border: 30px solid;
			border-color: stripes(<span class="swatch" tabIndex="0" style="--color: dodgerblue"></span>dodgerblue, <span class="swatch" tabIndex="0" style="--color: skyblue"></span>skyblue) stripes(<span class="swatch" tabIndex="0" style="--color: yellow"></span>yellow, <span class="swatch" tabIndex="0" style="--color: gold"></span>gold) stripes(<span class="swatch" tabIndex="0" style="--color: lightgreen"></span>lightgreen, <span class="swatch" tabIndex="0" style="--color: limegreen"></span>limegreen) stripes(<span class="swatch" tabIndex="0" style="--color: indianred"></span>indianred, <span class="swatch" tabIndex="0" style="--color: orange"></span>orange);
		}
		</pre>

		Sample rendering:

		<img src="images/multicolor-border.png" width="450" height="270"
		     alt="A box with a border that has four sides,
		          each side having two colors in stripes.
		          The top border is dodger blue and sky blue,
		          the right border is yellow and gold,
		          the bottom border is light green and lime green,
		          and the left border is indian red and orange."
		>

		The same border colors with ''border-style: dotted'':

		<img src="images/multicolor-border-dotted.png" width="450" height="270"
		     alt="A box with a border that has four sides,
		          each side having two colors in stripes.
		          The top border is dodger blue and sky blue,
		          the right border is yellow and gold,
		          the bottom border is light green and lime green,
		          and the left border is indian red and orange.
		          The border style is dotted, so the colors appear in dots along the border."
		>
	</div>

	<pre class="propdef shorthand">
		Name: border-color
		Value: [ <<color>> | <<image-1D>> ]{1,4}
	</pre>

	'border-color' is a [=shorthand property=] for the four physical 'border-*-color' properties.
	The four values set the top, right, bottom and left border, respectively.
	A missing left is the same as right,
	a missing bottom is the same as top,
	and a missing right is also the same as top.
	This is resolved individually for each list item.

	The [=flow-relative=] properties
	'border-block-start-color',
	'border-block-end-color',
	'border-inline-start-color',
	and 'border-inline-end-color'
	correspond to the [=physical=] properties
	'border-top-color',
	'border-bottom-color',
	'border-left-color',
	and 'border-right-color'.
	The mapping depends on the element’s 'writing-mode', 'direction', and 'text-orientation'.

	<pre class="propdef shorthand">
	Name: border-block-color, border-inline-color
	Value: <<'border-top-color'>>{1,2}
	</pre>

	These two <a>shorthand properties</a> set the
	'border-block-start-color' &amp; 'border-block-end-color'
	and
	'border-inline-start-color' &amp; 'border-inline-end-color',
	respectively.
	The first value represents the <a>start</a> side color,
	and the second value represents the <a>end</a> side color.
	If only one value is given,
	it applies to both the <a>start</a> and <a>end</a> sides.

	<wpt pathprefix="/css/css-backgrounds/">
		animations/border-color-interpolation.html
		border-image-displayed-with-transparent-border-color.html
		color-mix-currentcolor-border-repaint-parent.html
		color-mix-currentcolor-border-repaint.html
		currentcolor-border-repaint-parent.html
		inheritance.sub.html
		parsing/border-color-computed.html
		parsing/border-color-invalid.html
		parsing/border-color-shorthand.html
		parsing/border-color-valid.html
	</wpt>

<h3 id="border-style" oldids="the-border-style">
Line Patterns: the 'border-style' properties</h3>

	<pre class="propdef">
	Name: border-top-style, border-right-style, border-bottom-style, border-left-style, border-block-start-style, border-block-end-style, border-inline-start-style, border-inline-end-style
	Value: <<line-style>>
	Initial: none
	Applies to: all elements except [=ruby base containers=] and [=ruby annotation containers=]
	Inherited: no
	Logical property group: border-style
	Percentages: N/A
	Computed value: specified keyword
	Animation type: discrete
	</pre>

	These properties control whether a [=border=] appears,
	and if it does what <dfn noexport lt="border style" id="border-style-dfn">style</dfn> it's drawn in
	(if it is not overridden by a <a href="#border-images">border image</a>).

	The [=flow-relative=] properties
	'border-block-start-style',
	'border-block-end-style',
	'border-inline-start-style',
	and 'border-inline-end-style'
	correspond to the [=physical=] properties
	'border-top-style',
	'border-bottom-style',
	'border-left-style',
	and 'border-right-style'.
	The mapping depends on the element’s 'writing-mode', 'direction', and 'text-orientation'.

	<pre class="propdef shorthand">
	Name: border-block-style, border-inline-style
	Value: <<'border-top-style'>>{1,2}
	</pre>

	These two <a>shorthand properties</a> set the
	'border-block-start-style' &amp; 'border-block-end-style'
	and
	'border-inline-start-style' &amp; 'border-inline-end-style',
	respectively.
	The first value represents the <a>start</a> side style,
	and the second value represents the <a>end</a> side style.
	If only one value is given,
	it applies to both the <a>start</a> and <a>end</a> sides.

	<pre class="propdef shorthand">
	Name: border-style
	Value: <<'border-top-style'>>{1,4}
	</pre>

	'border-style' is a [=shorthand property=] for the four physical 'border-*-style' properties.
	The four values set the top, right, bottom and left border, respectively.
	A missing left is the same as right,
	a missing bottom is the same as top,
	and a missing right is also the same as top.
	This is resolved individually for each list item.

	The style is specified as a <<line-style>> keyword, where
	<pre class=prod><dfn><<line-style>></dfn> = none | hidden | dotted | dashed | solid | double | groove | ridge | inset | outset</pre>

	Values have the following meanings:

	<dl dfn-type=value dfn-for="<line-style>, border-style, border-top-style, border-left-style, border-bottom-style, border-right-style, border">
		<dt><dfn>none</dfn>
		<dd>
			No border.
			Color and width are ignored (i.e., the border has width 0).
			Note this means that the initial value of 'border-image-width'
			will also resolve to zero.

		<dt><dfn>hidden</dfn>
		<dd>
			Same as ''border-style/none'',
			but has different behavior in the border conflict resolution rules
			for border-collapsed tables [[!CSS2]].

		<dt><dfn>dotted</dfn>
		<dd>
			A series of round dots.

		<dt><dfn>dashed</dfn>
		<dd>
			A series of square-ended dashes.

		<dt><dfn>solid</dfn>
		<dd>
			A single line segment.

		<dt><dfn>double</dfn>
		<dd>
			Two parallel solid lines with some space between them.
			(The thickness of the lines is not specified,
				but the sum of the lines and the space must equal 'border-width'.)

		<dt><dfn>groove</dfn>
		<dd>
			Looks as if it were carved in the canvas.
			(This is typically achieved by creating a “shadow” from two colors
				that are slightly lighter and darker than the specified 'border-color'.)

		<dt><dfn>ridge</dfn>
		<dd>
			Looks as if it were coming out of the canvas.

		<dt><dfn>inset</dfn>
		<dd>
			Looks as if the content on the inside of the border
			is sunken into the canvas.
			Treated as ''border-style/ridge'' in the
			<a href="https://www.w3.org/TR/CSS2/tables.html#collapsing-borders">collapsing border model</a>. [[!CSS2]]

		<dt><dfn>outset</dfn>
		<dd>
			Looks as if the content on the inside of the border
			is raised out of the canvas.
			Treated as ''border-style/groove'' in the
			<a href="https://www.w3.org/TR/CSS2/tables.html#collapsing-borders">collapsing border model</a>. [[!CSS2]]
	</dl>

	Borders are drawn in front of the element’s background,
	but behind the element’s content (in case it overlaps).

	<figure>
		<img src="images/borderstyles.png" width="669" height="383"
		     alt=""
		>

		<figcaption>Example renderings of the predefined border styles.</figcaption>
	</figure>

	Note: Border colors close to black or white
	may need different color calculations than colors in between
	in order to create the required “3D” effect
	of ''border-style/groove'', ''border-style/ridge'', ''border-style/inset'', or ''border-style/outset''.

	Note: There is no control over
	the spacing of the dots and dashes,
	nor over the length of the dashes.
	Implementations are encouraged to choose a spacing
	that makes the corners symmetrical.

	<wpt pathprefix="/css/css-backgrounds/">
		inheritance.sub.html
		parsing/border-style-computed.html
		parsing/border-style-invalid.html
		parsing/border-style-shorthand.html
		parsing/border-style-valid.html
	</wpt>

<h3 id="border-width" oldids="the-border-width">
Line Thickness: the 'border-width' properties</h3>

	<pre class="propdef">
	Name: border-top-width, border-right-width, border-bottom-width, border-left-width, border-block-start-width, border-block-end-width, border-inline-start-width, border-inline-end-width
	Value: <<line-width>>
	Initial: medium
	Applies to: all elements except [=ruby base containers=] and [=ruby annotation containers=]
	Inherited: no
	Logical property group: border-width
	Percentages: N/A
	Computed value: absolute length, [=snapped as a border width=]
	Animation Type: by computed value
	</pre>

	These properties specify the thickness of the [=border=],
	i.e. the <dfn export id="border-width-dfn">border width</dfn>.
	Where

	<pre class=prod><dfn><<line-width>></dfn> = <<length [0,∞]>> | hairline | thin | medium | thick</pre>

	<p dfn-type=value dfn-for="<line-width>, border-width, border-top-width, border-left-width, border-bottom-width, border-right-width, border">
	Negative values are invalid.
	The <dfn>thin</dfn>, <dfn>medium</dfn>, and <dfn>thick</dfn> keywords
	are equivalent to ''1px'', ''3px'', and ''5px'', respectively.
	The <dfn>hairline</dfn> keyword is a UA-defined length,
	less than or equal to ''1px''
	and equal to an integer number of device pixels at the default page zoom,
	which represents a "just visible" line.
	(While it can be as large as ''1px'',
	on many devices it will be approximately ''0.3px'' to ''0.5px''.)

	The [=resolved value=] for the 'border-width' properties is the [=used value=].

	If the 'border-style' corresponding to a given 'border-width' is ''border-style/none'' or ''border-style/hidden'',
	then the [=used value|used=] width is 0.

	The [=flow-relative=] properties
	'border-block-start-width',
	'border-block-end-width',
	'border-inline-start-width',
	and 'border-inline-end-width'
	correspond to the [=physical=] properties
	'border-top-width',
	'border-bottom-width',
	'border-left-width',
	and 'border-right-width'.
	The mapping depends on the element’s 'writing-mode', 'direction', and 'text-orientation'.

	<pre class="propdef shorthand">
	Name: border-block-width, border-inline-width
	Value: <<'border-top-width'>>{1,2}
	</pre>

	These two <a>shorthand properties</a> set the
	'border-block-start-width' &amp; 'border-block-end-width'
	and
	'border-inline-start-width' &amp; 'border-inline-end-width',
	respectively.
	The first value represents the <a>start</a> side width,
	and the second value represents the <a>end</a> side width.
	If only one value is given,
	it applies to both the <a>start</a> and <a>end</a> sides.

	<pre class="propdef shorthand">
	Name: border-width
	Value: <<'border-top-width'>>{1,4}
	</pre>

	'border-width' is a [=shorthand property=] for the four physical 'border-*-width' properties.
	The four values set the top, right, bottom and left border, respectively.
	A missing left is the same as right,
	a missing bottom is the same as top,
	and a missing right is also the same as top.
	This is resolved individually for each list item.

	Note: Although the [=initial value|initial=] width is ''medium'',
	the [=initial value|initial=] style is ''border-style/none'';
	therefore the [=used value|used=] initial width is 0.

	<wpt pathprefix="/css/css-backgrounds/">
		animations/border-bottom-width-composition.html
		animations/border-image-width-composition.html
		animations/border-image-width-interpolation.html
		animations/border-left-width-composition.html
		animations/border-right-width-composition.html
		animations/border-top-width-composition.html
		animations/border-width-interpolation.html
		border-bottom-width-medium.html
		border-bottom-width-thick.html
		border-bottom-width-thin.html
		border-left-width-medium.html
		border-left-width-thick.html
		border-left-width-thin.html
		border-right-width-medium.html
		border-right-width-thick.html
		border-right-width-thin.html
		border-top-width-medium.html
		border-top-width-thick.html
		border-top-width-thin.html
		border-width-cssom.html
		border-width-pixel-snapping-001-a.html
		border-width-pixel-snapping-001-b.html
		border-width-small-values-001-a.html
		border-width-small-values-001-b.html
		border-width-small-values-001-c.html
		border-width-small-values-001-d.html
		border-width-small-values-001-e.html
		inheritance.sub.html
		parsing/border-width-computed.html
		parsing/border-width-invalid.html
		parsing/border-width-shorthand.html
		parsing/border-width-valid.html
	</wpt>
	<wpt>
		borders-on-sub-unit-sized-elements.html
		subpixel-borders-with-child-border-box-sizing.html
		subpixel-borders-with-child.html
	</wpt>

<h3 id="border-shorthands" oldids="the-border-shorthands">
Border Shorthand Properties</h3>

	<pre class="propdef shorthand">
	Name: border-top, border-right, border-bottom, border-left, border-block-start, border-block-end, border-inline-start, border-inline-end
	Value: <<line-width>> || <<line-style>> || <<color>>
	Initial: See individual properties
	Applies to: all elements except [=ruby base containers=] and [=ruby annotation containers=]
	Inherited: no
	Percentages: N/A
	Computed value: see individual properties
	Animation Type: see individual properties
	</pre>

	These [=shorthand properties=] set
	the 'border-width', 'border-color', and 'border-style'
	of one side of the [=borders=] of a box.
	Omitted values are set to their [=initial values=].

	The [=flow-relative=] properties
	'border-block-start',
	'border-block-end',
	'border-inline-start',
	and 'border-inline-end'
	correspond to the [=physical=] properties
	'border-top',
	'border-bottom',
	'border-left',
	and 'border-right'.
	The mapping depends on the element’s 'writing-mode', 'direction', and 'text-orientation'.

	<pre class="propdef shorthand">
	Name: border-block, border-inline
	Value: <<'border-block-start'>>
	</pre>

	These two <a>shorthand properties</a> set the
	'border-block-start' &amp; 'border-block-end'
	or
	'border-inline-start' &amp; 'border-inline-end',
	respectively,
	both to the same style.

	<!-- intentionally cannot set two sides independently;
		see discussion in https://github.com/w3c/csswg-drafts/issues/3519 -->

	<pre class="propdef shorthand">
	Name: border
	Value: <<line-width>> || <<line-style>> || <<color>>
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		parsing/border-invalid.html
		parsing/border-shorthand.html
		parsing/border-valid.html
	</wpt>

	The 'border' property is a [=shorthand property=] for setting
	the same 'border-width', 'border-color', and 'border-style'
	for all four borders of a box.
	Unlike the shorthand 'margin' and 'padding' properties,
	the 'border' property cannot set different values on the four borders.
	To do so, one or more of the other border properties must be used.

	The 'border' shorthand also resets 'border-image' to its initial value.
	It is therefore recommended that authors use the 'border' shorthand,
	rather than other shorthands or the individual properties,
	to override any border settings earlier in the cascade.
	This will ensure that 'border-image' has also been reset
	to allow the new styles to take effect.

	Note: The CSS Working Group intends for the 'border' shorthand
	to reset all border properties in future levels of CSS as well.
	For example, if a <css>border-characters</css> property
	is introduced in the future to allow glyphs as borders,
	it will also be reset by the 'border' shorthand.
	By using the 'border' shorthand to reset borders,
	authors can be guaranteed a “blank canvas”
	no matter what properties are introduced in the future.

	<div class="example">
		For example, the first rule below is equivalent to the set of five
		rules shown after it:

		<pre>
		p { border: solid red }
		p {
		  border-top: solid red;
		  border-right: solid red;
		  border-bottom: solid red;
		  border-left: solid red;
		  border-image: none;
		}
		</pre>
	</div>

	Since, to some extent, the properties have overlapping functionality,
	the order in which the rules are specified is important.

	<div class="example">
		Consider this example:
		<pre>
		blockquote {
		  border-color: red;
		  border-left: double;
		  color: black
		}
		</pre>

		In the above example,
		the color of the left border is black, while the other borders are red.
		This is due to 'border-left' setting the width, style, and color.
		Since the color value is not given by the 'border-left' property,
		it will be taken from the 'color' property.
		The fact that the 'color' property is set after the 'border-left' property
		is not relevant.
	</div>

<h2 id="corners">
Corners</h2>

	The [=padding edge=] (inner border) radius is
	the outer border radius minus the corresponding border thickness.
	In the case where this results in a negative value,
	the inner radius is zero.
	(In such cases the center of the border’s inner curve might not coincide
	with that of its outer curve.)
	Likewise the [=content edge=] radius is
	the [=padding edge=] radius minus the corresponding [=padding=],
	or if that is negative, zero.
	The border and padding thicknesses in the curved region
	are thus interpolated from the adjoining sides,
	and when two adjoining borders are of different thicknesses
	the corner will show a smooth transition
	between the thicker and thinner borders.

	All border styles (''border-style/solid'', ''border-style/dotted'',  ''border-style/inset'', etc.)
	follow the curve of the border.

	<figure>
		<img src="images/smooth-radius.png" width="407" height="176"
		     alt=""
		>

		<figcaption>
			The effect of a rounded corner when the two borders it connects
			are of unequal thickness (left)
			and the effect of a rounded corner on borders
			that are thicker than the radius of the corner (right).
		</figcaption>
	</figure>


	Note: If the center of a corner's outer curve
	is past an opposite [=padding edge=]
	(in the [=border area=] of a side opposite the corner),
	the inner curve will not be a full quarter ellipse.

	<figure>
		<table>
			<tr>
				<td>
					<pre>
					p { width: 70px; height: 70px; border: solid 30px;
					border-color: orange orange silver silver;
					border-top-right-radius: 100%; }
					</pre>
				<td>
					<img src="images/partial-curve.png" width="141" height="142"
					     alt="The curved corner is an arc from the top left corner
					          sweeping across the top right corner to the bottom right corner,
					          describing a quarter-ellipse;
					          but since the opposite sides have a border thickness
					          the padding edge curve starts inward from the outer arc's endpoints."
					>
		</table>
		<figcaption>
		Where the border-radius curve extends into the opposite sides' borders,
		the arc of the padding edge is less than 90&deg;.
		</figcaption>
	</figure>

	The [=margin edge=], being outside the [=border edge=],
	calculates its radius by <em>adding</em> the corresponding margin thickness
	to each border radius, with the corresponding [=outset-adjusted border radius=] applied.

<div algorithm="border-radius-outset">

	When expanding an [=edge=] that has a [=border radius=], e.g. for computing the [=margin edge=], 'box-shadow' spread, or 'overflow-clip-margin',
	the different [=border radius=] values are adjusted so that a small rounded corner with a big outset does not appear to be disproportionally round.

	This is done by computing the corresponding [=outset-adjusted border radius=].

	To compute the <dfn export>outset-adjusted border radius</dfn> given the 2-dimensional [=size=]'s |edge|, |radius|, and |outset|:
		1. Let |coverage| be <code>2 * min(|radius|'s [=width=] / |edge|'s [=width=], |radius|'s [=height=] / |edge|'s [=height=])</code>.
		1. Let |adustedRadiusWidth| be the [=adjusted radius dimension=] given |coverage|, |radius|'s [=width=], and |outset|'s [=width=].
		1. Let |adustedRadiusHeight| be the [=adjusted radius dimension=] given |coverage|, |radius|'s [=height=], and |outset|'s [=height=].
		1. Return (|adustedRadiusWidth|, |adustedRadiusHeight|).

	To compute the <dfn>adjusted radius dimension</dfn> given numbers |coverage|, |radius|, and |outset|:
		1. If |radius| is greater than |spread|, or if |coverage| is greater than 1, then return <code>|radius| + |outset|</code>.
		1. Let |ratio| be <code>|radius| / |outset|</code>.
		1. Return <code>|radius| + |outset| * (1 - (1 - |ratio|)<sup>3</sup> * (1 - |coverage|<sup>3</sup>))</code>.

		Note: this algorithm is designed to reduce the effect of the |outset| (or spread) on the shape of the corner.
		The |coverage| factor makes this reduction more pronounced for rectangular shapes (where the [=border radius=] is close to 0),
		and less pronounced for elliptical shapes (where the [=border radius=] is close to 50%).
</div>


<h3 id="corner-clipping">
Corner Clipping</h3>

	Although <a href="#border-image">border images</a>
	are not affected by 'border-radius',
	other effects that clip painting or event handling
	to the [=border edge|border=], [=padding edge|padding=], or [=content edge|content=] edge
	must clip to their respective curves.
	For example,
	backgrounds clip to the curve specified by 'background-clip',
	'overflow' values other than ''visible'' to the curved [=padding edge=]
	(when 'overflow' on both axes is not ''visible''),
	[=replaced element=] content to the curved [=content edge=],
	pointer events to the curved [=border edge=],
	etc.

	Note: As 'border-radius' reduces the interactive area of an element
	authors should make sure the remaining interactive area conforms
	to recommended minima for the platforms they target;
	in particular, conforming to recommended minimum touch target sizes
	may require larger widths and heights when 'border-radius' is used.

	<div class=example>
		This example adds appropriate padding,
		so that the contents do not overflow the corners.
		Note that there is no border,
		but the background will still have rounded corners.

		<pre>
		DIV {
		    background: black;
		    color: white;
		    border-radius: 1em;
		    padding: 1em }
		</pre>
	</div>

<h3 id="corner-transitions">
Color and Style Transitions</h3>

	Color and style transitions must be contained
	within the segment of the border that intersects
	the smallest rectangle that contains both border radii
	as well as the center of the inner curve
	(which may be a point representing the corner of the padding edge,
	if the border radii are smaller than the [=border width=]).

	If one of these borders is zero-width,
	then the other border takes up the entire transitional area.
	Otherwise,
	the center of color and style transitions between adjoining borders
	is a point along the curve that is a continuous monotonic function
	of the ratio of the border widths.
	However it is not defined what these transitions look like
	or what function maps from this ratio to a point on the curve.

	<figure>
		<img src="images/transition-region.png" width="600" height="178"
		     alt=""
		>

		<figcaption>
			Given these corner shapes, color and style transitions
			must be contained within the green region.
			In case D the rectangle defined by the border radii
			does not include the center of the inner curve (which is a sharp corner),
			so the transition region is expanded to include that corner.
			Transitions may take up the entire transition region,
			but are not required to:
			For example, a gradient color transition between two solid border styles
			might take up only the region bounded by
			the tips of the outer radii and the tips of the inner radii
			(represented in case D by the dark green region).
		</figcaption>
	</figure>

	<wpt>
		border-radius-currentcolor.html
	</wpt>

<h3 id="corner-overlap">
Overlapping Curves</h3>

	Corner curves must not overlap:
	When the sum of any two adjacent border radii
	exceeds the size of the border box,
	UAs must proportionally reduce
	the used values of all border radii
	until none of them overlap.
	The algorithm for reducing radii is as follows:

	Let <var>f</var> = min(<var>L<sub>i</sub></var>/<var>S<sub>i</sub></var>),
	where <var>i</var> ∈ {top, right, bottom, left},
	<var>S<sub>i</sub></var> is the sum of the two corresponding radii
	of the corners on side <var>i</var>,
	and <var>L<sub>top</sub></var> = <var>L<sub>bottom</sub></var> = the width of the box,
	and <var>L<sub>left</sub></var> = <var>L<sub>right</sub></var> = the height of the box.
	If <var>f</var> &lt; 1, then all corner radii are reduced
	by multiplying them by <var>f</var>.

	Note: This formula ensures that quarter circles remain quarter circles
	and large radii remain larger than smaller ones,
	but it may reduce corners that were already small enough,
	which may make borders of nearby elements that should look the same
	look different.

	If the curve interferes with UI elements such as scrollbars,
	the UA may further reduce the used value of the affected border radii
	(and only the affected border radii)
	as much as necessary, but no more.

	<div class=example>
		For example, the borders A of the <a href="#reduced-radius">figure below</a>
		might be the result of

		<pre>
		box-sizing: border-box;
		width: 6em;
		height: 2.5em;
		border-radius: 0.5em 2em 0.5em 2em
		</pre>

		The height (2.5em) is enough for the specified radii (0.5em plus 2.0em).
		However, if the height is only 2em,

		<pre>
		box-sizing: border-box;
		width: 6em;
		height: 2em;
		border-radius: 0.5em 2em 0.5em 2em
		</pre>

		all corners need to be reduced by a factor 0.8 to make them fit.
		The used border radii thus are
		0.4em (instead of 0.5em) and 1.6em (instead of 2em).
		See borders B in the figure.

		<figure id=reduced-radius>
			<img src="images/corner-large-mix.png" width="539" height="168"
			     alt="rectangle with two tiny rounded corners and two very large ones, on opposite corners"
			>

			<figcaption>
				These rounded corner might be the result of
				''width: 6em; height: 2.5em; border-radius: 0.5em 2em 0.5em 2em''
				for A; and ditto but with ''height: 2em'' for B.
			</figcaption>
		</figure>
	</div>

<h3 id="border-radius-tables">
Effect on Tables</h3>

	The 'border-radius' properties do apply to
	''display/table'', ''inline-table'', and ''table-cell'' boxes
	in separated borders mode (''border-collapse: separate'').
	When 'border-collapse' is ''border-collapse/collapse'', they have no effect.

	<wpt pathprefix="/css/css-backgrounds/">
		ttwf-reftest-borderRadius.html
	</wpt>

<h3 id="border-radius" oldids="the-border-radius">
Corner Sizing: the 'border-*-*-radius' properties</h3>

	<pre class="propdef">
	Name: border-top-left-radius, border-top-right-radius, border-bottom-right-radius, border-bottom-left-radius, border-start-start-radius, border-start-end-radius, border-end-start-radius, border-end-end-radius
	Value: <<border-radius>>
	Initial: 0
	Applies to: all elements (but see prose)
	Inherited: no
	Logical property group: border-radius
	Percentages: Refer to corresponding dimension of the <a>border box</a>.
	Computed value: pair of computed <<length-percentage>> values
	Animation Type: by computed value
	</pre>

	The radius is specified as a <<border-radius>> value, where

	<pre class="prod">
	<dfn><<border-radius>></dfn> = <<slash-separated-border-radius-syntax>> | <<legacy-border-radius-syntax>>
	<dfn><<slash-separated-border-radius-syntax>></dfn> = <<length-percentage [0,∞]>> [ / <<length-percentage [0,∞]>> ]?
	<dfn><<legacy-border-radius-syntax>></dfn> = <<length-percentage [0,∞]>>{1,2}
	</pre>

	The two <<length-percentage>> values of the 'border-*-radius' properties
	define the <dfn id="border-radii" lt="border radius">radii</dfn> of
	a quarter ellipse that defines the shape of the corner
	of the outer [=border edge=] (see the diagram below).
	The first value is the horizontal radius,
	the second the vertical radius.
	If the second value is omitted it is copied from the first.
	If either length is zero, the corner is square, not rounded.
	Percentages for the horizontal radius refer to the width of the [=border box=],
	whereas percentages for the vertical radius refer to the height of the [=border box=].
	Negative values are invalid.

	Note: Authors <em>should</em> use the slash syntax, which is preferred for new content,
	but the legacy syntax (two values separated by whitespace)
	is supported for backwards compatibility.

	<figure>
		<img src="images/corner.png" width="289" height="179"
		     alt="Diagram of the inscribed ellipse"
		>

		<figcaption>
			The two values of ''border-top-left-radius: 55pt 25pt''
			define the curvature of the corner.
		</figcaption>
	</figure>

	<div class=example>
		This example draws ovals of 15em wide and 10em high:

		<pre>
		DIV.standout {
		    width: 13em;
		    height: 8em;
		    border: solid black 1em;
		    border-radius: 7.5em 5em }
		</pre>
	</div>

	The [=flow-relative=] properties
	'border-start-start-radius',
	'border-start-end-radius',
	'border-end-start-radius',
	and 'border-end-end-radius'
	correspond to the [=physical=] properties
	'border-top-left-radius',
	'border-bottom-left-radius',
	'border-top-right-radius',
	and 'border-bottom-right-radius'.
	The mapping depends on the element’s 'writing-mode', 'direction', and 'text-orientation',
	with the first start/end giving the block axis side,
	and the second the inline-axis side
	(i.e. patterned as 'border-<var>block</var>-<var>inline</var>-radius').

<h3 id="corner-sizing">
Corner Sizing Shorthands: the 'border-radius' and 'border-*-radius' shorthand properties</h3>

<h4 id="corner-sizing-side-shorthands">
Sizing The Corners Of One Side:
The 'border-top-radius', 'border-right-radius',
'border-bottom-radius', 'border-left-radius',
'border-block-start-radius', 'border-block-end-radius',
'border-inline-start-radius', 'border-inline-end-radius' shorthands</h4>

	<pre class="propdef shorthand">
		Name: border-top-radius, border-right-radius, border-bottom-radius, border-left-radius,
			border-block-start-radius, border-block-end-radius, border-inline-start-radius, border-inline-end-radius
		Value: <<length-percentage [0,∞]>>{1,2} [ / <<length-percentage [0,∞]>>{1,2} ]?
		Initial: 0
		Applies to: all elements (but see prose)
		Inherited: no
		Percentages: Refer to corresponding dimension of the <a>border box</a>.
		Computed value: see individual properties
		Animation type: see individual properties
	</pre>

	<p>The 'border-*-radius' shorthands set the two 'border-*-*-radius'
	longhand properties of the related side. If values are given before
	and after the slash, then the values before the slash set the
	horizontal radius and the values after the slash set the vertical radius.
	If there is no slash, then the values set both radii equally.
	The two values for the radii are given in the order
	top-left, top-right for 'border-top-radius',
	top-right, bottom-right for 'border-right-radius',
	bottom-left, bottom-right for 'border-bottom-radius',
	top-left, bottom-left for 'border-left-radius',
	start-start, start-end for 'border-block-start-radius',
	end-start, end-end for 'border-block-end-radius'
	start-start, end-start for 'border-inline-start-radius',
	and start-end, end-end for 'border-inline-end-radius'.
	If the second value is omitted it is copied from the first.

<wpt>
	border-radius-greater-than-width.html
	tentative/border-radius-side-shorthands/border-radius-side-shorthands-001.html
	tentative/border-radius-side-shorthands/border-radius-side-shorthands-002.html
	tentative/parsing/border-block-end-radius-computed.html
	tentative/parsing/border-block-end-radius-invalid.html
	tentative/parsing/border-block-end-radius-valid.html
	tentative/parsing/border-block-start-radius-computed.html
	tentative/parsing/border-block-start-radius-invalid.html
	tentative/parsing/border-block-start-radius-valid.html
	tentative/parsing/border-bottom-radius-computed.html
	tentative/parsing/border-bottom-radius-invalid.html
	tentative/parsing/border-bottom-radius-valid.html
	tentative/parsing/border-inline-end-radius-computed.html
	tentative/parsing/border-inline-end-radius-invalid.html
	tentative/parsing/border-inline-end-radius-valid.html
	tentative/parsing/border-inline-start-radius-computed.html
	tentative/parsing/border-inline-start-radius-invalid.html
	tentative/parsing/border-inline-start-radius-valid.html
	tentative/parsing/border-left-radius-computed.html
	tentative/parsing/border-left-radius-invalid.html
	tentative/parsing/border-left-radius-valid.html
	tentative/parsing/border-right-radius-computed.html
	tentative/parsing/border-right-radius-invalid.html
	tentative/parsing/border-right-radius-valid.html
	tentative/parsing/border-top-radius-computed.html
	tentative/parsing/border-top-radius-invalid.html
	tentative/parsing/border-top-radius-valid.html
</wpt>
<wpt pathprefix="/css/css-backgrounds/">
	animations/border-bottom-left-radius-composition.html
	animations/border-bottom-right-radius-composition.html
	animations/border-radius-interpolation.html
	animations/border-top-left-radius-composition.html
	animations/border-top-right-radius-composition.html
	border-bottom-left-radius-001.xht
	border-bottom-left-radius-004.xht
	border-bottom-left-radius-005.xht
	border-bottom-left-radius-010.xht
	border-bottom-left-radius-011.xht
	border-bottom-left-radius-014.xht
	border-bottom-right-radius-001.xht
	border-bottom-right-radius-004.xht
	border-bottom-right-radius-005.xht
	border-bottom-right-radius-010.xht
	border-bottom-right-radius-011.xht
	border-bottom-right-radius-014.xht
	border-radius-001.xht
	border-radius-002.xht
	border-radius-003.xht
	border-radius-004.xht
	border-radius-005.xht
	border-radius-006.xht
	border-radius-007.xht
	border-radius-008.xht
	border-radius-009.xht
	border-radius-010.xht
	border-radius-011.xht
	border-radius-012.html
	border-radius-013.html
	border-radius-clip-001.html
	border-radius-clip-002.htm
	border-radius-clipping-002.html
	border-radius-clipping-with-transform-001.html
	border-radius-css-text.html
	border-radius-dynamic-from-no-radius.html
	border-radius-horizontal-value-is-zero.html
	border-radius-shorthand-002.html
	border-top-left-radius-001.xht
	border-top-left-radius-004.xht
	border-top-left-radius-005.xht
	border-top-left-radius-010.xht
	border-top-left-radius-011.xht
	border-top-left-radius-014.xht
	border-top-right-radius-001.xht
	border-top-right-radius-004.xht
	border-top-right-radius-005.xht
	border-top-right-radius-010.xht
	border-top-right-radius-011.xht
	border-top-right-radius-014.xht
	box-shadow-border-radius-001.html
	css-border-radius-001.html
	inheritance.sub.html
	inner-border-non-renderable.html
	parsing/border-radius-computed.html
	parsing/border-radius-invalid.html
	parsing/border-radius-valid.html
	parsing/webkit-border-radius-valid.html
</wpt>

<h4 id="corner-sizing-shorthand">
Sizing All Corners At Once:
The 'border-radius' shorthand</h4>

	<pre class="propdef shorthand">
		Name: border-radius
		Value: <<length-percentage [0,∞]>>{1,4} [ / <<length-percentage [0,∞]>>{1,4} ]?
	</pre>

	The 'border-radius' shorthand sets all four 'border-*-radius' properties.
	If values are given before and after the slash,
	then the values before the slash set the horizontal radii
	and the values after the slash set the vertical radii.
	If there is no slash, then the values set the radii in both axes equally.
	The four values for each radii are given in the order
	top-left, top-right, bottom-right, bottom-left.
	If bottom-left is omitted it is the same as top-right.
	If bottom-right is omitted it is the same as top-left.
	If top-right is omitted it is the same as top-left.

	<div class="example">
		<pre>
		border-radius: 4em;
		</pre>
		is equivalent to
		<pre>
		border-top-left-radius:     4em;
		border-top-right-radius:    4em;
		border-bottom-right-radius: 4em;
		border-bottom-left-radius:  4em;
		</pre>
		and
		<pre>
		border-radius: 2em 1em 4em / 0.5em 3em;
		</pre>
		is equivalent to
		<pre>
		border-top-left-radius:     2em 0.5em;
		border-top-right-radius:    1em 3em;
		border-bottom-right-radius: 4em 0.5em;
		border-bottom-left-radius:  1em 3em;
		</pre>
	</div>

<h3 id="corner-shaping">
Corner Shaping: the 'corner-*-shape' properties</h3>

	By default, non-zero 'border-radius' values
	define a quarter-ellipse <dfn export>corner shape</dfn>
	that rounds the affected corners,
	filling the <dfn export>corner area</dfn>
	defined by the 'border-radius' for that corner.
	However in some cases, other [=corner shapes=] are desired.
	The 'corner-*-shape' properties (and their shorthands)
	specify exactly what [=corner shapes=] a box will use
	for the region defined by its 'border-*-radius' values.

	The different [=corner shapes=] can all be expressed
	as different parameters to a <em>superellipse</em>.
	A superellipse is a generalization of an ellipse,
	and based on its `k` parameter can express all the shapes between
	a square, an ellipse, and a notch.

	<details class=note>
		<summary>How does a superellipse work?</summary>

		A unit circle is defined by the equation:

		<figure>
			<math display=block>
				<mrow>
					<msup>
						<mi>x</mi>
						<mn>2</mn>
					</msup>
					<mo>+</mo>
					<msup>
						<mi>y</mi>
						<mn>2</mn>
					</msup>
					<mo>=</mo>
					<mn>1</mn>
				</mrow>
			</math>
		</figure>

		The circle is made from all points (x,y) that satisfy the equation.
		A given ellipse can then be produced by scaling this shape
		in the X and/or Y axis.

		The unit superellipse equation just changes the <sup>2</sup> exponent
		into a variable.
		For this spec's purposes, we'll write it as 2<sup>K</sup>:

		<figure>
			<math display=block>
				<mrow>
					<msup>
						<mi>x</mi>
						<msup>
							<mn>2</mn>
							<mi>K</mi>
						</msup>
					</msup>
					<mo>+</mo>
					<msup>
						<mi>y</mi>
						<msup>
							<mn>2</mn>
							<mi>K</mi>
						</msup>
					</msup>
					<mo>=</mo>
					<mn>1</mn>
				</mrow>
			</math>
		</figure>

		The |K| in this equation is the ''superellipse()'' argument.

		|K| can be any value;
		setting |K| to 1 gives the standard circle/ellipse equation,
		but other values define the entire family of superellipse curves:

		* Values larger than 1 make it more "square":
			the traditional "squircle" uses a |K| of 2,
			and a |K| of infinity is a perfect square.
			(A |K| of only 10 is already nearly indistinguishable from a square;
			it scales very quickly.)

		* Values between 0 and 1 make it "flatter";
			when |K| is 0 it's a diamond with perfectly flat sides.

		* Negative values define concave curves,
			roughly opposite of what you get with positive values:
			a |K| of -1 gives a nearly elliptical "scoop"
			that's roughly the opposite of a |K| of 1,
			a |K| of -2 gives a "squircle" scoop,
			a |K| of negative infinity gives a square scoop,
			etc.

		(Note that most literature on superellipses
		will write the equation with a simpler <math display=inline><msup><mi>x</mi><mi>K</mi></msup></math> exponent.
		The <math display=inline><msup><mi>x</mi><msup><mn>2</mn><mi>K</mi></msup></msup></math> form
		was chosen here
		to make the argument ranges easier to reason about:
		all possible values are valid,
		the symmetrical shapes are just positive/negative,
		the "middle" bevel is 0,
		etc.)
	</details>

	To allow full expression as well as interpolation,
	the 'corner-shape' properties can provide the superellipse parameter directly
	using the ''superellipse()'' function,
	or use one of the supplied keywords which represent commonly used parameters.
	See the <<corner-shape-value>> definition for details.

	<wpt>
		corner-shape/corner-shape-backdrop-filter.html
		corner-shape/corner-shape-backdrop-filter-overflow.html
		corner-shape/corner-shape-bevel-overflow-composite.html
		corner-shape/corner-shape-bevel-overflow.html
		corner-shape/corner-shape-computed.html
		corner-shape/corner-shape-fill.html
		corner-shape/corner-shape-hittest.html
		corner-shape/corner-shape-iframe-border.html
		corner-shape/corner-shape-img-border.html
		corner-shape/corner-shape-img.html
		corner-shape/corner-shape-inset-shadow.html
		corner-shape/corner-shape-invalid.html
		corner-shape/corner-shape-notch.html
		corner-shape/corner-shape-outside-left.html
		corner-shape/corner-shape-outside-right.html
		corner-shape/corner-shape-overflow-clip-margin.html
		corner-shape/corner-shape-square.html
		corner-shape/corner-shape-svg-border.html
		corner-shape/corner-shape-valid.html
		corner-shape/corner-shape-video-border.html
		corner-shape/corner-shape-noop-keyframe.html
		corner-shape/corner-shape-zoom-overlap-extreme-values-crash.html
		corner-shape/render-corner-shape.html
	</wpt>

	<pre class="propdef">
		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
		Value: <<corner-shape-value>>
		Initial: round
		Applies to: all elements where 'border-radius' can apply
		Inherited: no
		Logical property group: corner-shape
		Computed value: the corresponding ''superellipse()'' value
		Animation Type: see [=superellipse interpolation=]
	</pre>

	The 'corner-*-*-shape' longhand properties
	set the corner shape for the given corner.

	The [=flow-relative=] longhands
	('corner-start-start-shape', etc.)
	correspond to the [=physical=] longhands
	('corner-top-left-shape', etc.)
	depending on the element’s 'writing-mode', 'direction', and 'text-orientation'.
	The first <css>start</css>/<css>end</css> gives the block axis side,
	and the second the inline-axis side
	(i.e. patterned as <css>corner-<var ignore>block</var>-<var ignore>inline</var>-shape</css>).

	<pre class=prod>
		<dfn><<corner-shape-value>></dfn> = <l>''corner-shape/round''</l> | <l>''corner-shape/scoop''</l> | <l>''corner-shape/bevel''</l> | <l>''corner-shape/notch''</l> | <l>''corner-shape/square''</l> | <l>''corner-shape/squircle''</l> |
		                       <<superellipse()>>
		<dfn>superellipse()</dfn> = superellipse(<<number>> | infinity | -infinity)
	</pre>

	<dl dfn-type="value" dfn-for="<corner-shape-value>, corner-shape">
		<dt><dfn>round</dfn>
		<dd>The [=corner shape=] is a quarter of a convex ellipse.
			Equivalent to ''superellipse(1)''.

			Note: This is the initial value of 'corner-shape' properties,
			as it was the behavior of 'border-radius'
			before 'corner-shape' existed.

		<dt><dfn>squircle</dfn>
		<dd>The [=corner shape=] is a quarter of a "squircle",
			a convex curve between ''corner-shape/round'' and ''corner-shape/square''.
			Equivalent to ''superellipse(2)''.

		<dt><dfn>square</dfn>
		<dd>The [=corner shape=] is a convex 90deg angle.
			Equivalent to ''superellipse(infinity)''.

			Note: This looks identical to the "normal" square corner
			you get from ''border-radius: 0'',
			but it can smoothly animate with the other 'corner-shape' values.

		<dt><dfn>bevel</dfn>
		<dd>The [=corner shape=] is a straight diagonal line,
			neither convex nor concave.
			Equivalent to ''superellipse(0)''.

		<dt><dfn>scoop</dfn>
		<dd>The [=corner shape=] is a concave quarter-ellipse.
			Equivalent to ''superellipse(-1)''.

		<dt><dfn>notch</dfn>
		<dd>The [=corner shape=] is a concave 90deg angle.
			Equivalent to ''superellipse(-infinity)''.

		<dt><dfn>superellipse(K)</dfn>
		<dd>The [=corner shape=] is a quarter of a superellipse.
			The argument |K| is the <dfn dfn for>superellipse parameter</dfn>,
			and it defines a superellipse
			using an exponent of 2<sup>K</sup>.

			See the note in [[#corner-shaping]] for an explanation
			of the mathematical definition of a superellipse,
			and what various K values mean.
			See [[#corner-shape-rendering]] for precise details
			of how the superellipse is computed and rendered.
	</dl>

	<div class=example>

		<figure>
			<img src="images/superellipse-param.svg" width="480" height="360"
			     alt=""
			>

			<figcaption>
				Different ''superellipse()'' values for the top right corner: infinity, 1, 0, -1, and -infinity.
			</figcaption>
		</figure>
	</div>

	Note: If 'border-radius' is not specified
	(or is set to 0),
	the [=corner area=] is zero-sized as well,
	and 'corner-shape' won't have any effect.

	'corner-*-shape' does not alter the [=overflow=] rules for 'border-*-radius',
	except insofar as it shapes the corners differently;
	elements are still clipped by the shaped border as normal.

	The curve specified by 'corner-*-shape'
	defines the <em>outer</em> edge of the border.
	The inner edge of the border follows the curve of the outer edge
	(in a way that's not necessarily expressible as a superellipse curve),
	with a nearly consistent distance from the outer edge throughout,
	(or a linearly increasing distance
	if the 'border-width' of the two border edges meeting at the the corner are not uniform).

	'corner-*-shape' also affects the rendering of 'box-shadow',
	and how the [=overflow clip edge=] is shaped when it's extended from the box,
	but these do not directly follow the 'corner-*-shape' path
	like the inner border edge does.
	Instead, it scales the 'corner-shape' path in an axis-aligned manner.

<h3 id="corner-shaping-shorthands">
Corner Shaping Shorthands: the 'corner-shape' and 'corner-*-shape' shorthand properties</h3>

<h4 id="corner-shaping-side-shorthands">
Shaping The Corners Of One Side:
The 'corner-*-shape' shorthands:</h4>

	<pre class="propdef shorthand">
	Name: corner-top-shape, corner-right-shape, corner-bottom-shape, corner-left-shape,
		corner-block-start-shape, corner-block-end-shape, corner-inline-start-shape, corner-inline-end-shape
	Value: <<'corner-top-left-shape'>>{1,2}
	</pre>

	The 'corner-*-shape' shorthands set the two 'corner-*-*-shape'
	properties of the related side.
	If only one value is given,
	the second value defaults to the same value.

	For the physical shorthands ('corner-top-shape', etc.),
	the values are either in left/right order, or top/bottom order,
	whichever axis is meaningful for the property.
	That is, ''corner-top-shape: round square''
	sets ''corner-top-left-shape: round; corner-top-right-shape: square;''.

	For the logical shorthands ('corner-block-start-shape', etc.),
	the values are always in start/end order in the other axis.
	That is, ''corner-block-start-shape: round square''
	sets ''corner-start-start-shape: round; corner-start-end-shape: square;''.

<h4 id="corner-shaping-shorthand">
Shaping All Corners At Once:
The 'corner-shape' shorthand</h4>

	<pre class="propdef shorthand">
		Name: corner-shape
		Value: <<'corner-top-left-shape'>>{1,4}
		Initial: round
		Applies to: all elements where 'border-radius' can apply
		Inherited: no
		Animation type: see individual properties
	</pre>

	The 'corner-shape' property specifies the shape of the box's corners,
	within the region specified by 'border-radius'.
	The four values set the top, right, bottom and left shape, respectively.
	A missing left is the same as right,
	a missing bottom is the same as top,
	and a missing right is also the same as top.

<h3 id="corner-shorthands">
Corner Sizing & Shaping Shorthands: the 'corner' and 'corner-*' shorthand properties</h3>

<h4 id="single-corner-shorthands">
Sizing & shaping a corner:
The 'corner-top-left', 'corner-top-right',
'corner-bottom-right', 'corner-bottom-left',
'corner-start-start', 'corner-start-end',
'corner-end-start', 'corner-end-end' shorthands</h4>

	<pre class="propdef">
		Name: corner-top-left, corner-top-right, corner-bottom-left, corner-bottom-right,
			corner-start-start, corner-start-end, corner-end-start, corner-end-end
		Value: <<'border-top-left-radius'>> || <<'corner-top-left-shape'>>
		Initial: 0
		Applies to: all elements (but see prose)
		Inherited: no
		Percentages: Refer to corresponding dimension of the <a>border box</a>.
		Computed value: see individual properties
		Animation type: see individual properties
	</pre>

	The 'corner-*-*' shorthands set the two 'corner-*-*-shape' and 'border-*-*-radius'
	longhand properties of the related side.
	See the corresponding 'corner-*-*-shape' and 'border-*-*-radius' properties for further details.


<h4 id="corner-side-shorthands">
Sizing & shaping rhe Corners Of One Side:
The 'corner-top', 'corner-right',
'corner-bottom', 'corner-left',
'corner-block-start', 'corner-block-end',
'corner-inline-start', 'corner-inline-end' shorthands</h4>

	<pre class="propdef shorthand">
		Name: corner-top, corner-right, corner-bottom, corner-left,
			corner-block-start, corner-block-end, corner-inline-start, corner-inline-end
		Value: <<'border-top-radius'>> || <<'corner-top-shape'>>
		Initial: 0
		Applies to: all elements (but see prose)
		Inherited: no
		Percentages: Refer to corresponding dimension of the <a>border box</a>.
		Computed value: see individual properties
		Animation type: see individual properties
	</pre>

	The 'corner-*' shorthands set the two 'corner-*-shape' longhand properties and two 'border-*-radius'
	longhand properties of the related side.
	See the corresponding 'corner-*-shape' and 'border-*-radius' properties for further details.

<h4 id="corner-shorthand">
Sizing & Shaping All Corners At Once:
The 'corner' shorthand</h4>

	<pre class="propdef">
		Name: corner
		Value: <<'border-radius'>> || <<'corner-shape'>>
		Initial: 0
		Applies to: all elements (but see prose)
		Inherited: no
		Percentages: Refer to corresponding dimension of the <a>border box</a>.
		Computed value: see individual properties
		Animation type: see individual properties
	</pre>

	The 'corner' shorthand sets the 'corner-*-shape' and 'border-*-radius' longhands all together.

<h4 id=corner-shape-rendering>
Rendering 'corner-shape'</h4>

When rendering elements with shaped corners, the element's [=border contour path=] needs to be offset,
based on [=border=], [=outline=], 'box-shadow', 'overflow-clip-margin' and more.

When rendering borders or outlines, the offset is aligned to the curve of the element's shape.
When rendering 'box-shadow' or offsetting for 'overflow-clip-margin', the offset is also aligned to the same curve in the other direction, and the curve continues to the outer edge.

An [=/element=] |element|'s <dfn>outer contour</dfn> is the [=border contour path=] given |element| and |element|'s [=border edge=].

An [=/element=] |element|'s <dfn>inner contour</dfn> is the [=border contour path=] given |element| and |element|'s [=border width=].

An [=/element=]'s [=border=] is rendered in the area between its [=outer contour=] and its [=inner contour=].

An [=/element=]'s [=outline=] follows the [=outer contour=] with the [=used value|used=] 'outline-width' and 'outline-offset'.
The precise way in which it is rendered is implementation-defined.

An [=/element=]'s [=overflow=] area is shaped by its [=inner contour=].
An [=/element=]'s [=overflow clip edge=] is shaped by the [=border contour path=] given |element|, and an [=uniform inset from an outset=] given |element|'s [=used value|used=] 'overflow-clip-margin'.

Each shadow of [=/element=]'s 'box-shadow' is shaped by the [=border contour path=] given |element|, and an [=uniform inset from an outset=] given the shadow's [=used value|used=] 'box-shadow-spread'.

An <dfn>uniform inset from an outset</dfn> given a number |outset| is an [=edge=] whose value is <code>-|outset|</code> in all directions.

<h5 id=vector-math-helpers>Vector Math Helpers</h5>

A <dfn>two-dimensional vector</dfn> is a pair of numbers (x, y).
<div algorithm="extend-point">
A <dfn>point extended by vectors</dfn> given a {{DOMPointReadOnly}} |p| and a [=/list=] of [=two-dimensional vector=]s |vectors|:
	1. Let |x| be |p|'s {{DOMPointReadOnly/x}}.
	1. Let |y| be |p|'s {{DOMPointReadOnly/y}}.
	1. [=list/For each=] |v| in |vectors|:
		1. Increment |x| by |v|[0];
		1. Increment |y| by |v|[1];
	1. Return a new {{DOMPointReadOnly}} whose {{DOMPointReadOnly/x}} is |x| and whose {{DOMPointReadOnly/y}} is |y|.
</div>

To <dfn for="two-dimensional vector">scale</dfn> a [=two-dimensional vector=] |v| by a number |factor|, return <code>(|v|[0] ⋅ |factor|, |v|[1] ⋅ |factor|)</code>.

<div algorithm="normalize-vector">
To <dfn for="two-dimensional vector">normalize</dfn> a [=two-dimensional vector=] |v|:
	1. Let |l| be <code>hypot(|v|[0], |v|[1])</code>.
	1. If |l| is 0, return |v|.
	1. Return <code>(|v|[0] / |l|, |v|[1] / |l|)</code>.
</div>

The <dfn for="two-dimensional vector">perpendicular</dfn> of a [=two-dimensional vector=] |v| is <code>(-|v|[1], |v|[0])</code>.

The <dfn>vector between two points</dfn>, given {{DOMPoint}}s |a| and |b|, is <code>(|b|'s {{DOMPointReadOnly/x}} - |a|'s {{DOMPointReadOnly/x}}, |b|'s {{DOMPointReadOnly/y}} - |a|'s {{DOMPointReadOnly/y}})</code>. 

<h5 id=contour-path>Computing a contoured path</h5>

This algorithm describes how to compute a path with shaped corners (a path that is either inset or outset from the original).
To avoid the complexities of defining how superellipses intersect, the algorithm simplifies the process by specifying that each corner is "clipped out" of the path.
The specific implementation details of this clipping operation are left to implementations.

<div algorithm="border-aligned-contour-path">
To compute an [=/element=] |element|'s <dfn>border contour path</dfn> given numbers |topInset|, |rightInset|, |bottomInset|, |leftInset|:
	1. Let |borderRect| be |element|'s [=border box=].
	1. Let |unshapedTargetRect| be |borderRect|, inset by |topInset|, |rightInset|, |bottomInset|, |leftInset|.
		
			Note: If this is a shadow or 'overflow-clip-margin', the insets would have negative values and |unshapedTargetRect| would become an outset of |borderRect|.

	1. Let |path| be a path that contains |unshapedTargetRect|.

	1. Let |scaleFactor| be the [=opposite corner scale factor=] given |element|.

	1. Let |adjustedRadius| be the following steps given a property |P|, and numbers |insetX| and |insetY|:
		1. Let |radius| be |element|'s [=used value=] of |P|.
		1. If |insetX| and |insetY| are zero, return |radius|.
		1. If |insetX| or |insetY| are positive, then return <code>(|radius|'s [=width=] ⋅ |scaleFactor|, |radius|'s [=height=] ⋅ |scaleFactor|)</code>.
		1. Let |adjustedRadiusInOutsetCoordinates| be the [=outset-adjusted border radius=] given |borderRect|'s size, |radius|, and <code>(-|insetX|, -|insetY|)</code>.
		1. Return <code>(|adjustedRadiusInOutsetCoordinates|'s [=width=] - |insetX|, |adjustedRadiusInOutsetCoordinates|'s [=height=] - |insetY|)</code>.

	1. Let |adjustedTopRightRadius| be the |adjustedRadius| given 'border-top-right-radius', |insetRight|, and |insetTop|.
	1. Let |adjustedBottomRightRadius| be the |adjustedRadius| given 'border-bottom-right-radius', |insetRight|, and |insetBottom|.
	1. Let |adjustedBottomLeftRadius| be the |adjustedRadius| given 'border-bottom-left-radius', |insetLeft|, and |insetBottom|.
	1. Let |adjustedTopLeftRadius| be the |adjustedRadius| given 'border-top-left-radius', |insetLeft|, and |insetTop|.

	1. Clip out from |path|, the [=border-aligned corner clip-out path=] given 
		|borderRect|'s right, |borderRect|'s top,
		<code>(-|adjustedTopRightRadius|[0], 0)</code>, <code>(0, |adjustedTopRightRadius|[1])</code>,
		|element|'s [=computed value|computed=] 'corner-top-right-shape',
		|topInset|, and |rightInset|.

	1. Clip out from |path|, the [=border-aligned corner clip-out path=] given 
		|borderRect|'s right, |borderRect|'s bottom,
		<code>(0, -|adjustedBottomRightRadius|[1])</code>, <code>(-|adjustedBottomRightRadius|[0], 0)</code>,
		|element|'s [=computed value|computed=] 'corner-bottom-right-shape',
		|rightInset|, and |bottomInset|.
		
	1. Clip out from |path|, the [=border-aligned corner clip-out path=] given 
		|borderRect|'s left, |borderRect|'s bottom,
		<code>(|adjustedBottomLeftRadius|[0], 0)</code>, <code>(0, -|adjustedBottomLeftRadius|[1])</code>,
		|element|'s [=computed value|computed=] 'corner-bottom-left-shape',
		|bottomInset|, and |leftInset|.
		
	1. Clip out from |path|, the [=border-aligned corner clip-out path=] given 
		|borderRect|'s left, |borderRect|'s top,
		<code>(0, |adjustedTopLeftRadius|[1])</code>, <code>(|adjustedTopLeftRadius|[0], 0)</code>,
		|element|'s [=computed value|computed=] 'corner-top-left-shape',
		|leftInset|, and |topInset|.

	1. Return |path|.

To get the <dfn>border-aligned corner clip-out path</dfn> given a {{DOMPointReadOnly}} |originalCornerOuter|, a [=two-dimensional vector=] |vectorTowardsStart|, a [=two-dimensional vector=] |vectorTowardsEnd|, a [=superellipse parameter=] |curvature|, and numbers |startInset| and |endInset|:
	1. If |curvature| is ∞, then return an empty path.
	1. Let |clampedHalfCorner| be the [=normalized superellipse half corner=] given <code>clamp(|curvature|, -1, 1)</code>.
	1. Let |originalCornerStart| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |vectorTowardsStart| ».
	1. Let |originalCornerEnd| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |vectorTowardsEnd| ».
	1. Let |originalCornerCenter| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |vectorTowardsStart|, |vectorTowardsEnd| ».
	1. Let |extendStart| be a [=vector between two points|vector between=] |originalCornerStart| and |originalCornerCenter|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] |startInset|.
	1. Let |extendEnd| be a [=vector between two points|vector between=] |originalCornerEnd| and |originalCornerCenter|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] |endInset|.
	1. Let |clipStart| be |originalCornerStart|, [=point extended by vectors|extended by=] « |extendStart| ».
	1. Let |clipEnd| be |originalCornerEnd|, [=point extended by vectors|extended by=] « |extendEnd| ».
	1. Let |clipOuter| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |extendStart|, |extendEnd| ».
	1. Let |vectorFromStartToControlPoint| be the the [=two-dimensional vector=] <code>(2 ⋅ |clampedHalfCorner| - 0.5, 1.5 - 2 ⋅ |clampedHalfCorner|)</code>.
	1. Let |singlePixelVectorFromStartToControlPoint| be the |vectorFromStartToControlPoint|, [=two-dimensional vector/normalize|normalized=].
	1. Let <code>|strokeA|, |strokeB|</code> be the [=two-dimensional vector/perpendicular=] of |singlePixelVectorFromStartToControlPoint|.
	1. Let |offset1| be [=vector between two points|the vector between=] |originalCornerStart| and |outerCorner|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|startInset| ⋅ |strokeA|</code>.
	1. Let |offset2| be [=vector between two points|the vector between=] |outerCorner| and |originalCornerEnd|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|startInset| ⋅ |strokeB|</code>.
	1. Let |offset3| be [=vector between two points|the vector between=] |originalCornerEnd| and |originalCornerCenter|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|endInset| ⋅ |strokeB|</code>.
	1. Let |offset4| be [=vector between two points|the vector between=] |originalCornerCenter| and |originalCornerStart|, [=two-dimensional vector/normalize|normalized=] and [=two-dimensional vector/scale|scaled by=] <code>|endInset| ⋅ |strokeA|</code>.
	1. Let |adjustedCornerStart| be |originalCornerStart|, [=point extended by vectors|extended by=] « |offset1|, |offset2| ».
	1. Let |adjustedCornerEnd| be |originalCornerEnd|, [=point extended by vectors|extended by=] « |offset3|, |offset4| ».
	1. Let |adjustedCornerCenter| be |originalCornerCenter|, [=point extended by vectors|extended by=] « |offset4|, |offset1| ».
	1. Let |adjustedCornerOuter| be |originalCornerOuter|, [=point extended by vectors|extended by=] « |offset2|, |offset3| ».
	1. Let |curveCenter| be |adjustedCornerOuter| if |curvature| is less than 0, |adjustedCornerCenter| otherwise.
	1. Let |mapPointToCorner| be the following steps: given numbers |x| and |y|:
		1. Let |v1| be  [=vector between two points|the vector between=] |curveCenter| and |adjustedCornerEnd|, [=two-dimensional vector/scale|scaled by=] |x|.
		1. Let |v2| be  [=vector between two points|the vector between=] |curveCenter| and |adjustedCornerStart|, [=two-dimensional vector/scale|scaled by=] |y|.
		1. Return the {{DOMPointReadOnly}} at <code>(|x|, |y|)</code>, [=point extended by vectors|extended by=] « |v1|, |v2| ».

	1. Let |controlPoint| be the result of calling |mapPointToCorner| given |vectorFromStartToControlPoint|'s {{DOMPointReadOnly/y}} and <code>1 - |unitVectorFromStartToControlPoint|'s {{DOMPointReadOnly/x}}</code>.
	1. Let |axisAlignedCornerStart| be the intersection between the lines <code>(|adjustedCornerStart|, |controlPoint|)</code> and <code>(|clipStart|, |clipOuter|)</code>. If the lines are parallel, let it be <code>adjustedCornerStart</code>.
	1. Let |axisAlignedCornerEnd| be the intersection between the lines <code>(|adjustedCornerEnd|, |controlPoint|)</code> and <code>(|clipEnd|, |clipOuter|)</code>. If the lines are parallel, let it be <code>adjustedCornerEnd</code>.

			Note: |axisAlignedCornerStart| and |axisAlignedCornerEnd| act as "miters" when rendering an outset.
			They are a straight extension of the curve's tangent, intersecting with the unshaped target rect.
	
	1. Let |path| be a path, starting at |axisAlignedCornerStart|.
	1. If |curvature| is -∞:
		1. Extend |path| to |adjustedCornerStart|.
		1. Extend |path| to |adjustedCornerCenter|.
		1. Extend |path| to |adjustedCornerEnd|.
	1. Otherwise:
		1. Let |K| be <code>0.5<sup>-abs(|curvature|)</sup></code>.
		1. For every |T| between 0 and 1, in an [=implementation-approximated=] manner,
				extend |path| to the result of calling |mapPointToCorner| given <code>|T|<sup>|K|</sup></code> and <code>(1 - |T|)<sup>|K|</sup></code>.

	1. Extend |path| to |axisAlignedCornerEnd|.
	1. Extend |path| to |clipOuter|.
	1. Return |path|.
</div>

<wpt>
	corner-shape/corners-computed.html
	corner-shape/corners-invalid.html
	corner-shape/corners-valid.html
</wpt>

<h4 id=corner-shape-constrain-radii>
Constraining opposite radii</h4>

When concave 'corner-shape' values are present (the [=superellipse parameter=] is negative), diagonally opposite corners might overlap each other.

<div class="example">
	<p>The following example would create overlapping corners if not constrained.</p>
	<pre class="lang-css">
		div {
			corner-shape: scoop;
			border-top-left-radius: 80%;
			border-bottom-right-radius: 80%;
		}
	</pre>
</div>

To prevent this, the four radii are constrained to prevent overlaps.
This is done by computing a hull polygon for each of the opposite corners, and finding the highest downscale factor which, if applied to both corners, would make it so that the polygons would not intersect.

<div algorithm="constrain-radii-for-concave-corner-shape">
To compute the <dfn>opposite corner scale factor</dfn> given an [=/element=] |element|:
	1. Let |rect| be |element|'s [=border box=].
	1. Let |topRightHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-top-right-shape',
		mapped to the rectangle (|rect|'s [=width dimension=] - |element|'s [=computed value|computed=] horizontal 'border-top-right-radius', 0, |rect|'s [=computed value|computed=] 'border-top-right-radius').
	1. Let |bottomRightHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-bottom-right-shape',
		rotated by 90deg with (0.5, 0.5) as an origin,
		and mapped to the rectangle (|rect|'s [=width dimension=] - |element|'s [=computed value|computed=] horizontal 'border-bottom-right-radius', |rect|'s [=height dimension=] - |element|'s [=computed value|computed=] vertical 'border-bottom-right-radius',
		|element|'s [=computed value|computed=] 'border-bottom-right-radius').
	1. Let |bottomLeftHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-bottom-right-shape',
		rotated by 180deg with (0.5, 0.5) as an origin,
		and mapped to the rectangle (0, |rect|'s [=height dimension=] - |element|'s [=computed value|computed=] vertical 'border-bottom-left-radius',
		|element|'s [=computed value|computed=] 'border-bottom-left-radius').
	1. Let |topLeftHull| be a the [=normalized inner corner hull=] given |element|'s [=computed value|computed=] 'corner-top-left-shape',
		rotated by 270deg with (0.5, 0.5) as an origin,
		mapped to (0, 0, |element|'s [=computed value|computed=] 'border-top-left-radius').
	1. Let |scaleFactorA| be the highest number which, if both |topLeftHull| and |bottomRightHull| were scaled by, using their first point as the origin, those polygons would not intersect.
	1. Let |scaleFactorB| be the highest number which, if both |topRightHull| and |bottomLeftHull| were scaled by, using their first point as the origin, those polygons would not intersect.
	1. Return <code>min(1, |scaleFactorA|, |scaleFactorB|)</code>.
</div>


<h4 id=corner-shape-interpolation>
Interpolating corner shapes</h4>

Since a <<corner-shape-value>> can always be expressed by a ''superellipse()'' with an [=superellipse parameter=] variable, interpolating between two
<<corner-shape-value>>s is done by interpolating the [=superellipse parameter=] itself.
Since it uses a <code>log2</code>, interpolating it linearly would result in an effect where concave corners interpolate at a much higher velocity than convex corners.
To balance that, the <dfn>superellipse interpolation</dfn> formula describes how a [=superellipse parameter=] is converted to a value between 0 and 1, and vice versa:

<div algorithm="superellipse-param-to-interpolation-value">
To compute the <dfn>normalized superellipse half corner</dfn> given a [=superellipse parameter=] |s|, return the first matching statement, switching on |s|:

	<dl class=switch>
		: -∞
		:: Return 0.

		: ∞
		:: Return 1.

		: Otherwise
		::
			1. Let |k| be <code>0.5<sup>abs(|s|)</sup></code>.
			1. Let |convexHalfCorner| be <code>0.5<sup>1/|k|</sup></code>.
			1. If |s| is less than 0, return <code>1 - |convexHalfCorner|</code>.
			1. Return |convexHalfCorner|.
	</dl>
</div>

<div algorithm="superellipse-param-to-hull">
	To compute the <dfn>normalized inner corner hull</dfn> given a [=superellipse parameter=] |curvature|:

	1. If |curvature| is greater than or equal to zero, return a triangle betwen « (1, 1), (1, 0), (0, 1) ».
	1. Let |axisLineA| be a line between <code>(1, 0)</code> and <code>(1, 1)</code>.
	1. Let |axisLineB| be a line between <code>(0, 1)</code> and <code>(1, 1)</code>.
	1. Let |normalizedHalfCorner| be the [=normalized superellipse half corner=] given |curvature|.
	1. Let |halfCornerPoint| be <code>(|normalizedHalfCorner|, 1 - |normalizedHalfCorner|)</code>.
	1. Let |lineFromCenterToHalfCorner| be a line between <code>(0, 0)</code> and |halfCornerPoint|.
	1. Let |tangentLine| be the line perpendicular to |lineFromCenterToHalfCorner|, at |halfCornerPoint|.
	1. Let |intersectionA| be the intersection between |axisLineA| and |tangentLine|.
	1. Let |intersectionB| be the intersection between |axisLineB| and |tangentLine|.
	1. Return a pentagon between the points « (1, 1), (1, 0), |intersectionA|, |intersectionB|, (0, 1), (1, 1) ».
</div>

To interpolate a [=superellipse parameter=] |s| to an interpolation value between 0 and 1, return the [=normalized superellipse half corner=] given |s|.

<div algorithm="convert interpolation value to superellipse parameter">
	To convert a <<number [0,1]>> |interpolationValue| back to a [=superellipse parameter=], switch on |interpolationValue|:

	<dl class=switch>
		: 0
		:: Return -∞.

		: 0.5
		:: Return 0.

		: 1
		:: Return ∞.

		: Otherwise
		::
			1. Let |convexHalfCorner| be |interpolationValue|.
			1. If |interpolationValue| is less than 0.5, set |convexHalfCorner| to 1 - |interpolationValue|.
			1. Let |k| be <code>ln(0.5) / ln(|convexHalfCorner|)</code>.
			1. Let |s| be <code>log2(|k|)</code>.
			1. If |interpolationValue| is less than 0.5, return -|s|.
			1. Return |s|.

	</dl>
</div>

<wpt>
	corner-shape/corner-shape-interpolation.html
</wpt>

<h2 id="border-images">
Border Images</h2>

	Authors can specify an image to be used in place of the border styles.
	In this case, the border's design is taken from the sides and corners
	of an image specified with 'border-image-source',
	whose pieces may be sliced, scaled, and stretched in various ways
	to fit the size of the [=border image area=].
	The border-image properties do not affect layout:
	layout of the box, its content, and surrounding content
	is based on the 'border-width' and 'border-style' properties only.

	<div class=example>
		This example creates
		a top and bottom border consisting of a whole number of orange diamonds
		and a left and right border of a single, stretched diamond.
		The corners are diamonds of a different color.
		The image to tile is as follows.
		Apart from the diamonds, it is transparent:

		<img src="images/border.png" width="81" height="81"
		     alt="Tile for border"
		>

		The image is 81 by 81 pixels and has to be divided into 9 equal parts.
		The style rules could thus be as follows:

		<pre>
		DIV {
		  border: double orange 1em;
		  border-image: url("border.png") 27 round stretch;
		 }
		</pre>

		The result, when applied to a DIV of 12 by 5em,
		will be similar to this:

		<img src="images/borderresult.png" width="239" height="116"
		     alt="Element with a diamond border"
		>
	</div>

	<div class="example">
		This shows a more complicated example,
		demonstrating how the border image corresponds to the fallback border-style
		but can also extend beyond the border area.
		The border image is a wavy green border with an extended corner effect:

		<figure>
			<img src="images/groovy-border-image-slice.png" width="396" height="375"
			     alt="Diagram: The border image shows a wavy green border
			          with more exaggerated waves towards the corners,
			          which are capped by a disconnected green circle.
			          Four cuts at 124px offsets from each side
			          divide the image into 124px-wide square corners,
			          124px-wide but thin side slices,
			          and a small center square."
			>

			<figcaption>
				The 'border-image-source' image,
				with the four 'border-image-slice' cuts at 124px
				dividing the image into nine parts.
			</figcaption>
		</figure>

		The rest of the border properties then interact
		to lay out the tiles as follows:

		<figure>
			<img src="images/border-image.png" width="452" height="537"
			     alt="Diagram: The image-less (fallback) rendering
			          has a green double border.
			          The rendering with border-image shows the wavy green border,
			          ith the waves getting longer as they reach the corners.
			          The corner tiles render as 124px-wide squares
			          and the side tiles repeat a whole number of times
			          to fill the space in between.
			          Because of the gradual corner effects,
			          the tiles extend deep into the padding area.
			          The whole border image effect is outset 31px,
			          so that the troughs of the waves align
			          just outside the padding edge."
			>

			<figcaption>
				Diagram of all border-image properties and how they interact,
				and showing the rendering with and without the border-image in effect.
			</figcaption>
		</figure>

		Here, even though the 'border-width' is 12px,
		the 'border-image-width' property computes to 124px.
		The [=border image area=] is then outset 31px from the [=border box=]
		and into the [=margin area=].
		If the border-image fails to load
		(or if border images are not supported by the UA),
		the fallback rendering uses a green double border.
	</div>

	<div class="example" id="border-image-border-shorthand-example">
		Notice that the 'border' shorthand resets 'border-image'.
		This makes it easy to turn off or reset all border effects:

		<pre>
		.notebox {
		  border: double orange;
		  /* must set 'border' shorthand first, otherwise it erases 'border-image' */
		  border-image: url("border.png") 30 round;
		  /* but other 'border' properties can be set after */
		  border-width: thin thick;
		}
		...
		.sidebar .notebox {
		  box-shadow: 0 0 5px gray;
		  border-radius: 5px;
		  border: none; /* turn off all borders */
		  /* 'border' shorthand resets 'border-image' */
		}
		</pre>
	</div>

<h3 id="border-image-source" oldids="the-border-image-source">
Image Source: the 'border-image-source' property</h3>

	<pre class="propdef">
	Name: border-image-source
	Value: none | <<image>>
	Initial: none
	Applies to: All elements, except internal table elements when 'border-collapse' is ''border-collapse/collapse''
	Inherited: no
	Percentages: N/A
	Computed value: the keyword ''border-image-source/none'' or the computed <<image>>
	Animation type: discrete
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		animations/border-image-source-interpolation.html
		css3-border-image-source.html
		parsing/border-image-source-computed.sub.html
		parsing/border-image-source-invalid.html
		parsing/border-image-source-valid.html
	</wpt>

	Specifies an image to use as a border
	in place of the rendering specified by the 'border-style' properties
	and, if given the ''fill'' keyword in 'border-image-slice',
	as an additional image backdrop for the element.
	If the value is ''border-image-source/none'' or if the image cannot be displayed
	(or the property doesn't apply), the border styles will be used;
	otherwise the element's 'border-style' borders are not drawn
	and this <dfn export id="border-image-dfn">border image</dfn> is drawn
	as described in the sections below.

<h3 id="border-image-slice" oldids="the-border-image-slice">
Image Slicing: the 'border-image-slice' property</h3>

	<pre class="propdef">
	Name: border-image-slice
	Value: [<<number [0,∞]>> | <<percentage [0,∞]>>]{1,4} &amp;&amp; fill?
	Initial: 100%
	Applies to: All elements, except internal table elements when 'border-collapse' is ''border-collapse/collapse''
	Inherited: no
	Percentages: refer to size of the border image
	Computed value: four values, each either a number or percentage; plus a ''fill'' keyword if specified
	Animation type: by computed value
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		animations/border-image-slice-composition.html
		animations/border-image-slice-interpolation-stability.html
		animations/border-image-slice-interpolation.html
		border-image-slice-001.xht
		border-image-slice-002.xht
		border-image-slice-003.xht
		border-image-slice-004.htm
		border-image-slice-005.htm
		border-image-slice-006.htm
		border-image-slice-007.htm
		border-image-slice-fill-001.html
		border-image-slice-fill-002.html
		border-image-slice-fill-003.html
		border-image-slice-percentage.html
		border-image-slice-shorthand-reset.html
		parsing/border-image-slice-computed.html
		parsing/border-image-slice-invalid.html
		parsing/border-image-slice-valid.html
	</wpt>

	This property specifies inward offsets from
	the top, right, bottom, and left edges of the image,
	dividing it into nine regions: four corners, four edges and a middle.
	The middle image part is discarded (treated as fully transparent)
	unless the ''fill'' keyword is present.
	(It is drawn over the background;
	see <a href="#border-image-process">Drawing the Border Image</a>.)

	If there is only one component value,
	it applies to all sides.
	If there are two values,
	the top and bottom are set to the first value
	and the right and left are set to the second.
	If there are three values,
	the top is set to the first value,
	the left and right are set to the second,
	and the bottom is set to the third.
	If there are four values
	they apply to the top, right, bottom, and left, respectively.

	<dl dfn-for=border-image-slice dfn-type=value>
		<dt><dfn><<percentage [0,∞]>></dfn>
		<dd>
			Percentages are relative to the size of the image:
			the width of the image for the horizontal offsets,
			the height for vertical offsets.

		<dt><dfn><<number [0,∞]>></dfn>
		<dd>
			Numbers represent pixels in the image
			(if the image is a raster image)
			or vector coordinates
			(if the image is a vector image).

		<dt><dfn id="border-image-slice-fill">fill</dfn>
		<dd>
			The ''fill'' keyword, if present,
			causes the middle part of the border-image to be preserved.
			(By default it is discarded, i.e., treated as empty.)
	</dl>

	Negative values are invalid.
	Computed values larger than the size of the image are interpreted as ''100%''.

	The regions given by the 'border-image-slice' values may overlap.
	However if the sum of the right and left widths
	is equal to or greater than the width of the image,
	the images for the top and bottom edge and the middle part are empty--
	which has the same effect as if a nonempty transparent image
	had been specified for those parts.
	Analogously for the top and bottom values.

	If the image must be sized to determine the slices
	(for example, for SVG images with no [=natural dimensions=]),
	then it is sized using the <a href="https://www.w3.org/TR/css3-images/#default-sizing">default sizing algorithm</a>
	with no [=specified size=] and the [=border image area=] as the [=default object size=].

	<figure>
		<img src="images/slice.png" width="388" height="304"
		     alt="Diagram: two horizontal cuts and two vertical cuts through an image"
		>

		<figcaption>
			Diagram illustrating the cuts corresponding to the value ''25% 30% 12% 20%''
		</figcaption>
	</figure>

<h3 id="border-image-width" oldids="the-border-image-width">
Drawing Areas: the 'border-image-width' property</h3>

	<pre class="propdef">
	Name: border-image-width
	Value: [ <<length-percentage [0,∞]>> | <<number [0,∞]>> | auto ]{1,4}
	Initial: 1
	Applies to: All elements,
		except internal table elements when 'border-collapse' is ''border-collapse/collapse''
	Inherited: no
	Percentages: Relative to width/height of the [=border image area=]
	Computed value: four values,
		each either a number,
		the keyword ''border-image-width/auto'',
		or a computed <<length-percentage>> value
	Animation type: by computed value
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		border-image-width-001.htm
		border-image-width-005.xht
		border-image-width-006.xht
		border-image-width-007.xht
		border-image-width-008.html
		border-image-width-009.html
		border-image-width-should-extend-to-padding.html
		parsing/border-image-width-computed.html
		parsing/border-image-width-invalid.html
		parsing/border-image-width-valid.html
	</wpt>

	The [=border image=] is drawn inside an area called the <dfn export>border image area</dfn>.
	This is an area whose boundaries by default correspond to the [=border box=],
	see 'border-image-outset'.

	The four values of 'border-image-width' specify offsets
	that are used to divide the [=border image area=] into nine
	<dfn export lt="border image region" local-lt="region">regions</dfn>.
	The offsets represent inward distances from
	the top, right, bottom, and left sides of the area, respectively.

	If there is only one component value,
	it applies to all sides.
	If there are two values,
	the top and bottom are set to the first value
	and the right and left are set to the second.
	If there are three values,
	the top is set to the first value,
	the left and right are set to the second,
	and the bottom is set to the third.
	If there are four values
	they apply to the top, right, bottom, and left, respectively.

	Values have the following meanings:

	<dl dfn-for=border-image-width dfn-type=value>
		<dt><dfn><<length-percentage [0,∞]>></dfn>
		<dd>
			Percentages refer to the size of the [=border image area=]:
			the width of the area for horizontal offsets,
			the height for vertical offsets.

		<dt><dfn><<number [0,∞]>></dfn>
		<dd>
			Numbers represent multiples of the corresponding computed
			<a href="#border-width">border-width</a>.

		<dt><dfn>auto</dfn>
		<dd>
			If ''border-image-width/auto'' is specified
			then the used 'border-image-width' is
			the [=natural size|natural=] width or height (whichever is applicable)
			of the corresponding image slice (see 'border-image-slice').
			If the image does not have the required [=natural dimension=]
			then the corresponding computed 'border-width' is used instead.
	</dl>

	Negative values are invalid for any 'border-image-width' values.

	If two opposite 'border-image-width' offsets are large enough that they overlap,
	then the [=used values=] of all 'border-image-width' offsets
	are proportionally reduced until they no longer overlap.
	In mathematical notation:
	Given <var>L<sub>width</sub></var>
	as the width of the [=border image area=],
	<var>L<sub>height</sub></var>
	as its height,
	and <var>W<sub><var>side</var></sub></var>
	as the 'border-image-width' offset for the <var>side</var> side,
	let <var>f</var> = min(<var>L<sub>width</sub></var>/(<var>W<sub>left</sub></var>+<var>W<sub>right</sub></var>),
	<var>L<sub>height</sub></var>/(<var>W<sub>top</sub></var>+<var>W<sub>bottom</sub></var>)).
	If <var>f</var> &lt; 1,
	then all <var>W</var> are reduced by multiplying them by <var>f</var>.

<h3 id="border-image-outset" oldids="the-border-image-outset">
Edge Overhang: the 'border-image-outset' property</h3>

	<pre class="propdef">
	Name: border-image-outset
	Value: [ <<length [0,∞]>> | <<number [0,∞]>> ]{1,4}
	Initial: 0
	Applies to: All elements, except internal table elements when 'border-collapse' is ''border-collapse/collapse''
	Inherited: no
	Percentages: N/A
	Computed value: four values, each a number or absolute length
	Animation type: by computed value
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		animations/border-image-outset-composition.html
		animations/border-image-outset-interpolation.html
		border-image-outset-003.html
		parsing/border-image-outset-computed.html
		parsing/border-image-outset-invalid.html
		parsing/border-image-outset-valid.html
	</wpt>

	The values specify the amount by which the [=border image area=]
	extends beyond the [=border box=].

	If there is only one component value,
	it applies to all sides.
	If there are two values,
	the top and bottom are set to the first value
	and the right and left are set to the second.
	If there are three values,
	the top is set to the first value,
	the left and right are set to the second,
	and the bottom is set to the third.
	If there are four values
	they apply to the top, right, bottom, and left, respectively.

	<dl dfn-for=border-image-outset dfn-type=value>
		<dt><<length [0,∞]>>
		<dd>
			Represents an outset of the specified length.

		<dt><<number [0,∞]>>
		<dd>
			Represents an outset of the specified multiple of
			the corresponding computed <a href="#border-width">border-width</a>.
	</dl>

	Negative values are invalid.

	Portions of the border-image that are rendered outside the [=border box=]
	are [=ink overflow=] and
	do not trigger scrolling.
	Also such portions are invisible to mouse events
	and do not capture such events on behalf of the element.

	Note: Even though they never cause a scrolling mechanism,
	outset images may still be clipped by an ancestor or by the viewport.

<h3 id="border-image-repeat" oldids="the-border-image-repeat">
Image Tiling: the 'border-image-repeat' property</h3>

	<pre class="propdef">
	Name: border-image-repeat
	Value: [ stretch | repeat | round | space ]{1,2}
	Initial: stretch
	Applies to: All elements, except internal table elements when 'border-collapse' is ''border-collapse/collapse''
	Inherited: no
	Percentages: N/A
	Computed value: two keywords, one per axis
	Animation type: discrete
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		animations/discrete-no-interpolation.html
		border-image-repeat-002.htm
		border-image-repeat-004.htm
		border-image-repeat-005.html
		border-image-repeat-1.html
		border-image-repeat-repeat-001.html
		border-image-repeat-round-003.html
		border-image-repeat-round-1.html
		border-image-repeat-round-2.html
		border-image-repeat-round-stretch-001.html
		border-image-repeat-round.html
		border-image-repeat-space-011.html
		border-image-repeat-space-1.html
		border-image-repeat-space-10.html
		border-image-repeat-space-2.html
		border-image-repeat-space-3.html
		border-image-repeat-space-4-ref-1.html
		border-image-repeat-space-4.html
		border-image-repeat-space-5-ref-1.html
		border-image-repeat-space-5.html
		border-image-repeat-space-6.html
		border-image-repeat-space-7.html
		border-image-repeat-space-8.html
		border-image-repeat-space-9.html
		border-image-repeat-stretch-round-001.html
		border-image-repeat_repeatnegx_none_50px.html
		css3-border-image-repeat-repeat.html
		css3-border-image-repeat-stretch.html
		parsing/border-image-repeat-computed.html
		parsing/border-image-repeat-invalid.html
		parsing/border-image-repeat-valid.html
	</wpt>

	This property specifies how the images for the sides
	and the middle part of the [=border image=]
	are scaled and tiled.
	The first keyword applies to the horizontal scaling and tiling
	of the top, middle and bottom parts,
	the second to the vertical scaling and tiling
	of the left, middle and right parts;
	see <a href="#border-image-process">Drawing the Border Image</a>.
	If the second keyword is absent, it is assumed to be the same as the first.
	Values have the following meanings:

	<dl dfn-for=border-image-repeat dfn-type=value>
		<dt><dfn>stretch</dfn></dt>
		<dd>
			The image is stretched to fill its corresponding [=region=].
		<dt><dfn>repeat</dfn></dt>
		<dd>
			The image is tiled (repeated) to fill its corresponding [=region=].
		<dt><dfn>round</dfn></dt>
		<dd>
			The image is tiled (repeated) to fill its corresponding [=region=].
			If it does not fill the area with a whole number of tiles,
			the image is rescaled so that it does.
		<dt><dfn>space</dfn></dt>
		<dd>
			The image is tiled (repeated) to fill its corresponding [=region=].
			If it does not fill the region with a whole number of tiles,
			the extra space is distributed around the tiles.
	</dl>

	The exact process for scaling and tiling the border-image parts
	is given in the section below.

<h3 id="border-image-process">
Drawing the Border Image</h3>

	After the [=border image=] given by 'border-image-source'
	is sliced by the 'border-image-slice' values,
	the resulting nine images are scaled, positioned, and tiled
	into their corresponding [=border image regions=] in four steps:

	<ol>
	<li>Scale to 'border-image-width'.
		<ul>
		<li>The two images for the top and bottom edges are made as tall
			as the top and bottom [=border image regions=], respectively,
			and their width is scaled proportionally.

		<li>The images for the left and right edges are made as wide
			as the left and right [=border image regions=], respectively,
			and their height is scaled proportionally.

		<li>The corner images are scaled to be as wide and as tall
			as the their respective [=border image regions=].

		<li>The middle image's width is scaled by the same factor as the top image
			unless that factor is zero or infinity,
			in which case the scaling factor of the bottom is substituted,
			and failing that, the width is not scaled.
			The height of the middle image is scaled by the same factor as the left image
			unless that factor is zero or infinity,
			in which case the scaling factor of the right image is substituted,
			and failing that, the height is not scaled.
		</ul>

	<li>Scale to 'border-image-repeat'.
		<ul>
		<li>If the first keyword is ''border-image-repeat/stretch'',
			the top, middle and bottom images are further scaled
			to be as wide as the middle region of the [=border image area=].
			The height is not changed any further.

		<li>If the first keyword is ''border-image-repeat/round'',
			the top, middle and bottom images are resized in width,
			so that exactly a whole number of them fit
			in the middle region of the [=border image area=],
			exactly as for ''background-repeat/round'' in the 'background-repeat' property.

		<li>If the first keyword is ''border-image-repeat/repeat'' or ''border-image-repeat/space'',
			the top, middle, and bottom images are not changed any further.

		<li>The effects of ''border-image-repeat/stretch'', ''border-image-repeat/round'', ''border-image-repeat/repeat'', and ''border-image-repeat/space''
			for the second keyword are analogous,
			acting on the height of the left, middle and right images.
		</ul>

	<li>Position the first tile.
		<ul>
		<li>If the first keyword is ''border-image-repeat/repeat'',
			the top, middle, and bottom images
			are centered horizontally in their respective regions.
			Otherwise the images are placed at the left edge
			of their respective regions of the [=border image area=].

		<li>If the second keyword is ''border-image-repeat/repeat'',
			the left, middle, and right images
			are centered vertically in their respective regions.
			Otherwise the images are placed at the top edge
			of their respective regions of the [=border image area=].
		</ul>

	<li>Tile and draw.
		<ul>
		<li>The images are then tiled to fill their respective regions.

		<li>In the case of ''border-image-repeat/space'',
			any partial tiles are discarded and the extra space distributed
			before, after, and between the tiles.
			(I.e. the gap before the first tile,
			the gap after the last tile,
			and the gaps between tiles are equalized.)
			<span class="note">This can result in empty border-image side regions.</span>

		<li>The images are drawn at the same stacking level as normal borders:
			immediately in front of the background layers.

		<li>The middle image is not drawn
			unless ''fill'' was specified for 'border-image-source'.
		</ul>
	</ol>

<h3 id="border-image" oldids="the-border-image">
Border Image Shorthand: the 'border-image' property</h3>

	<pre class="propdef">
	Name: border-image
	Value: <<'border-image-source'>> || <<'border-image-slice'>> [ / <<'border-image-width'>> | / <<'border-image-width'>>? / <<'border-image-outset'>> ]? || <<'border-image-repeat'>>
	Initial: See individual properties
	Applies to: See individual properties
	Inherited: no
	Percentages: N/A
	Computed value: See individual properties
	Animation Type: See individual properties
	</pre>

	<wpt pathprefix="/css/css-backgrounds/">
		border-image-002.html
		border-image-003.html
		border-image-004.html
		border-image-006.html
		border-image-007.html
		border-image-011.html
		border-image-012.html
		border-image-013.html
		border-image-017.xht
		border-image-018.xht
		border-image-019.xht
		border-image-020.xht
		border-image-calc.html
		border-image-image-type-001.htm
		border-image-image-type-002.htm
		border-image-image-type-003.htm
		border-image-image-type-004.htm
		border-image-image-type-005.htm
		border-image-round-and-stretch.html
		border-image-shorthand-001.htm
		border-image-shorthand-002.htm
		border-image-shorthand-003.htm
		border-image-space-001.html
		parsing/border-image-invalid.html
		parsing/border-image-shorthand.sub.html
		parsing/border-image-valid.html
	</wpt>

	This is a shorthand property for setting
	'border-image-source',
	'border-image-slice',
	'border-image-width',
	'border-image-outset',
	and 'border-image-repeat'
	in a single declaration.
	Omitted values are set to their [=initial values=].

<h3 id=border-image-tables>Effect on Tables</h3>

	The 'border-image' properties apply
	to the border of tables and inline tables
	that have 'border-collapse' set to ''border-collapse/collapse''.
	However, this specification does not define
	how such an image border is rendered.
	In particular, it does not define how the image border interacts
	with the borders of cells, rows and row groups at the edges of the table
	(see <a href="https://www.w3.org/TR/2011/REC-CSS2-20110607/tables.html#border-conflict-resolution">border conflict resolution</a> in [[!CSS2]]).

	It is expected that a future specification will define the rendering.
	It is recommended that UAs do not apply border images
	to tables with collapsed borders until then.

<h2 id="partial-borders">
Partial borders</h2>

<details>
	<summary>Not Ready For Implementation</summary>
	<p>
	This section is not yet ready for implementation.
	It exists in this repository to record the ideas and promote discussion.
	<p>
	Before attempting to implement anything of this section,
	please contact the CSSWG at www-style@w3.org.
</details>

	CSS borders traditionally cover an entire border edge. Sometimes,
	however, it can be useful to hide some parts of the border.

	Issue: Here are two proposals for doing this:
	the second one is from GCPM, the first one is an attempt to recast it more readably.
	The names are terrible, known problem, proposals accepted.
	There is a problem with conceiving this as clipping:
	if you have dotted borders, you want whole dots always, not parts of dots.
	So it should be a drawing limit, not a clip.

<h3 id="border-limit">
Partial Borders: the 'border-limit' property</h3>

	<pre class="propdef">
		Name: border-limit
		Value: all | [ sides | corners ] <<length-percentage [0,∞]>>?
					| [ top | right | bottom | left ] <<length-percentage [0,∞]>>
		Initial: all
		Applies to: all elements, except table element when 'border-collapse' is ''collapse''
		Inherited: no
		Percentages: relative to border-box
		Animation type: discrete
	</pre>

	<p>By default, the entire border is drawn. However, border rendering can be
		limited to only part of a border. The keyword specifies which part, and
		the length or percentage specifies how much.

	<dl dfn-type="value" dfn-for="border-limit">
		<dt><dfn>''all''</dfn>
			<dd>The entire border is drawn.
		<dt><dfn>''sides''</dfn>
			<dd>The sides are drawn up to but not including the corners (as defined
			by the border radii). A length or percentage is measured from the center
			of each side: ''50%'' draws the middle 50% of the border; by default the
			entire side is drawn.
		<dt><dfn>''corners''</dfn>
			<dd>The corners are drawn plus the specified distance into the sides if
			specified. A length is measured from the closest edge of the corner area.
			A percentage is measured from the absolute corner of the border box.
		<dt><dfn>''left''</dfn>
		<dt><dfn>''right''</dfn>
			<dd>For the left and right (vertical) sides, draws the entire side and
			corner. For the top and bottom (horizontal) sides, draws the left/right
			portion, as specified. Distances are measured as for ''corners''.
		<dt><dfn>''top''</dfn>
		<dt><dfn>''bottom''</dfn>
			<dd>For the top and bottom (horizontal) sides, draws the entire side and
			corner. For the left and right (vertical) sides, draws the top/bottom
			portion, as specified. Distances are measured as for ''corners''.
	</dl>

	<div class="example">
		<p>The following example draws only the middle 50% of the sides.</p>
		<pre class="lang-css">
			div {
				border: solid;
				border-limit: sides 50%;
			}
		</pre>
	</div>
	<div class="example">
		<p>The following example draws only the curved parts of the corners.</p>
		<pre class="lang-css">
			div {
				border: solid;
				border-radius: 1em 2em;
				border-limit: corners;
			}
		</pre>
	</div>
	<div class="example">
		<p>The following example draws only the left 4em of the top border.</p>
		<pre class="lang-css">
			div {
				border-top: solid;
				border-limit: left 4em;
			}
		</pre>
	</div>
	<div class="example">
		<p>The following example draws only the first 10px of each corner:</p>
		<pre class="lang-css">
			div {
				border: solid;
				border-limit: corners 10px;
			}
		</pre>
	</div>
	<div class="example">
		<p>The following example draws the curved part of the corner plus 5px
		along the sides:</p>
		<pre class="lang-css">
			div {
				border: solid;
				border-radius: 5px;
				border-limit: corners 5px;
			}
		</pre>
	</div>
	<div class="example">
		<p>The following example draws the curved part of the corner and all of
		the side except the middle 40%.</p>
		<pre class="lang-css">
			div {
				border: solid;
				border-radius: 5px;
				border-limit: corners 30%;
			}
		</pre>
	</div>

<h3 id="border-clip">
The 'border-clip' properties</h3>

	<pre class="propdef">
		Name: border-top-clip, border-right-clip, border-bottom-clip, border-left-clip,
			border-block-start-clip, border-block-end-clip, border-inline-start-clip, border-inline-end-clip
		Value: none | [ <<length-percentage [0,∞]>> | <<flex>> ]+
		Initial: none
		Inherited: no
		Logical property group: border-clip
		Percentages: refer to length of border-edge side
		Computed value: ''border-top-clip/none'', or a list consisting of absolute lengths, or percentages as specified
		Animation type: by computed value
	</pre>

	<p>These properties split their respective borders into parts along
	the border edge. The first part is visible, the second is invisible,
	the third part is visible, etc. Parts can be specified with lengths,
	percentages, or flexible lengths (expressed by the ''fr'' unit, as per
	[[CSS3GRID]]).
	The ''border-top-clip/none'' value means
	that the border is not split, but shown normally.

	The [=flow-relative=] longhands
	('border-block-start-clip', etc.)
	correspond to the [=physical=] longhands
	('border-top-clip', etc.)
	depending on the element’s 'writing-mode', 'direction', and 'text-orientation'.

	<pre class="propdef shorthand">
		Name: border-block-clip, border-inline-clip
		Value: <<'border-top-clip'>>
	</pre>

	These two [=shorthand properties=] set the
	'border-block-start-clip' &amp; 'border-block-end-clip'
	and
	'border-inline-start-clip' &amp; 'border-inline-end-clip',
	respectively.

	<pre class="propdef shorthand">
		Name: border-clip
		Value: <<'border-top-clip'>>
	</pre>

	'border-clip' is a [=shorthand property=] for the longhand properties,
	setting all four sides to the same value.

	If the listed parts are shorter than the border, any remaining
	border is split proportionally between the specified flexible lengths. If
	there are no flexible lengths, the behavior is as if ''1fr'' had been
	specified at the end of the list.

	If the listed parts are longer than the border, the specified parts
	will be shown in full until the end of the border. In this case, all
	flexible lengths will be zero.

	For horizontal borders, parts are listed from left to right. For
	vertical borders, parts are listed from top to bottom.

	The exact border parts are determined by laying out the specified border
	parts with all flexible lengths initially set to zero. Any remaining border is
	split proportionally between the flexible lengths specified.

	<div class="example">
		<pre>border-clip: 10px 1fr 10px;</pre>

		<div style="position: relative; width: 250px; height: 150px; background: white;">
			<div style="border: 2px solid black; width: 200px; height: 100px; position: absolute; top: 20px; left: 20px">
				<div style="position: absolute; background: white; left: 15px; top: -5px; height: 110px; width: 170px"></div>
				<div style="position: absolute; background: white; left: -5px; top: 15px; height: 70px; width: 210px"></div>
			</div>
		</div>
	</div>

	<div class="example">
		<pre>
			border-top-clip: 10px 1fr 10px;
			border-bottom-clip: 10px 1fr 10px;
			border-right-clip: 5px 1fr 5px;
			border-left-clip: 5px 1fr 5px;
		</pre>
		<div style="position: relative; width: 250px; height: 150px; background: white;">
			<div style="border: 2px solid black; width: 200px; height: 100px; position: absolute; top: 20px; left: 20px">
				<div style="position: absolute; background: white; left: 15px; top: -5px; height: 110px; width: 170px"></div>
				<div style="position: absolute; background: white; left: -5px; top: 5px; height: 90px; width: 210px"></div>
			</div>
		</div>
	</div>

	<div class="example">
		<p>By making the first part have zero length, the inverse border of
		the previous example can easily be created:

		<pre>
			border-top-clip: 0 10px 1fr 10px;
			border-bottom-clip: 0 10px 1fr 10px;
			border-right-clip: 0 5px 1fr 5px;
			border-left-clip: 0 5px 1fr 5px;
		</pre>

		<div style="position: relative; width: 250px; height: 150px; background: white;">
			<div style="border: 2px solid black; width: 200px; height: 100px; position: absolute; top: 20px; left: 20px">
				<div style="position: absolute; background: white; left: -5px; top: -5px; height: 10px; width: 15px"></div>
				<div style="position: absolute; background: white; right: -5px; top: -5px; height: 10px; width: 15px"></div>
				<div style="position: absolute; background: white; left: -5px; top: 95px; height: 10px; width: 15px"></div>
				<div style="position: absolute; background: white; right: -5px; top: 95px; height: 10px; width: 15px"></div>
			</div>
		</div>
	</div>

	<div class="example">
		<pre>
			border: thin solid black;
			border-clip: 0 1fr; /* hide borders */
			border-top-clip: 10px 1fr 10px; /* make certain borders visible */
			border-bottom-clip: 10px 1fr 10px;
		</pre>

		<div style="position: relative; width: 250px; height: 150px; background: white;">
			<div style="border: 2px solid black; width: 200px; height: 100px; position: absolute; top: 20px; left: 20px">
				<div style="position: absolute; background: white; left: 15px; top: -5px; height: 110px; width: 170px"></div>
				<div style="position: absolute; background: white; left: -5px; top: 0px; height: 100px; width: 210px"></div>
			</div>
		</div>
	</div>

	<div class="example">
		<pre>
			border-top: thin solid black;
			border-bottom: thin solid black;
			border-top-clip: 10px;
			border-bottom-clip: 10px;
		</pre>

		<div style="position: relative; width: 250px; height: 150px; background: white;">
			<div style="border: 2px solid black; width: 200px; height: 100px; position: absolute; top: 20px; left: 20px">
				<div style="position: absolute; background: white; left: 15px; top: -5px; height: 110px; width: 200px"></div>
				<div style="position: absolute; background: white; left: -5px; top: 0px; height: 100px; width: 210px"></div>
			</div>
		</div>
	</div>

	<div class="example">
		<pre>
			border-top: thin solid black;
			border-clip: 10px;
		</pre>
		<div style="position: relative; width: 250px; height: 150px; background: white;">
			<div style="border: 2px solid black; width: 200px; height: 100px; position: absolute; top: 20px; left: 20px">
				<div style="position: absolute; background: white; left: 15px; top: -5px; height: 110px; width: 200px"></div>
				<div style="position: absolute; background: white; left: -5px; top: 0px; height: 110px; width: 210px"></div>
			</div>
		</div>
	</div>

	<div class="example">
		<p>This rendering:
		<div style="background: white; color: black; padding: 0.2em 0.5em">
			<pre style="margin-left: 0;">
				A sentence consists of words&#xB9;.
			</pre>
			<div style="width: 3em; height: 2px; background: black"></div>
			<pre style="margin-left: 0">
				&#xB9; Most often.
			</pre>
		</div>
		can be achieved with this style sheet:
		<pre>
			@footnote {
				border-top: thin solid black;
				border-clip: 4em;
			}
		</pre>
	</div>

	<div class="example">
		<pre>
			border: 4px solid black;
			border-top-clip: 40px 20px 0 1fr 20px 20px 0 1fr 40px;
		</pre>
		<p>In this example, there will be a visible 40px border part on each end of the top border. Inside the 40px border parts, there will be an invisible border part of at least 20px. Inside these invisible border parts, there will be visible border parts, each 20px long with 20px invisible border parts between them.
		<div style="position: relative; width: 192px; background: white; padding: 40px">
			<div style="border: 4px solid black; height: 40px"></div>
			<div style="position: absolute; background: white; width: 20px; height: 4px; top: 40px; left: 80px"></div>
			<div style="position: absolute; background: red; width: 6px; height: 4px; top: 40px; left: 100px"></div>
			<div style="position: absolute; background: white; width: 20px; height: 4px; top: 40px; left: 126px"></div>
			<div style="position: absolute; background: white; width: 20px; height: 4px; top: 40px; left: 166px"></div>
			<div style="position: absolute; background: red; width: 6px; height: 4px; top: 40px; left: 186px"></div>
		</div>
		<p>The fragments are shown in red for illustrative purposes; they should not be visible in compliant UAs.
	</div>

	<div class="example">
		<pre>
			border: 4px solid black;
			border-top-clip: 3fr 10px 2fr 10px 1fr 10px 10px 10px 1fr 10px 2fr 10px 3fr;
		</pre>

		<p>All but one of the visible border parts are represented as flexible lengths in this example. The length of these border parts will change when the width of the element changes. Here is one rendering where 1fr ends up being 10px:
		<div style="position: relative; width: 190px; background: white; padding: 40px">
			<div style="border: 4px solid black; border-top: none; height: 40px"></div>
			<div style="position: absolute; background: red; width: 30px; height: 4px; top: 40px; left: 40px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 70px"></div>
			<div style="position: absolute; background: red; width: 20px; height: 4px; top: 40px; left: 80px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 100px"></div>
			<div style="position: absolute; background: red; width: 10px; height: 4px; top: 40px; left: 110px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 120px"></div>
			<div style="position: absolute; background: black; width: 10px; height: 4px; top: 40px; left: 130px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 140px"></div>
			<div style="position: absolute; background: red; width: 10px; height: 4px; top: 40px; left: 150px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 160px"></div>
			<div style="position: absolute; background: red; width: 20px; height: 4px; top: 40px; left: 170px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 190px"></div>
			<div style="position: absolute; background: red; width: 30px; height: 4px; top: 40px; left: 200px"></div>
		</div>

		<p>Here is another rendering where 1fr ends up being 30px:

		<div style="position: relative; width: 440px; background: white; padding: 40px">
			<div style="border: 4px solid black; border-top: none; height: 40px"></div>
			<div style="position: absolute; background: red; width: 90px; height: 4px; top: 40px; left: 40px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 130px"></div>
			<div style="position: absolute; background: red; width: 60px; height: 4px; top: 40px; left: 140px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 200px"></div>
			<div style="position: absolute; background: red; width: 30px; height: 4px; top: 40px; left: 210px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 240px"></div>
			<div style="position: absolute; background: black; width: 10px; height: 4px; top: 40px; left: 250px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 260px"></div>
			<div style="position: absolute; background: red; width: 30px; height: 4px; top: 40px; left: 270px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 300px"></div>
			<div style="position: absolute; background: red; width: 60px; height: 4px; top: 40px; left: 310px"></div>
			<div style="position: absolute; background: white; width: 10px; height: 4px; top: 40px; left: 370px"></div>
			<div style="position: absolute; background: red; width: 90px; height: 4px; top: 40px; left: 390px"></div>
		</div>
		<p>The fragments are shown in red for illustrative purposes; they should be black in compliant UAs.
	</div>

<wpt>
	tentative/parsing/border-clip-computed.html
	tentative/parsing/border-clip-invalid.html
	tentative/parsing/border-clip-valid.html
</wpt>

<h2 id="drop-shadows" oldids="misc">
Drop Shadows</h2>

<h3 id="box-shadow-color">
Coloring shadows: the 'box-shadow-color' property</h3>

	<pre class="propdef">
		Name: box-shadow-color
		Value: <<color>>#
		Initial: currentcolor
		Applies to: all elements
		Inherited: no
		Percentages: N/A
		Computed value: list, each item a computed color
		Animation type: by computed value
	</pre>

	<p>The 'box-shadow-color' property defines one or more drop shadow colors.
	The property accepts a comma-separated list of shadow colors.

	<p>See the section [[css-backgrounds-3#shadow-layers|“Layering, Layout, and
	Other Details”]] for how 'box-shadow-color' interacts with other
	comma-separated drop shadow properties to form each drop shadow
	layer.

<wpt>
	tentative/parsing/box-shadow-color-computed.html
	tentative/parsing/box-shadow-color-invalid.html
	tentative/parsing/box-shadow-color-valid.html
</wpt>

<h3 id="box-shadow-offset">
Offsetting shadows: the 'box-shadow-offset' property</h3>

	<pre class="propdef">
		Name: box-shadow-offset
		Value: [ none | <<length>>{1,2} ]#
		Initial: none
		Applies to: all elements
		Inherited: no
		Percentages: N/A
		Computed value: list, each item either ''box-shadow-offset/none'' or a pair of offsets
			(horizontal and vertical) from the element‘s box
		Animation type: by computed value,
			treating ''box-shadow-offset/none'' as ''0 0''
			when interpolated with non-''box-shadow-offset/none'' values.
	</pre>

	<p>The 'box-shadow-offset' property defines one or more drop shadow offsets.
	The property accepts a comma-separated list.
	Each item in that list can either be the ''box-shadow-offset/none'' value,
	which indicates no shadow,
	a pair of <<length>> values,
	which define the horizontal and vertical offsets,
	or a single <<length>> value,
	which sets both offsets to the same value.

	<dl dfn-type=value dfn-for=box-shadow-offset>
	<dt><dfn id="shadow-offset-none">none</dfn>
	<dd>
		The shadow will not be rendered.
		The values of other box shadow properties corresponding to this shadow have no effect.

	<dt><dfn id="shadow-offset-x">1st <<length>></dfn>
	<dd>
		Specifies the <dfn>horizontal offset</dfn> of the shadow.
		A positive value draws a shadow that is offset to the right of the box,
		a negative length to the left.

		If only one <<length>> value is specified,
		it sets both the horizontal and vertical offsets to that value.

	<dt><dfn id="shadow-offset-y">2nd <<length>></dfn>
	<dd>
		Specifies the <dfn>vertical offset</dfn> of the shadow.
		A positive value offsets the shadow down, a negative one up.
	</dl>

	<p>See the section [[css-backgrounds-3#shadow-layers|“Layering, Layout, and
	Other Details”]] for how 'box-shadow-offset' interacts with other
	comma-separated drop shadow properties to form each drop shadow
	layer.

<wpt>
	tentative/parsing/box-shadow-offset-computed.html
	tentative/parsing/box-shadow-offset-invalid.html
	tentative/parsing/box-shadow-offset-valid.html
</wpt>

<h3 id="box-shadow-blur">
Blurring shadows: the 'box-shadow-blur' property</h3>

	<pre class="propdef">
		Name: box-shadow-blur
		Value: <<length [0,∞]>>#
		Initial: 0
		Applies to: all elements
		Inherited: no
		Percentages: N/A
		Computed value: list, each item a <<length>>
		Animation type: by computed value
	</pre>

	<p>The 'box-shadow-blur' property defines one or more blur radii for drop shadows.
	The property accepts a comma-separated list of <<length>> values.

	<p>Negative values are invalid.
	If the blur value is zero, the shadow’s edge is sharp.
	Otherwise, the larger the value, the more the shadow’s edge is blurred.
	See [[css-backgrounds-3#shadow-blur|Shadow Blurring]], below.

	<p>See the section [[css-backgrounds-3#shadow-layers|“Layering, Layout, and
	Other Details”]] for how 'box-shadow-blur' interacts with other
	comma-separated drop shadow properties to form each drop shadow
	layer.

<wpt>
	tentative/parsing/box-shadow-blur-computed.html
	tentative/parsing/box-shadow-blur-invalid.html
	tentative/parsing/box-shadow-blur-valid.html
</wpt>

<h3 id="box-shadow-spread">
Spreading shadows: the 'box-shadow-spread' property</h3>

	<pre class="propdef">
		Name: box-shadow-spread
		Value: <<length>>#
		Initial: 0
		Applies to: all elements
		Inherited: no
		Percentages: N/A
		Computed value: list, each item a <<length>>
		Animation type: by computed value
	</pre>

	<p>The 'box-shadow-spread' property defines one or more spread distances for drop shadows.
	The property accepts a comma-separated list of <<length>> values.

	<p>Positive values cause the shadow to expand in all directions by the specified radius.
	Negative values cause the shadow to contract.
	See [[css-backgrounds-3#shadow-shape|Shadow Shape]], below.
	<p class="note">Note that for inner shadows,
	expanding the shadow (creating more shadow area)
	means contracting the shadow’s perimeter shape.

	<p>See the section [[css-backgrounds-3#shadow-layers|“Layering, Layout, and
	Other Details”]] for how 'box-shadow-spread' interacts with other
	comma-separated drop shadow properties to form each drop shadow
	layer.

<wpt>
	tentative/parsing/box-shadow-spread-computed.html
	tentative/parsing/box-shadow-spread-invalid.html
	tentative/parsing/box-shadow-spread-valid.html
</wpt>

<h3 id="box-shadow-position">
Spreading shadows: the 'box-shadow-position' property</h3>

	<pre class="propdef">
		Name: box-shadow-position
		Value: [ outset | inset ]#
		Initial: outset
		Applies to: all elements
		Inherited: no
		Percentages: N/A
		Computed value: list, each item one of the keywords
		Animation type: by computed value
	</pre>

	<p>The 'box-shadow-position' property defines one or more drop shadow positions.
	The property accepts a comma-separated list of ''box-shadow-position/outset'' and ''box-shadow-position/inset'' keywords.

	<dl dfn-type=value dfn-for=box-shadow-position>
	<dt><dfn>outset</dfn>
	<dd>
		Causes the drop shadow to be an <dfn local-lt="outer shadow">outer box-shadow</dfn>.
		That means, one that shadows the box onto the canvas, as if it were lifted above the canvas.

	<dt><dfn>inset</dfn>
	<dd>
		Causes the drop shadow to be an <dfn local-lt="inner shadow">inner box-shadow</dfn>.
		That means, one that shadows the canvas onto the box, as if the box were cut out
		of the canvas and shifted behind it.
	</dl>

	<p>See the section [[css-backgrounds-3#shadow-layers|“Layering, Layout, and
	Other Details”]] for how 'box-shadow-position' interacts with other
	comma-separated drop shadow properties to form each drop shadow
	layer.

<wpt>
	tentative/parsing/box-shadow-position-computed.html
	tentative/parsing/box-shadow-position-invalid.html
	tentative/parsing/box-shadow-position-valid.html
</wpt>

<h3 id="box-shadow" oldids="the-box-shadow">
Drop Shadows Shorthand: the 'box-shadow' property</h3>

	<pre class="propdef">
		Name: box-shadow
		Value: <<spread-shadow>>#
		Initial: none
		Applies to: all elements
		Inherited: no
		Percentages: N/A
		Computed value: see individual properties
		Animation type: see individual properties
	</pre>

	<p>The 'box-shadow' property attaches one or more drop-shadows to the box.
	The property accepts a comma-separated list of shadows,
	ordered front to back.

	<p>Each shadow is given as a <<spread-shadow>>,
	outlining the 'box-shadow-offset' defined by two <<length>> values, and optional values for the 'box-shadow-blur',
	'box-shadow-spread', 'box-shadow-color', and 'box-shadow-position'.
	Omitted lengths are ''0'';
	omitted colors default to ''transparent'' when the specified offset is ''box-shadow-offset/none''
	and to ''currentcolor'' otherwise.

	Note: To avoid ambiguities in parsing the different <<length>> values,
	the offset has to be specified as two <<length>> values, in opposite to the 'box-shadow-offset' property,
	where a single <<length>> value can be used to specify both offsets.

	<pre class=prod>
	<dfn><<spread-shadow>></dfn> = <<'box-shadow-color'>>? &amp;&amp; [ [ none | <<length>>{2} ] [ <<'box-shadow-blur'>> <<'box-shadow-spread'>>? ]? ] &amp;&amp; <<'box-shadow-position'>>?</pre>

	<div class="example">
		The example below demonstrates the effects of spread and blur on the shadow:
		<pre>
		width: <b>100px</b>; height: <b>100px</b>;
		border: <b>12px solid blue</b>; background-color: <b>orange</b>;
		border-top-left-radius: <b>60px 90px</b>;
		border-bottom-right-radius: <b>60px 90px</b>;
		box-shadow: <b>64px 64px 12px 40px rgba(0,0,0,0.4),
		            12px 12px 0px 8px rgba(0,0,0,0.4) inset</b>;
		</pre>
		<figure>
			<img src="images/spread-blur.png" width="251" height="244"
			     alt="The sample code above would create a 100px&times;100px orange box with a 12px blue border,
			          whose top right / bottom left corners are sharp and tob left / bottom right corners are elliptically curved.
			          Two shadows are created: an inner one, which due to its offset and spread creates a 20px-wide band of darker orange along the top and left sides of the box (curving to match the rounded top left border shape);
			          and an outer one, creating a 204px&times;204px gray duplicate of the shape seemingly behind the box,
			          offset 24px down and 24px to the right of the box's top and left edges.
			          Applying the 12px blur radius to the outer shadow creates a gradual shift from the shadow color to transparent along its edges
			          which is visibly apparent for 24px centered along the edge of the shadow."
			>
		</figure>
	</div>

<h4 id="shadow-shape">
Shadow Shape, Spread, and Knockout</h4>

	An [=outer box-shadow=] casts a shadow
	as if the border-box of the element were opaque.
	Assuming a spread distance of zero, its perimeter has
	the exact same size and shape as the border box.
	The shadow is drawn outside the border edge only:
	it is clipped inside the border-box of the element.

	An [=inner box-shadow=] casts a shadow
	as if everything outside the padding edge were opaque.
	Assuming a spread distance of zero, its perimeter has
	the exact same size and shape as the padding box.
	The shadow is drawn inside the padding edge only:
	it is clipped outside the padding box of the element.

	If a [=spread distance=] is defined,
	the shadow perimeter defined above
	is expanded outward (for [=outer box-shadows=])
	or contracted inward (for [=inner box-shadows=])
	by outsetting (insetting, for inner shadows)
	the shadow's straight edges by the [=spread distance=]
	(and flooring the resulting width/height at zero).

	<div class="example">
		Below are some examples of an orange box with a blue border
		being given a drop shadow.

		<table class="data" id="box-shadow-samples">
			<tr>
				<th scope="rowgroup">
					<pre><code>
					border:5px solid blue;
					background-color:orange;
					width: 144px;
					height: 144px;
					</code></pre>
				<th>
					<pre><code>border-radius: 20px;</code></pre>
				<th>
					<pre><code>border-radius: 0;</code></pre>
			<tr>
				<th>
					<pre><code>
					box-shadow:
					  rgba(0,0,0,0.4)
					  10px 10px;
					</code></pre>
				<td>
					<img src="images/shadow-outer-round.png" width="175" height="175"
					     alt="A round-cornered box with a light gray shadow the same shape
					          as the border box offset 10px to the right and 10px down
					          from directly underneath the box."
					>
				<td>
					<img src="images/shadow-outer-square.png" width="175" height="175"
					     alt="A square-cornered box with a light gray shadow the same shape
					          as the border box offset 10px to the right and 10px down
					          from directly underneath the box."
					>
			<tr>
				<th>
					<pre><code>
					box-shadow:
					  rgba(0,0,0,0.4)
					  10px 10px
					  inset
					</code></pre>
				<td>
					<img src="images/shadow-inner-round.png" width="175" height="175"
					     alt="A round-cornered box with a light gray shadow the inverse shape
					          of the padding box filling 10px in from the top and left edges
					          (just inside the border)."
					>
				<td>
					<img src="images/shadow-inner-square.png" width="175" height="175"
					     alt="A square-cornered box with a light gray shadow the inverse shape
					          of the padding box filling 10px in from the top and left edges
					          (just inside the border)."
					>
			<tr>
				<th>
					<pre><code>
					box-shadow:
					  rgba(0,0,0,0.4)
					  10px 10px 0
					  10px /* spread */
					</code></pre>
				<td>
					<img src="images/shadow-outer-spread-round.png" width="175" height="175"
					     alt="A round-cornered box with a light gray shadow the same shape
					          as the box but 20px taller and wider and offset so that the
					          top and left edges of the shadow are directly underneath the
					          top and left edges of the box."
					>
				<td>
					<img src="images/shadow-outer-spread-square.png" width="175" height="175"
					     alt="A square-cornered box with a light gray shadow the same shape
					          as the box but 20px taller and wider and offset so that the
					          top and left edges of the shadow are directly underneath the
					          top and left edges of the box."
					>
			<tr>
				<th>
					<pre><code>
					box-shadow:
					  rgba(0,0,0,0.4)
					  10px 10px 0
					  10px /* spread */
					  inset
					</code></pre>
				<td>
					<img src="images/shadow-inner-spread-round.png" width="175" height="175"
					     alt="A round-cornered box with a light gray shadow the inverse shape
					          of the box but 20px narrower and shorter filling 20px in from
					          the top and left edges (just inside the border)."
					>
				<td>
					<img src="images/shadow-inner-spread-square.png" width="175" height="175"
					     alt="A round-cornered box with a light gray shadow the inverse shape
					          of the box but 20px narrower and shorter filling 20px in from
					          the top and left edges (just inside the border)."
					>
		</table>
	</div>

	To preserve the box's shape when spread is applied,
	the corner radii of the shadow are also increased (decreased, for inner shadows)
	from the border-box (padding-box) radii by adding (subtracting)
	the [=spread distance=] (and flooring at zero).
	For outer shadows, the [=border radius=] is then [=outset-adjusted border radius|adjusted=], independently in each dimension,
	to preserve the sharpness of rounded corners.

	The 'border-image' does not affect the shape of the box-shadow.

<h4 id="shadow-blur">
Blurring Shadow Edges</h4>

	A non-zero [=blur radius=] indicates
	that the resulting shadow should be blurred,
	such as by a Gaussian filter.
	The exact algorithm is not defined;
	however the resulting shadow must approximate
	(with each pixel being within 5% of its expected value)
	the image that would be generated by applying to the shadow
	a Gaussian blur with a standard deviation equal to half the blur radius.

	Note: This means for a long, straight shadow edge,
	the blur radius will create a visibly apparent color transition
	approximately the twice length of the blur radius
	that is perpendicular to and centered on the shadow's edge,
	and that ranges
	from almost the full shadow color at the endpoint inside the shadow
	to almost fully transparent at the endpoint outside it.

<h3 id="shadow-layers">
Layering, Layout, and Other Details</h3>

	Drop shadows are declared in the [=coordinated value list=]
	constructed from the 'box-shadow-*' properties,
	which form a [=coordinating list property group=]
	with 'box-shadow-offset' as the [=coordinating list base property=].
	See [[css-values-4#linked-properties]].

	The shadow effects are applied front-to-back:
	the first shadow is on top and the others are layered behind.
	Shadows do not influence layout and may overlap (or be overlapped by)
	other boxes and text or their shadows.
	In terms of stacking contexts and the painting order,
	the <i>outer box-shadows</i> of an element are drawn immediately below the background of that element,
	and the <i>inner shadows</i> of an element are drawn immediately above the background of that element
	(below the borders and border image, if any).

	Unless otherwise specified, drop shadows are only applied to the [=principal box=].
	If the affected box has multiple fragments,
	the shadows are applied as specified in 'box-decoration-break'.

	Shadows do not trigger scrolling or increase the size of the scrollable area.

	Outer shadows have no effect on internal table elements in the collapsing border model.
	If a shadow is defined for single border edge in the collapsing border model
	that has multiple border thicknesses
	(e.g. an outer shadow on a table where one row has thicker borders than the others,
	or an inner shadow on a rowspanning table cell that adjoins cells with different border thicknesses),
	the exact position and rendering of its shadows are undefined.

<h2 id="border-shape">
Border Shaping</h2>

	While 'corner-shape' and 'border-radius' allow some expressiveness to styling a border,
	they still work with the assumption that the border is rectangular.

	The 'border-shape' property augments these capabilities,
	by enabling the author to use any [=basic shape=] to specify the path of the border.

<h3 id="border-shape-func">
The 'border-shape' property</h3>

	<pre class="propdef">
		Name: border-shape
		Value: none | [ <<basic-shape>> <<geometry-box>>?]{1,2}
		Initial: none
		Applies to: all elements
		Inherited: no
		Percentages: see prose
		Computed value: list, each item a computed color
		Animation type: by computed value
	</pre>

	The 'border-shape' property defines custom shapes for element borders
	using one or two [=basic shape=] values.

<h3 id="border-shape-syntax">
Syntax and Usage Modes</h3>

	The 'border-shape' property accepts either a single <<basic-shape>> or two <<basic-shape>>s:

	: Single <<basic-shape>> (Stroke mode)
	:: The border is rendered as a stroke along the shape's path,
		with the stroke width determined by the
		[=relevant side for border shape|relevant side=]'s [=computed value|computed=] [=border width=].
		This mode is useful for creating outlined shapes.

	: Two <<basic-shape>>s (Fill mode)
	:: The border is rendered as the area between the two paths.
		The first shape defines the outer boundary,
		and the second shape defines the inner boundary.
		This mode provides precise control over the border region's geometry.
		The fill color of the border is the [=relevant side for border shape|relevant side=]'s [=computed value|computed=] 'border-color'.

<h3 id="border-shape-geometry-box">
Geometry Box References</h3>

	When a <<geometry-box>> is not explicitly provided,
	the default reference box depends on the number of <<basic-shape>> values:

	: Single <<basic-shape>>
	:: The <<geometry-box>> defaults to the ''half-border-box'' value,
		which positions the stroke to match the default border behavior,
		with the border extending equally inward and outward from the shape path.
	
	: Two <<basic-shape>>s
	:: The first (outer) shape defaults to the [=border box=],
		and the second (inner) shape defaults to the [=padding box=].
		This allows the 'border-width' properties to naturally affect the final shape.

<h3 id="border-shape-examples">
Examples</h3>

	<div class="example">
		Creating a circular border using stroke mode:

		<pre class=lang-css>
		.circular-button {
			width: 100px;
			height: 100px;
			border: 5px solid blue;
			border-shape: circle(50%);
		}
		</pre>

		This creates a circular border with a 5px stroke width.
	</div>

	<div class="example">
		Creating a diamond-shaped border using fill mode:

		<pre class=lang-css>
		.diamond {
			width: 200px;
			height: 200px;
			border: 10px solid crimson;
			border-shape:
				polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)
				polygon(50% 10%, 90% 50%, 50% 90%, 10% 50%);
		}
		</pre>

		This creates a diamond border by defining outer and inner polygons.
	</div>

	<div class="example">
		Using a custom path shape:

		<pre class=lang-css>
		.custom-shape {
			border: 8px solid green;
			border-shape: path('M 10,30 A 20,20 0,0,1 50,30 A 20,20 0,0,1 90,30 Q 90,60 50,90 Q 10,60 10,30 z');
		}
		</pre>

		This creates a heart-shaped border using an SVG path.
	</div>

	<div class="example">
		Combining 'border-shape' with different border widths:

		<pre class=lang-css>
		.fancy-box {
			width: 100px;
			height: 100px;
			border-top-width: 10px;
			border-right-width: 5px;
			border-bottom-width: 10px;
			border-left-width: 5px;
			border-style: solid;
			border-color: purple;
			border-shape: ellipse(50% 40%);
		}
		</pre>

		The [=relevant side for border shape=] determines which border width is used for the stroke.
	</div>

<h3 id="border-shape-interactions">
Interactions with Other Properties</h3>

<h4 id="border-shape-radius-interaction">
Interaction with 'border-radius' and 'corner-shape'</h4>

	The 'border-shape' property is not compatible with 'border-radius' and 'corner-shape'.
	When an element's [=computed value=] of 'border-shape' is not <css>none</css>,
	its 'border-radius' is ignored, as if it was set to 0.
	'corner-shape' is implicitly ignored, as it can only work in tandem with 'border-radius'.

	Note: Authors should use either 'border-shape' for custom shapes
	or 'border-radius'/'corner-shape' for rectangular boxes with styled corners,
	but not both simultaneously.

<h4 id="border-shape-shadow-interaction">
Interaction with 'box-shadow'</h4>

	An [=outer box-shadow=] is cast as if the shape defined by the outer path were opaque.
	An [=inner box-shadow=] is cast as if everything outside the shape defined by the inner path were opaque.
	For both inner and outer shadows, the shadow shape is expanded or contracted by the spread distance,
	blurred by the blur radius, and then clipped by the 'border-shape', adhering to the standard 'box-shadow' painting rules.

	<div class="example">
		<pre class=lang-css>
		.shaped-shadow {
			border-shape: circle(50%);
			box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
		}
		</pre>

		The shadow follows the circular shape rather than a rectangular box.
	</div>

<h4 id="border-shape-overflow-interaction">
Interaction with Overflow and Clipping</h4>

	The inner 'border-shape' clips the [=overflow=] content of the element,
	in the same manner as 'border-radius',
	as described in <a href="https://drafts.csswg.org/css-backgrounds-3/#corner-clipping">corner clipping</a>.

	Issue: how should this affect clipping replaced elements?

<h4 id="border-shape-layout-interaction">
Interaction with Layout</h4>

	'border-shape' does not affect geometry or layout,
	which is still computed using the existing 'border-width' properties.
	The shaped border is purely a visual effect.

	'border-shape' does not affect the flow of content inside the box.

	Note: An author can use 'border-shape' in tandem with 'shape-inside'
	to create effects that both decorate the box and control its text flow.

<h3 id="border-shape-relevant-side">
Determining the Relevant Side</h3>

	<div algorithm="choose-relevant-side-for-border-shape">
	An element's <dfn>relevant side for border shape</dfn> is the first side (in the order [=block-start=], [=inline-start=], [=block-end=], and [=inline-end=]) that has a non-''border-style/none'' [=border style=], or [=block-start=] if they're all ''border-style/none''.
		1. If |element|'s [=computed value|computed=] 'border-block-start-style' is not ''border-style/none'', then return [=block-start=].
		1. If |element|'s [=computed value|computed=] 'border-inline-start-style' is not ''border-style/none'', then return [=inline-start=].
		1. If |element|'s [=computed value|computed=] 'border-block-end-style' is not ''border-style/none'', then return [=block-end=].
		1. If |element|'s [=computed value|computed=] 'border-inline-end-style' is not ''border-style/none'', then return [=inline-end=].
		1. Return [=block-start=].
	</div>

	Note: This algorithm ensures consistent behavior when multiple border sides have different styles or widths.
	The first non-none border side (in logical order) determines the border characteristics
	used for the shaped border.


<wpt>
	tentative/border-shape/border-shape-clips-background.html
	tentative/border-shape/border-shape-double-shape-default.html
	tentative/border-shape/border-shape-inner-outer.html
	tentative/border-shape/border-shape-overflow.html
	tentative/border-shape/border-shape-shadow.html
	tentative/border-shape/border-shape-geometry-box.html
	tentative/border-shape/border-shape-half-border-box-default.html
	tentative/border-shape/border-shape-overflow-solid-background.html
	tentative/border-shape/border-shape-stroke-from-border.html
	tentative/border-shape/border-shape-stroke-invalidation.html
	tentative/parsing/border-shape-computed.html
	tentative/parsing/border-shape-invalid.html
	tentative/parsing/border-shape-valid.html
</wpt>

<h2 class=no-num id=privacy>Privacy Considerations</h2>

No new privacy considerations have been reported on this specification.

<h2 class=no-num id=security>Security Considerations</h2>

No new security considerations have been reported on this specification.

<h2 class=no-num id="changes">
Changes</h2>

<h3 class=no-num id="changes-20250722">
Changes since the <a href="https://www.w3.org/TR/2025/WD-css-borders-4-20250722/">
First Public Working Draft</a> of 22 July 2025
</h3>

	* Added 'corner-*' shorthands
	* Renamed <code>corners</code> to 'corner'
	* Added Web Platform Tests coverage
	* Incorporated full text of [[CSS3BG]] related to borders and shadows
	* Renamed 'border-clip-*' properties to 'border-*-clip' and added logical longhands and shorthands
	* Renamed <css>normal</css> value of 'border-*-clip' properties to ''border-top-clip/none''
	* Added new syntax for 'border-*-*-radius' longhands using a slash to separate horizontal and vertical radii
	* Allowed a single <<length>> value for 'box-shadow-offset' to set both offsets to the same value
	* Changed the special case of 'border-width' having a value of ''0'' when 'border-style' is ''border-style/none'' or ''border-style/hidden''
		from a computed-value effect to a resolved-value effect.
		(<a href="https://github.com/w3c/csswg-drafts/issues/11494">Issue 11494</a>)

<h3 class=no-num id="level-changes">
Additions since [[CSS3BG]]</h3>

	* <<image-1D>> as value for 'border-color' and its longhands
	* Added physical and logical 'border-*-radius' shorthands
	* Added 'corner-shape' and 'corner-*-shape' shorthands, plus related 'corner' and 'corner-*' shorthands
	* Added 'border-shape'
	* Added <a href="#partial-borders">partial borders</a> via 'border-limit' and 'border-*-clip' properties
	* Added 'box-shadow-*' longhands and turned 'box-shadow' into a shorthand
	* Moved logical border properties from [[CSS-LOGICAL-1]] to this spec.

<h2 class=no-num id="acknowledgments">
Acknowledgments</h2>

	<p>In addition to the many contributors to the [[CSS1]], [[CSS2]],
	and [[CSS3BG]] predecessors to this module,
	the editors would like to thank
	Tab Atkins,
	Noam Rosenthal,
	Håkon Wium Lie,
	Oriol Brufau,
	and Guillaume Lebas
	for their suggestions and feedback specifically for this Level 4.
