Reputation: 821
I have a container with a child element in it. The container has a border radius of 0.3rem
. My child element has a border as well. I would like my child's border to round at the same radius as the parent, but I can't seem to do it. My first approach was to just have the child match the parent's radius of 0.3rem
but for some reason (even though the computed font size on both elements are the same) the borders don't line up perfectly:
My second approach was to use the commonly suggested overflow: hidden
style on the parent container. Doing this without the child matching the parent's border radius does make the entire button perfectly follow the outline of the parent container, but now the child's border looks "cut off" in the corner:
Is there any way I can both follow the parent container's curve while keeping a matching border curve on the child element?
Upvotes: 5
Views: 4885
Reputation: 5181
The border-radius of the inner element is the padding edge radius of the outer element, and
The padding edge (inner border) radius is the outer border radius minus the corresponding border thickness.
—CSS Backgrounds and Borders Module Level 3, § 5.2. Corner Shaping
div {
border-radius: 1rem;
border-width: 5px;
}
span {
border-radius: 0 0 calc(1rem - 5px) calc(1rem - 5px);
border-width: 3px;
}
/* the rest is positioning and colors */
div {
position: absolute;
top: 2rem;
bottom: 2rem;
left: 2rem;
right: 2rem;
border-color: grey;
border-style: solid;
}
span {
display: block;
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 5rem;
border-color: #33f;
border-style: solid;
}
<div><span></span></div>
Upvotes: 7
Reputation: 3941
Your issue is that the parent div has a border around it. It looks like this is being done to offset it from the content below, similar to a drop-shadow.
div {
border-radius: 1rem;
box-sizing: border-box;
}
.outer {
width: 100px;
height: 100px;
background: lightgrey;
border: 3px solid black;
}
.inner {
width: calc(100px - 6px);
height: calc(50px - 6px);
position: relative;
top: 50px;
left: 0px;
background: red;
border-top-left-radius: unset;
border-top-right-radius: unset;
border: 3px solid blue;
}
<div class="outer">
<div class="inner"></div>
</div>
There are a couple ways you can solve this. You can make sure that the child element overlays the outer element, that way their borders and radiuses are the same. Your other option is to remove the border from the parent container.
div {
border-radius: 1rem;
box-sizing: border-box;
display: inline-block
}
.outer {
width: 100px;
height: 100px;
margin-left: 5px;
background: lightgrey;
border: 3px solid black;
}
.inner {
width: 100px;
height: 50px;
position: relative;
top: 50px;
left: -3px;
background: red;
border-top-left-radius: unset;
border-top-right-radius: unset;
border: 3px solid blue;
}
.outer2 {
border: none;
}
.inner2 {
width: 100px;
left: 0px;
height: 50px;
}
<div class="outer">
<div class="inner"></div>
</div>
<div class="outer outer2">
<div class="inner inner2"></div>
</div>
Dealing with these types of issues are always simpler when using box-sizing: border-box
, but they're possible with content-box
if you don't mind doing a little more math.
You can play around with it a little easier using this jsfiddle.
Upvotes: 1
Reputation: 10998
Unfortunately, no, there is no easy way to match border radius of nested objects. If you try to simply match, you'll end up with something like this (notice the sliver or white between the red and blue):
div {
display: inline-block;
border: 2px solid blue;
border-radius: 10px;
}
span {
display: block;
background: red;
height: 100px;
width: 100px;
border-radius: inherit;
}
<div>
<span></span>
</div>
In terms of the shape you're trying to draw, it's probably best to go along this (syntactically ugly) route:
body {
background: aliceblue;
box-sizing: border-box;
}
*, *::after, *::before {
box-sizing: inherit;
}
div > span:first-child {
border-top-left-radius: 10px;
border-top-right-radius: 10px;
}
div > span:last-child {
border-bottom-left-radius: 10px;
border-bottom-right-radius: 10px;
background-color: red;
border-color: blue;
border-style: solid;
}
span {
display: block;
height: 40px;
width: 80px;
background: white;
border-width: 2px;
}
<div>
<span></span>
<span></span>
<span></span>
</div>
Essentially, any time you're trying to match two curves of nested objects, it comes out nicer if you flatten the drawing logic. It's a hassle, but that's the best I've found for really solid results. You will have to use border-box
to make it so objects are sized by the outside of their border rather than inside of it (content size... it's lame).
Upvotes: 1