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?
2
Answers
The
clip-path
CSS property can do what you want. However, arriving at a path that matches your shape and is responsive has some steps.First, we can create the path we will use using an SVG editor. For example I have created an approximate curve using this tool. This gives me the SVG path:
Unfortunately, using this like
clip-path: path("m429 0c-46 97-392 39-430 129l430 0V0");
won’t yield what you want since it won’t be responsive. The path needs to be treated as relative to the container for that to happen and by default, this will not do that.One approach is to insert a dummy SVG into the page containing a
<clipPath clipPathUnits="objectBoundingBox">
and a child<path>
with those points above, and then reference this usingclip-path: url(#your-clippath-id)
. This is detailed in this answer.However, this is a little cumbersome. Another simpler approach is to convert the path to a polygon (which uses percentages) using some separate tool. I used this answer to successfully derive a polygon, which can be used with
clip-path
directly. This gave me:Edit: I needed to clean this up a bit and remove some useless points as I think this generative code is imperfect and could be improved. This gives me:
This is big, but the less points (inversely proportional to the
steps
variable on the above answer) there are the more inaccurate the shape.You can then use this directly with a single
<Box>
component. The curve will scale with the width/height of that box.For the one at the top of the page, you can just use the same setup but with
transform: scale(-1);
applied to reflect it so its the right way up.Here is a visual demo of the result:
adsy’s answer already show you the steps to use
clip-path
, so here’s my attempt to recreate thepath
. (Click the "Full page" button and resize your windows to test responsiveness)Alternatively, if you want pure CSS without SVG, you can try
border-radius
(the curve won’t be exactly like your example though)