You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
While 'corner-shape' and 'border-radius' allow some expressiveness to styling a border,
3149
3149
they still work with the assumption that the border is rectangular.
3150
3150
3151
-
The 'border-shape'function augments these capabilities,
3151
+
The 'border-shape'property augments these capabilities,
3152
3152
by enabling the author to use any [=basic shape=] to specify the path of the border.
3153
3153
3154
3154
<h3 id="border-shape-func">
@@ -3165,49 +3165,181 @@ The 'border-shape' property</h3>
3165
3165
Animation type: by computed value
3166
3166
</pre>
3167
3167
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.
3170
3170
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>
3174
3173
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:
3176
3175
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.
3178
3181
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'.
3181
3188
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>
3183
3191
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:
3188
3194
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.
3191
3204
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>
3194
3207
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:
3197
3210
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>
3200
3219
3201
-
Issue: how should this affect clipping replaced elements?
3220
+
This creates a circular border with a 5px stroke width.
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.
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
0 commit comments