Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS advanced shape (heart cut out of background)

Basically I want to create a shape in CSS only (so no images) that is the opposite of a heart shape. I don't know how to explain it properly so here is an image:

enter image description here

The blue is the background, as you can see, but the shape that I want to create is not a heart, it is the shape of the black rectangle.

If I would have the following shape (THE GRAY NOT THE BLACK)

enter image description here

I could duplicate it and then rotate it, that would give me the shape I am looking for.

like image 710
onlineracoon Avatar asked Jan 17 '13 19:01

onlineracoon


People also ask

How do you make a complicated shape in CSS?

You need to add width and height, and that's it. First two shapes are created. Adding border-radius and you have circles and ovals. More complex shapes require to add :before and :after pseudo-elements or more HTML.


3 Answers

Heart shape cut out using box-shadow

Let's create this — the blue is the background color of <body>

Screenshot

The pieces

Feel free to skip directly to the complete demo at the bottom of this answer :)

1 - The rounded corners

The rounded top left and top right corners are created with box-shadow on the two pseudo elements with border-radius: 50%.heart:before and .heart:after — They form two crescent shapes that look like this:

Crescent Shapes

2 - The angle

The angled shape is created by the box-shadow on .heart. Combined with the two circles, it looks like this:

Angled Shape

3 - The filler

We now need to fill in the gaps. This is done by the pseudo elements of the .box-shape container — .shape-box:before and .shape-box:after. The excess is cut-off neatly with overflow: hidden on the .shape-box. Combined with our pieces above, they look like this:

The filler

The Complete Example

Combine it all together and we get this nicely cut out heart shape. It is all contained in .shape-box.

body {
  background: #00A2F6;
}
.shape-box {
  height: 504px;
  width: 504px;
  position: relative;
  margin: 100px;
  overflow: hidden;
}
.shape-box:before,
.shape-box:after {
  content: '';
  display: block;
  height: 100px;
  width: 120px;
  background: #2B2B2B;
  transform: rotate(45deg);
  left: 190px;
  position: absolute;
  top: 40px;
}
.shape-box:after {
  width: 760px;
  height: 750px;
  box-shadow: inset 0 0 0 220px #2B2B2B;
  top: -150px;
  left: -130px;
  background: none;
}
.heart {
  transform: rotate(45deg);
  height: 357px;
  width: 356px;
  box-shadow: inset 0 0 0 50px #2B2B2B;
  position: absolute;
  left: 74px;
  top: 34px;
}
.heart:before,
.heart:after {
  content: '';
  display: block;
  width: 151px;
  height: 151px;
  border-radius: 50%;
  box-shadow: -40px -15px 0 20px #2B2B2B;
  position: absolute;
  left: 50px;
  top: 157px;
}
.heart:after {
  box-shadow: -15px -40px 0 21px #2B2B2B;
  left: 156px;
  top: 51px;
}
<div class="shape-box">
  <div class="heart"></div>
</div>
like image 129
misterManSam Avatar answered Sep 28 '22 06:09

misterManSam


This can be done with a combination of svg gradients, multiple backgrounds, and a little creative tiling/placement. Sample CSS from my working jsfiddle (without vendor prefixes, i.e. -webkit and -moz):

height: 400px;
width: 400px;
background-image:
  radial-gradient(75% 85.5%, circle, transparent 25%, black 26%),
  radial-gradient(25% 85.5%, circle, transparent 25%, black 26%),
  linear-gradient(225deg, transparent 25%, black 25%),
  linear-gradient(135deg, transparent 25%, black 25%);
background-size: 200px 200px;
background-position: top left, top right, bottom left, bottom right;
background-repeat: no-repeat;

This makes a heart-shaped cutout in the middle of a 400px square element. It can be modified to fit whatever size element you want.

Update: here’s a more complex fiddle that uses six gradients instead of four, but looks a bit nicer.

like image 36
marcus erronius Avatar answered Sep 28 '22 07:09

marcus erronius


Based on the work that Mark Hubbart did I was able to push this to a slightly more advanced form in this fiddle

This is not 100% complete yet as it will need some media queries to work across more browsers but it does show the start of a much more flexible working for the same goal.

#backgrounder {
z-index: 2;
background-image: 
   radial-gradient(68% 100%, circle, transparent 48%, white 30%), 
   radial-gradient(32% 100%, circle, transparent 48%, white 30%), 
   radial-gradient(110% 1%, circle, transparent 65%, white 30%), 
   radial-gradient(-8.5% 1%, circle, transparent 65%, white 30%), 
   linear-gradient(220deg, transparent 41%, white 30%), 
   linear-gradient(139deg, transparent 41%, white 30%);


 background-image: 
    -webkit-radial-gradient(68% 100%, circle, transparent 48%, white 30%), 
    -webkit-radial-gradient(32% 100%, circle, transparent 48%, white 30%), 
    -webkit-radial-gradient(110% 1%, circle, transparent 65%, white 30%), 
    -webkit-radial-gradient(-8.5% 1%, circle, transparent 65%, white 30%), 
    linear-gradient(220deg, transparent 41%, white 30%), 
    linear-gradient(139deg, transparent 41%, white 30%);

 background-size: 51% 31%, 50% 31%, 51% 50%, 50% 50%, 51% 51%, 50% 51%;
 background-position: top left, top right, 0% 30%, 100% 30%, bottom left, bottom right;
 background-repeat: no-repeat;
 position: absolute;
 top: 0; right: 0; bottom: 0; left: 0;
}
like image 28
Crispen Smith Avatar answered Sep 28 '22 08:09

Crispen Smith