Editor’s note: This tutorial was updated by Shalitha Suranga on 12 June 2024 to add information related to new CSS techniques, include recommendations around responsive corner designs, update browser compatibility information, add examples using different CSS layout techniques, and more.
Nowadays, popular web browsers implement various standard CSS properties to adjust HTML element shapes according to your design requirements. We can create stylish, pixel-perfect corners using these CSS features.
In this tutorial, we’ll first demonstrate how to create rounded corners and then show how you can apply these concepts to create your own corner designs — what I like to call fancy corners.
With a just few lines of CSS code, you can easily beautify the corners of HTML elements and create stunning visuals for users to interact with:
To start, let’s create a simple box centered in the <body>
so we can experiment with its corners:
<body> <div></div> </body> <style> body { margin: 0px; display: flex; height: 100vh; align-items: center; justify-content: center; background-color: #e7d39f; } div { width: 200px; height: 80px; background-color: #522d5b; } </style>
Right now, our box looks like this:
Now we’ll use this box as a model to build five types of fancy corners: rounded, elliptical, notched, scooped, and inverted. Let’s get started!
border-radius
is the fundamental CSS property to create rounded corners. You may have already used it. Here’s an overview of the property:
/* sets radius of all 4 corners */ border-radius: 10px; /* top-left top-right bottom-right bottom-left */ border-radius: 10px 15px 15px 10px;
You can use border-radius
for the above box element to create rounded corners like so:
div { border-radius: 15px; }
Our updated box with rounded corners looks like this:
You can also set different values for each corner with various length units of your choice, as shown in the following example:
div { border-radius: 2em 20px 2.5em 0.2in; }
This allows you to customize the rounded corners with CSS as needed:
If you only want one corner to be rounded, for example, you can set one of the following constituent properties.
div { border-top-left-radius: 15px; /* or border-top-right-radius: 15px; border-bottom-right-radius: 15px; border-bottom-left-radius: 15px; */ }
Here’s the result of the code above:
What about a circle? User avatars, for instance, are often displayed within circles. You’ll first need to create a square to make a perfect circle. Then, you can increase the border radius of all corners as follows:
div { width: 100px; /* overriding previous width/height values */ height: 100px; border-radius: 50%; /* here's the trick */ }
As a result, you get a perfect circle:
When we use a single value point for border-radius properties, we’ll typically get rounded corners. Using a single value for border-radius properties applies the same radius value for each corner’s x- and y-axis. As a result, we’ll get circular-rounded corners.
What if you need to make your corners elliptical? Shaping your corners like part of an ellipse instead of a circle allows you to get a bit more creative and complex with your CSS designs.
The %
unit generates elliptical corners only for rectangles, but it doesn’t offer much control over creating elliptical corners style on any rectangular shape including squares. Every border-radius constituent property of a specific corner also accepts two values for specifying x-y axis radiuses.
The following CSS code makes the top left corner elliptical:
div { border-top-left-radius: 20px 60px; }
You can see the result below:
You can create elliptical corners with the border-radius
property by passing the x and y radius values using the /
character. For example, the following CSS code uses the same elliptical corner setup for all corners using the shorthand syntax:
div { border-radius: 50px / 20%; /* expands to: border-top-left-radius: 50px 20%; border-top-right-radius: 50px 20%; border-bottom-right-radius: 50px 20%; border-bottom-left-radius: 50px 20%; */ }
This will give you a box with four matching elliptical corners:
You can also set different elliptical arcs for all corners using border-radius
as follows:
div { border-radius: 60px 40px 20px 10px / 21px 49px 27px 7px; }
The result of this code will look like the below:
The Fancy Border Radius web app lets you generate CSS code for elliptical corners by adjusting borders visually.
Going beyond the border-radius
property, you can utilize :before
and :after
pseudo-elements to create corners by rendering a second element along with the original parent element. The box-shadow
property helps us to create different types of corners with these pseudo-elements.
When using this method, you can only change one or two sides of the box. You’ll see why.
Here’s the CSS of the box:
div { position: relative; width: 200px; height: 80px; background-color: #522d5b; }
Next, use the :before
pseudo-element to create a border. We need to use :before
instead of :after
to avoid layout issues after adding content:
div:before { content: ""; position: absolute; margin: -20px; width: 40px; height: 40px; transform: rotate(45deg); background-color: black; }
Here, we set the sub-element color to black
just to see where it is during the notched corner designing process. The sub-element looks as follows:
Set overflow:hidden
on the box to hide the overflowed parts of its child elements.
div { /* other styles */ overflow: hidden; }
Now for the most interesting part — using box-shadow
to fill the background:
div:before { /* other styles */ box-shadow: 0 0 0 250px #522d5b; }
Here, we created a large shadow around the pseudo-element without any blur effect (which is set using the third 0
parameter), so we get an enlarged copy of the element around it. Thanks to the overflow:hidden
in the box, anything outside of it is hidden. You should get something like this:
Finally, remove the background colors from the box and the pseudo-element. The shadow color is set in the box-shadow
property (#522d5b
in our case) covers the the box element area and gets rendered as the background layer of the box, as shown in the following preview:
You can use both :before
and :after
pseudo-elements to style two corners, but it generates a bit of complex CSS, so this method is great for creating only one notched corner. How do you notch all four corners? There are two methods:
clip-path
property to create a border by drawing a clipping regionclip-path
The clip-path
property determines what region to show in an element. You can use it with the polygon()
function to create a notched corner (or anything else with complex values). Let’s apply this to our rectangle from before:
div { position: relative; width: 200px; height: 80px; overflow: hidden; background-color: #522d5b; clip-path: polygon( 0 20%, 10% 0, 90% 0, 100% 20%, 100% 80%, 90% 100%, 10% 100%, 0% 80% ) }
Here’s the resulting box with four notched corners:
You can use the following polygon definition to create notched corners only for two diagonal vertices of the box:
polygon( 0 20%, 10% 0, 100% 0, 100% 80%, 90% 100%, 0% 100% )
Here’s how the box with two notched corners should look:
Instead of repeating the same percentages, you can either use CSS variables or SCSS variables.
Creating scooped corners is similar to creating notched corners. Instead of using a rotated square as the pseudo-element, you can use a circle:
div:before { content: ""; position: absolute; margin: -20px; width: 40px; height: 40px; border-radius: 50%; /* new */ box-shadow: 0 0 0 250px #522d5b; }
Here’s our box with one scooped corner:
If you need to scoop all four corners, you can use the new CSS mask
property (baseline 2023 support) and the radial-gradient()
function, as shown in the following example:
div { position: relative; width: 200px; height: 80px; background-color: #522d5b; mask: radial-gradient(20px at 40px 40px, transparent 98%, black) -40px -40px; }
Here, the gradient function creates a transparent circle on a black background. Then we used the -40px -40px
mask positioning to push the generated circle to the top-left corner to equally distribute the gradient circle area to all four corners. As a result, we get scooped corners on all corners:
You can adjust the above positioning and sizing values and generate different scooped corners as follows:
mask: radial-gradient(14px at 40px 40px, transparent 98%, black) -33px -36px
The resulting box has four irregularly scooped corners, like so:
You can generate scooped corners CSS code by using the custom corner generator web app.
You can use the same method again to create inverted corners, with a few tweaks.
To create the box:
div { position: relative; width: 200px; height: 80px; background: #522d5b; }
To create the pseudo-element:
div:before { content: ""; position: absolute; top: -40px; left: 0; height: 40px; width: 40px; border-bottom-left-radius: 50%; background-color: black; }
This will give us the following:
The next step is to fill the small part between the pseudo-element and remove the background color. We can use the box-shadow
property to do that:
div:before { box-shadow: 0 20px 0 0 #522d5b; }
In box-shadow
, we set x
, spread
, and blur
to zero and y
to 20px
(half of the height). Therefore, the box shadow region covers the small empty region between the box and the pseudo-element element. The inverted corner looks as follows after removing the background color of the pseudo-element:
This type of design is perfect for speech bubbles. Look at the following sample — first, the HTML:
<div>I'm a speech bubble!</div>
Next, the CSS:
div { position: relative; display: flex; align-items: center; justify-content: center; width: 200px; height: 80px; background: #522d5b; border-radius: 0 15px 15px 15px; color: white; }
The above code snippet uses the CSS Flexbox feature to center the speech bubble content. Here, we used align-items: center
and justify-content: center
to place speech bubble text in the middle of the box element:
Let’s create another speech bubble that uses a flexbox with two columns. Here’s the HTML:
<div> <img src="https://placehold.co/80"> <span>I'm a speech bubble!</span> </div>
And here’s the CSS:
img { border-radius: 15px; scale: 0.72; }
The result of the code above should look like this:
For complex speech bubble layouts, you can also use CSS grids.
Users may access your web app or website using various device types, so you should implement responsive design techniques to support different viewport sizes. Besides, we need to enhance the accessibility factors of our web pages to let everyone use them productively.
Consider the following recommendations for improving responsive and accessibility factors when you use fancy corners:
clamp()
functionAs you can see, it’s possible to create all kinds of interesting corners — from simple rounded ones to snazzy, random designs — using nothing more than border-radius
, box-shadow
, mask
, pseudo-elements, and other CSS features.
You can take the basic tools you learned today and evolve your skills to create awesome, unique designs, especially for your next landing page project.
What’s your favorite type of fancy corner?
As web frontends get increasingly complex, resource-greedy features demand more and more from the browser. If you’re interested in monitoring and tracking client-side CPU usage, memory usage, and more for all of your users in production, try LogRocket.
LogRocket is like a DVR for web and mobile apps, recording everything that happens in your web app, mobile app, or website. Instead of guessing why problems happen, you can aggregate and report on key frontend performance metrics, replay user sessions along with application state, log network requests, and automatically surface all errors.
Modernize how you debug web and mobile apps — start monitoring for free.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to implement one-way and two-way data binding in Vue.js, using v-model and advanced techniques like defineModel for better apps.
Compare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
3 Replies to "How to create fancy corners with CSS"
THANKS, REALLY I LOVE YOU
What is a “nootched” corner?
Also, the “random” corners aren’t “random” at all.
Thanks for pointing out this typo — it’s fixed now. We also changed references to “random” corners to “irregular.” Thanks for reading and for the tip.