user1637281
user1637281

Reputation:

Is a concave border radius possible?

Here is a simple convex example.

http://jsfiddle.net/swY5k/

#test{
    width: 200px;
    height: 200px;
    background: #888888;
    border-radius: 50px;
}

However, I want a concave border radius.

I tried making the border-radius negative but this did not work.

Example of concave/convex:

enter image description here

Upvotes: 24

Views: 32741

Answers (7)

tomasdev
tomasdev

Reputation: 5997

Welcome to 2024. Simply achievable using two radial gradients in a single element. No pseudo elements, nor additional, nor shenanigans.

image of the snippet rendered below

div {
  --size: 50px;
  --concave-size: calc(var(--size) / 2);
  
  height: var(--size);
  width: var(--size); /* can be whatever */
  background-color: red;
  background-image:
      radial-gradient(circle at left, yellow, yellow var(--concave-size), transparent var(--concave-size)),
      radial-gradient(circle at right, blue, blue var(--concave-size), transparent var(--concave-size));
}
<div></div>

Upvotes: 0

tessi
tessi

Reputation: 13574

With clever use of the :before and :after pseudo classes, we can simulate a concave form:

    #test{
        width: 100px;
        height: 300px;
        background: green;
        position: relative;
        display: inline-block;
    }
    
    #test:before{
        background: white;
        height: 300px;
        width: 30px;
        border-radius: 0 60px 60px 0 / 0 300px 300px 0;
        display: inline-block;
        content: '';
    }
    
    #test:after{
        background: white;
        height: 300px;
        width: 30px;
        border-radius: 60px 0 0 60px / 300px 0 0  300px;
        display: inline-block;
        content: '';
        position: relative;
        left: 40px;
    }
<div id="test"></div>

The #test div is a plain rectangle. But its :before and :after elements are half-side concave filled with the background color (white in this case).

See this jsfiddle.

Upvotes: 16

Black Horse
Black Horse

Reputation: 71

There are several ways to make the concave border. And I prefer to use the radial gradients on the background. https://jsfiddle.net/black_horse/qygmb8z9/

Sample Picture

.single-border{
  height: 50px;
  padding: 20px;
  background:-moz-radial-gradient(0 100%, circle, rgba(204,0,0,0) 20px, #c00 21px), -moz-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 20px, #c00 21px), -moz-radial-gradient(100% 0, circle, rgba(204,0,0,0) 20px, #c00 21px), -moz-radial-gradient(0 0, circle, rgba(204,0,0,0) 20px, #c00 21px);
    background:-o-radial-gradient(0 100%, circle, rgba(204,0,0,0) 20px, #c00 21px), -o-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 20px, #c00 21px), -o-radial-gradient(100% 0, circle, rgba(204,0,0,0) 14px, #c00 21px), -o-radial-gradient(0 0, circle, rgba(204,0,0,0) 20px, #c00 21px);
    background:-webkit-radial-gradient(0 100%, circle, rgba(204,0,0,0) 20px, #c00 21px), -webkit-radial-gradient(100% 100%, circle, rgba(204,0,0,0) 20px, #c00 21px), -webkit-radial-gradient(100% 0, circle, rgba(204,0,0,0) 20px, #c00 21px), -webkit-radial-gradient(0 0, circle, rgba(204,0,0,0) 20px, #c00 21px);
    background-position:left bottom, right bottom, right top, left top;
    -moz-background-size:51% 51%;
    -webkit-background-size:51% 51%;
    background-size:51% 51%;
    background-repeat:no-repeat;
}


<div class="single-border">
  Single border
</div>

Upvotes: 2

Mohammad Usman
Mohammad Usman

Reputation: 39322

SVG is the recommended way to create such shapes. It offers simplicity and scale-ability.

We can use SVG's path element to create a shape like above and fill it with some solid color, gradient or a pattern.

Only one attribute d is used to define shapes in path element. This attribute itself contains a number of short commands and few parameters that are necessary for those commands to work.

Following code will create a convex shape:

<path d="M 150,25
         Q 115,100 150,175
         Q 185,100 150,25" />

And following one will create a concave shape:

<path d="M 30,25
         L 80,25
         Q 50,100 80,175
         L 30,175
         Q 60,100 30,25" />

Below is a brief description of path commands used in above code:

  • M command is used to define the starting point. It appears at the beginning and specify the point from where drawing should start.
  • L command is used to draw straight lines.
  • Q command is used to draw curves.

Output Image:

Convex and concave shapes

Working Demo:

<svg width="300" height="200" viewBox="0 0 300 200">
  <defs>
    <linearGradient id="grad">
      <stop offset="0" stop-color="#ddd" />
      <stop offset=".5" stop-color="#fff" />
      <stop offset="1" stop-color="#ddd" />
    </linearGradient>
  </defs>
  <g stroke-width="1" stroke="#000" fill="url(#grad)">
    <path d="M30,25 L80,25 Q50,100 80,175 L30,175 Q60,100 30,25" />
    <path d="M150,25 Q115,100 150,175 Q185,100 150,25" />
  </g>
</svg>

Useful Resources:

Below are some useful links for SVG:

Upvotes: 7

jbutler483
jbutler483

Reputation: 24559

To generate the shape, you can use pseudo elements

div {
  height: 250px;
  width: 100px;
  background: tomato;
  position: relative;
  margin:0 auto;
}
div:before {
  content: "";
  height: 100%;
  width: 50%;
  position: absolute;
  background: white;
  border-radius: 50%;
  left: -25%;
  transition: all 0.8s;
}
div:after {
  content: "";
  height: 100%;
  width: 50%;
  position: absolute;
  background: white;
  border-radius: 50%;
  right: -25%;
  transition: all 0.8s;
}
div:hover:before,
div:hover:after {
  background: blue;
}
hover the shape to see how it works:
<div></div>

Upvotes: 3

Spudley
Spudley

Reputation: 168685

I suggest using border-image, with a scalable SVG image in the border.

That way you can have any shape you want in the border; no need to be restricted to the shapes offered by border-radius, and no need to do any clever hacks or extra markup either.

The down-side is that neither border-image nor SVG is supported in older browsers (ie old IE versions). But of course, border-radius isn't either, so you don't lose much with this technique, compared with the flexibility you gain.

Upvotes: 2

James Holderness
James Holderness

Reputation: 23001

You can give the impression of a concave border using radial gradients on the background. For example, something like this:

#test {
    width: 200px;
    height: 200px;
    background: #888888;
    background:
      radial-gradient(circle 20px at -20% 50%,transparent,transparent 100px,#888888 100px),
      radial-gradient(circle 20px at 120% 50%,transparent,transparent 100px,#888888 100px);
    background-size:100px 200px, 100px 200px;
    background-position:0 0,100% 0;
    background-repeat:no-repeat;
}

Note that most webkit browsers still require prefixes for radial-gradients, and if you want to fully support older browsers you may need to implement the older gradient syntax too.

Upvotes: 20

Related Questions