I'm trying to clone some projects interfaces on dribble for study purposes and raise my css skills, i've selected the layout below:
As you can see it's a mobile interface but i'm using react dom to build it ( as i mention before, it's just for study purpose ).
My problem is about this wavy bordered div's on the top and the bottom of the layout, i have tried to follow some tutorials but i did not be able to do it.
What i've tried:
At first i have tried css to solve this, using position absulote an z-index to render divs to "hide" the purple background, but the final result was weird. Here is my code:
import { Flex, useBreakpointValue } from '@chakra-ui/react';
import { Box, Flex } from '@chakra-ui/react';
const Curve = () => (
<Box
position="absolute"
height="33vh"
width="100%"
bottom="0"
textAlign="center"
>
<Box
content='""'
display="block"
position="absolute"
borderRadius="100% 28%"
width="69.5%"
height="33vh"
transform="translate(85%, 60%)"
backgroundColor="#f8f9fc"
top={5}
left={-20}
/>
<Box
content='""'
display="block"
position="absolute"
borderRadius="100% 45%"
width="75%"
height="33vh"
backgroundColor="#3B3486"
transform="translate(-4%, 40%)"
zIndex="1"
top={5}
left={-20}
/>
</Box>
);
export function Login() {
return (
<>
<Box background="#3B3486" position="relative">
<Flex pt="9rem" />
<Curve />
</Box>
<Flex
h={'70vh'}
flex={1}
justifyContent={'center'}
alignItems={'center'}
>
Content
</Flex>
</>
);
}
At last, i read that i can use SVG elements to handle it, but the final result was not responsive to other layouts. I would like to use css to solve it because it is the purpose of this clone. Is it possible to do it?
adsy's answer already show you the steps to use clip-path
, so here's my attempt to recreate the path
. (Click the "Full page" button and resize your windows to test responsiveness)
:root {
--bg: #3B3486;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.svg {
position: absolute;
top: 0;
left: 0;
width: 0;
height: 0;
}
body::before,
body::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 33.33%;
background-color: var(--bg);
clip-path: url(#wavy-clip-path);
z-index: -1;
}
body::after {
top: unset;
bottom: 0;
scale: -1;
}
<svg class="svg">
<clipPath id="wavy-clip-path" clipPathUnits="objectBoundingBox">
<path d="M0,0 l1,0 c0,0.25 -0.15,0.33 -0.5,0.5 -0.33,0.15 -0.5,0.25 -0.5,0.5 z"></path>
</clipPath>
</svg>
Alternatively, if you want pure CSS without SVG, you can try border-radius
(the curve won't be exactly like your example though)
:root {
--bg: #3B3486;
}
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
width: 100vw;
height: 100vh;
display: grid;
grid-template-rows: 33.33% 33.33% 33.33%;
}
header,
footer,
main {
position: relative;
}
header::before,
footer::before,
main::before,
header::after,
footer::after,
main::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 50%;
background-color: var(--bg);
z-index: -1;
}
header::before {
border-bottom-right-radius: 50% 100%;
}
header::after {
top: unset;
bottom: 0;
}
footer::before {
border-top-left-radius: 50% 100%;
top: unset;
bottom: 0;
}
footer::after {
z-index: -2;
}
main::before {
border-top-left-radius: 50% 100%;
top: unset;
bottom: 100%;
background-color: #fff;
}
main::after {
border-bottom-right-radius: 50% 100%;
top: 100%;
background-color: #fff;
}
<header></header>
<main></main>
<footer></footer>