Building a curvy container with CSS
Design problem:
The white background underneath the call-to-action was an interesting problem. I could have easily exported it as an image or SVG from the design tool, and used this export as a background image. That would have led to some annoying layering problems with the darker banner background, so probably I could have exported the entire top banner, dark and rounded light, as one image. But that would have required two images, one for mobile, one for desktop.
Both seem wasteful if you can do the rounded white background with pure css.
Example
The rounded edge
I figured out pretty quickly how to make a circular container using border-radius: 50%
.
const Header = styled.section`
box-sizing: border-box;
position: relative;
height: 350px;
`;
const Bubble = styled.div`
box-sizing: border-box;
position: absolute;
background-color: #f00;
text-align: center;
border-radius: 50%;
height: 700px;
width: 700px;
`;
<Header>
<BackgroundImage src={banner} />
<Bubble>
<p>
...
</p>
</Bubble>
</Header>
Positioning
Super-easy, but we don’t want a circle. We want a mostly-rectangular container with one curved edge. So we need to get clever with positioning and sizing.
First we inflate the circle and use some negative margin
to position its origin off-view down and to the right so that the left-edge is where we want it.
const Bubble = styled.div`
box-sizing: border-box;
position: absolute;
background-color: #f00;
text-align: center;
border-radius: 50%;
height: 700px; width: 700px; top: -60px; right: -250px; bottom: 0; `;
Masking the edges
Now we just need to make it look like it has 3 straight edges and one curved edge. We can treat the parent container as a clipping-mask by just hiding overflow.
const Container = styled.section`
box-sizing: border-box;
position: relative;
overflow: hidden;`;
Centering the content
The content is obviously not where we want it to be wit respect to the visible container. So you can use padding
inside the circle-div to position the content where you want it.
const Bubble = styled.div`
box-sizing: border-box; position: absolute;
background-color: #f00;
text-align: center;
border-radius: 50%;
height: 700px;
width: 700px;
top: -60px;
right: -250px;
bottom: 0;
padding: 200px 300px 0 100px;`;
Using box-sizing: border-box
here will make sizing and padding easier to understand, as the total width/height of the circle will remain the same when you adjust the padding. Otherwise, you’ll have to adjust your desired sizing to take the padding into account.
border-box
tells the browser to account for any border and padding in the values you specify for an element’s width and height. If you set an element’s width to 100 pixels, that 100 pixels will include any border or padding you added, and the content box will shrink to absorb that extra width. This typically makes it much easier to size elements.
The Result
After adding some media queries to re-position the circle for small screens, here’s the final result.
Check out the full example on CodeSandbox.