Skip to content

Commit 9d10089

Browse files
Brush the border shape property spec text (#13361)
Add some structuring, some examples, improve wording.
1 parent 01d8bb0 commit 9d10089

1 file changed

Lines changed: 164 additions & 32 deletions

File tree

css-borders-4/Overview.bs

Lines changed: 164 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3148,7 +3148,7 @@ Border Shaping</h2>
31483148
While 'corner-shape' and 'border-radius' allow some expressiveness to styling a border,
31493149
they still work with the assumption that the border is rectangular.
31503150

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

31543154
<h3 id="border-shape-func">
@@ -3165,49 +3165,181 @@ The 'border-shape' property</h3>
31653165
Animation type: by computed value
31663166
</pre>
31673167

3168-
The 'border-shape' property is provided with either a single <<basic-shape>> or two <<basic-shape>>s,
3169-
resulting in one or two paths, respectively.
3168+
The 'border-shape' property defines custom shapes for element borders
3169+
using one or two [=basic shape=] values.
31703170

3171-
When two <<basic-shape>> values are given, the border is rendered as the shape between the two paths.
3172-
When only a single <<basic-shape>> is given, the border is rendered as a stroke with the
3173-
[=relevant side for border shape|relevant side=]'s [=computed value|computed=] [=border width=] as the stroke width.
3171+
<h3 id="border-shape-syntax">
3172+
Syntax and Usage Modes</h3>
31743173

3175-
The fill color of the border is the [=relevant side for border shape|relevant side=]'s [=computed value|computed=]'border-color'.
3174+
The 'border-shape' property accepts either a single <<basic-shape>> or two <<basic-shape>>s:
31763175

3177-
When a <<geometry-box>> is not given, the default computation of percentage differs based on the number of given <<basic-shape>> values.
3176+
: Single <<basic-shape>> (Stroke mode)
3177+
:: The border is rendered as a stroke along the shape's path,
3178+
with the stroke width determined by the
3179+
[=relevant side for border shape|relevant side=]'s [=computed value|computed=] [=border width=].
3180+
This mode is useful for creating outlined shapes.
31783181

3179-
When two <<basic-shape>> values are given, the first (outer) one defaults to the [=border box=] and the second (inner) one defaults to the [=padding box=].
3180-
This allows using the different 'border-width' properties to affect the final shape.
3182+
: Two <<basic-shape>>s (Fill mode)
3183+
:: The border is rendered as the area between the two paths.
3184+
The first shape defines the outer boundary,
3185+
and the second shape defines the inner boundary.
3186+
This mode provides precise control over the border region's geometry.
3187+
The fill color of the border is the [=relevant side for border shape|relevant side=]'s [=computed value|computed=] 'border-color'.
31813188

3182-
When a single <<basic-shape>> value is given, the <<geometry-box>> defaults to the ''half-border-box'' value, which allows stroking in a way that matches the default border behavior.
3189+
<h3 id="border-shape-geometry-box">
3190+
Geometry Box References</h3>
31833191

3184-
The 'border-shape' property is not compatible with 'border-radius' and 'corner-shape'.
3185-
When an element's [=computed value=] of 'border-shape' is not <css>none</css>,
3186-
its 'border-radius' is ignored, as if it was set to 0.
3187-
'corner-shape' is implicitly ignored, as it can only work in tandem with 'border-radius'.
3192+
When a <<geometry-box>> is not explicitly provided,
3193+
the default reference box depends on the number of <<basic-shape>> values:
31883194

3189-
An [=outer box-shadow=] follows the outside of the outer path, and an [=inner box-shadow=] follows the inside inner path.
3190-
Both are rendered as a stroke, with a stroke width of <code>spread * 2</code>, clipped by the border shape.
3195+
: Single <<basic-shape>>
3196+
:: The <<geometry-box>> defaults to the ''half-border-box'' value,
3197+
which positions the stroke to match the default border behavior,
3198+
with the border extending equally inward and outward from the shape path.
3199+
3200+
: Two <<basic-shape>>s
3201+
:: The first (outer) shape defaults to the [=border box=],
3202+
and the second (inner) shape defaults to the [=padding box=].
3203+
This allows the 'border-width' properties to naturally affect the final shape.
31913204

3192-
'border-shape' does not affect geometry or layout,
3193-
which is still computed using the existing 'border-width' properties.
3205+
<h3 id="border-shape-examples">
3206+
Examples</h3>
31943207

3195-
'border-shape' does not affect the flow of content inside the box.
3196-
Note: An author can use 'border-shape' in tandem with 'shape-inside' to create effects that decorate the box and control its text flow at the same time.
3208+
<div class="example">
3209+
Creating a circular border using stroke mode:
31973210

3198-
The inner 'border-shape' clips the [=overflow=] content of the element, in the same manner as 'border-radius',
3199-
as described in <a href="https://drafts.csswg.org/css-backgrounds-3/#corner-clipping">corner clipping</a>.
3211+
<pre class=lang-css>
3212+
.circular-button {
3213+
width: 100px;
3214+
height: 100px;
3215+
border: 5px solid blue;
3216+
border-shape: circle(50%);
3217+
}
3218+
</pre>
32003219

3201-
Issue: how should this affect clipping replaced elements?
3220+
This creates a circular border with a 5px stroke width.
3221+
</div>
32023222

3203-
<div algorithm="choose-relevant-side-for-border-shape">
3204-
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''.
3205-
1. If |element|'s [=computed value|computed=] 'border-block-start-style' is not ''border-style/none'', then return [=block-start=].
3206-
1. If |element|'s [=computed value|computed=] 'border-inline-start-style' is not ''border-style/none'', then return [=inline-start=].
3207-
1. If |element|'s [=computed value|computed=] 'border-block-end-style' is not ''border-style/none'', then return [=block-end=].
3208-
1. If |element|'s [=computed value|computed=] 'border-inline-end-style' is not ''border-style/none'', then return [=inline-end=].
3209-
1. Return [=block-start=].
3210-
</div>
3223+
<div class="example">
3224+
Creating a diamond-shaped border using fill mode:
3225+
3226+
<pre class=lang-css>
3227+
.diamond {
3228+
width: 200px;
3229+
height: 200px;
3230+
border: 10px solid crimson;
3231+
border-shape:
3232+
polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%)
3233+
polygon(50% 10%, 90% 50%, 50% 90%, 10% 50%);
3234+
}
3235+
</pre>
3236+
3237+
This creates a diamond border by defining outer and inner polygons.
3238+
</div>
3239+
3240+
<div class="example">
3241+
Using a custom path shape:
3242+
3243+
<pre class=lang-css>
3244+
.custom-shape {
3245+
border: 8px solid green;
3246+
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');
3247+
}
3248+
</pre>
3249+
3250+
This creates a heart-shaped border using an SVG path.
3251+
</div>
3252+
3253+
<div class="example">
3254+
Combining 'border-shape' with different border widths:
3255+
3256+
<pre class=lang-css>
3257+
.fancy-box {
3258+
width: 100px;
3259+
height: 100px;
3260+
border-top-width: 10px;
3261+
border-right-width: 5px;
3262+
border-bottom-width: 10px;
3263+
border-left-width: 5px;
3264+
border-style: solid;
3265+
border-color: purple;
3266+
border-shape: ellipse(50% 40%);
3267+
}
3268+
</pre>
3269+
3270+
The [=relevant side for border shape=] determines which border width is used for the stroke.
3271+
</div>
3272+
3273+
<h3 id="border-shape-interactions">
3274+
Interactions with Other Properties</h3>
3275+
3276+
<h4 id="border-shape-radius-interaction">
3277+
Interaction with 'border-radius' and 'corner-shape'</h4>
3278+
3279+
The 'border-shape' property is not compatible with 'border-radius' and 'corner-shape'.
3280+
When an element's [=computed value=] of 'border-shape' is not <css>none</css>,
3281+
its 'border-radius' is ignored, as if it was set to 0.
3282+
'corner-shape' is implicitly ignored, as it can only work in tandem with 'border-radius'.
3283+
3284+
Note: Authors should use either 'border-shape' for custom shapes
3285+
or 'border-radius'/'corner-shape' for rectangular boxes with styled corners,
3286+
but not both simultaneously.
3287+
3288+
<h4 id="border-shape-shadow-interaction">
3289+
Interaction with 'box-shadow'</h4>
3290+
3291+
An [=outer box-shadow=] follows the outside of the outer path,
3292+
and an [=inner box-shadow=] follows the inside of the inner path.
3293+
Both are rendered as a stroke, with a stroke width of <code>spread * 2</code>,
3294+
clipped by the border shape.
3295+
3296+
<div class="example">
3297+
<pre class=lang-css>
3298+
.shaped-shadow {
3299+
border-shape: circle(50%);
3300+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3);
3301+
}
3302+
</pre>
3303+
3304+
The shadow follows the circular shape rather than a rectangular box.
3305+
</div>
3306+
3307+
<h4 id="border-shape-overflow-interaction">
3308+
Interaction with Overflow and Clipping</h4>
3309+
3310+
The inner 'border-shape' clips the [=overflow=] content of the element,
3311+
in the same manner as 'border-radius',
3312+
as described in <a href="https://drafts.csswg.org/css-backgrounds-3/#corner-clipping">corner clipping</a>.
3313+
3314+
Issue: how should this affect clipping replaced elements?
3315+
3316+
<h4 id="border-shape-layout-interaction">
3317+
Interaction with Layout</h4>
3318+
3319+
'border-shape' does not affect geometry or layout,
3320+
which is still computed using the existing 'border-width' properties.
3321+
The shaped border is purely a visual effect.
3322+
3323+
'border-shape' does not affect the flow of content inside the box.
3324+
3325+
Note: An author can use 'border-shape' in tandem with 'shape-inside'
3326+
to create effects that both decorate the box and control its text flow.
3327+
3328+
<h3 id="border-shape-relevant-side">
3329+
Determining the Relevant Side</h3>
3330+
3331+
<div algorithm="choose-relevant-side-for-border-shape">
3332+
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''.
3333+
1. If |element|'s [=computed value|computed=] 'border-block-start-style' is not ''border-style/none'', then return [=block-start=].
3334+
1. If |element|'s [=computed value|computed=] 'border-inline-start-style' is not ''border-style/none'', then return [=inline-start=].
3335+
1. If |element|'s [=computed value|computed=] 'border-block-end-style' is not ''border-style/none'', then return [=block-end=].
3336+
1. If |element|'s [=computed value|computed=] 'border-inline-end-style' is not ''border-style/none'', then return [=inline-end=].
3337+
1. Return [=block-start=].
3338+
</div>
3339+
3340+
Note: This algorithm ensures consistent behavior when multiple border sides have different styles or widths.
3341+
The first non-none border side (in logical order) determines the border characteristics
3342+
used for the shaped border.
32113343

32123344

32133345
<wpt>

0 commit comments

Comments
 (0)