Get Ready For the Powerful CSS border-shape Property!
shape() and corner-shape
The shape() function is a new value for clip-path and offset-path that uses SVG syntax to create CSS shapes much more easily than, say, path(). I wrote a four-article series exploring this feature, and another article where I explore the creation of complex shapes. Speaking about SVG, you can express any SVG shape using shape(). Said differently, you can convert any SVG shape into a CSS shape and, guess what, I made a converter that does exactly that!
As far as corner-shape goes, itās a property that works in conjunction with border-radius. As its name suggests, it allows you to control the shape of an elementās corner using predefined keywords.
.corner {
border-radius: 20px;
corner-shape: round | scoop | bevel | notch | squircle;
}
It can also be used to create common CSS shapes, like I get into in another article, āCSS Shapes using corner-shape.ā
But is the corner-shape property really useful or even needed? Except for the squircle value, most of the shapes can already be created using clip-path or mask. But what corner-shape does that these others canāt is easily add borders and other decorations to those shapes! corner-shape will not only shape the corners, but it also supports other properties like border and box-shadow, allowing them to follow the shape rather than the elementās box. This is a game-changer because we all know that adding borders to shapes is a nightmare.
Support is still not great (Chromium-only as Iām writing this), but itās a good time to explore it and get an overview of its potential.
border-shape!
Shaping corners is good, but itās still fairly limited as far as what we can do with it. Like, what about shaping the whole element instead? Thatās what border-shape will do. It accepts the same values as clip-path, including the new shape() function.
So, it has the same job as clip-path? Whatās new? Like with corner-shape, most decorative properties such as border, box-shadow, and outline follow the shape. clip-path (and mask) will clip/mask the whole element, including the decorations, so having borders is a big NO. Thatās a major problem for creating CSS shapes.
The border-shape property is here to solve this issue. Instead of clipping the element, it āshapesā the element, allowing its decorations to follow that shape. In other words, putting borders on CSS shapes will become childās play! Not to mention that border-shape is also very easy to use. If you are familiar with clip-path, then you practically have nothing new to learn. Simply replace one property with another, and you are done.
.shape {
/* Old code */
clip-path: shape() | polygon() | ...;
/* New code */
border-shape: shape() | polygon() | ...;
}
I invite you again to learn more about the shape() function because itās the value that makes border-shape really powerful. The two really go hand-in-hand.
Now that you know the basic use of the property, shall we start the fun stuff? I am here to push the limits and show you what is possible using border-shape.
Note: Support is limited to Chrome-only for now so check out the next demos using Chrome.
Border-Only Shapes
As I said, the first major advantage here is adding borders to shapes that follow the actual shape, which also means the ability to create border-only shapes. All you have to do is write the following code:
.shape {
border: 8px solid red;
border-shape: /* your shape code */;
}
No more hacks and no more headaches! Most of the shapes are already available in my CSS Shapes collection, so really, making border-only shapes is something you can do with a simple copy/paste. Even some of my online generators are already configured to provide border-only versions of complex shapes, like blobs, wavy lines, and fancy frames, among many, many others.
Cutout Shapes
Letās take the previous code and update it as follows:
.shape {
border: 8px solid red;
border-shape: inset(0) /* your shape code */;
}
You keep the shape code you had, and you add inset(0) at the beginning. Yes, you can have two shape values inside border-shape and the result will be as follows:
From the specification: The border-shape property accepts either a single or two <shape>s:
- Single (Stroke mode): The border is rendered as a stroke along the shapeās path, with the stroke width determined by the relevant sideās computed border width. This mode is useful for creating outlined shapes.
- Two
<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.
Using a basic rectangle as the outer shape (inset(0)), I was able to easily transform the border-only version into a cutout version! Do you want the shape inside a circle? Easy! All I did is replace inset(0) (a rectangle) with circle() (a circle).
But we can do this with a simple border-radius: 50%, right? No! When working with border-shape, the border-radius is ignored, which is kind of logical since we no longer have corners to round - the element is now shaped. This is not a big deal since we can literally create any kind of shape that replaces the use of border-radius, as shown in the previous example.
Note: If you are wondering why I am using circle() without any argument, check out my article āCSS Functions that work without arguments.ā
Here are a few more examples with the two shapes value to look at before we move to the next part: You can literally use any combination to get complex-looking shapes without a bunch of effort!
Breakout Decorations
Now letās take a block of text and apply the previous code with the two shape values:
.box {
border-shape: inset(0) circle();
border-color: pink;
}
Perhaps this is nothing surprising considering what we have learned so far. We define two shapes and the border is drawn inside the area between them. Whatās new here is that we are dealing with content and, as you can see, it overlaps the border. border-shape shapes the whole element, including the elementās decoration, but any content inside remains unchanged and follows the initial rectangle shape. Thatās not new behavior since the same happens even with classic border-radius. And the content will overflow unless we decide to hide it using overflow: hidden. In this case, I wonāt consider the overflow property as I want the content to overflow and be placed on top of the border decoration.
Now letās update the code of the shape like this:
.box {
border-shape: inset(0 -100px) circle(50px);
border-color: pink;
}
I made the circle smaller and the rectangle bigger. Do you see where I am going? By making the radius of the circle 0 and the rectangle bigger, I create a breakout background effect!
.box {
border-shape: inset(0 -100vw) circle(0);
border-color: pink;
}
The element remains centered, but its background (that we are simulating using a border!) extends to the edge of the screen. And this is not limited to using two shape values. Even with the one shape value, we can achieve a breakout decoration (which is typically difficult) if you consider any value that gets you out of the elementās boundary.
Partial Decorations
Letās piggy-back off that last demo to try different decorations. This time, instead of extending outside the element boundary, I am staying within it to create partial decoration. In other words, we no longer have boundaries. border-shape has no limit. The only limit is your imagination!
I am mainly relying on the shape() function to create the decoration, so do yourself a favor and explore this feature by reading my four-article series! If you master shape(), you can easily produce complex decorations using border-shape.
Shape Animation
Yes, border-shape can be animated, and we can have different kinds of animations. With the two-value syntax, we can animate the border-width value to create a reveal effect. Cool, right? We can also apply this to image elements as well.
We can also animate the shape values to create more complex animations. Here is a demo of a bouncing hover effect applied to blob shapes (from my article āMaking Complex CSS Shapes Using shape()ā). I take the same code, replace clip-path with border-shape, and tada! And why not add a subtle animation to those previous decorations?
Want More? Letās Go!
Here is a hand-drawn underline that slides between the menu items on hover. Straight lines are boring! And why not an electric frame around your content? Donāt worry, itās safe for touch screens. What about a fancy border-only loader? (code taken from my squishy loader collection) Letās connect circles with a straight line that bends when the circles get closer and stretches when they get farther.
Conclusion
I think itās clear now why I am calling this new property āpowerful.ā In addition to making it easy to create CSS shapes, it lets us add fancy decorations, cool animations, and more! I didnāt go into fine detail with most of the demos as I wanted to keep this a light article showing the potential of border-shape. Now that you know we can create crazy stuff with it, stay tuned for more elaborate articles!
Donāt forget to bookmark my CSS Shapes collection and my online generators. I have already updated many of the shapes using shape(), and I am in the process of also including the border-shape version.
Comments
No comments yet. Start the discussion.