How to create CSS heart? / Why is this CSS creatin

2019-01-18 12:06发布

I've found the following CSS in one of the answers here on SO and I was wondering why does it create the desired heart shape:

      #heart { 
        position: relative; 
        width: 100px; 
        height: 90px; 
      } 

      #heart:before, #heart:after { 
        position: absolute; 
        content: ""; 
        left: 50px; 
        top: 0; 
        width: 50px; 
        height: 80px; 
        background: red; 
        border-radius: 50px 50px 0 0; 
        -webkit-transform: rotate(-45deg); 
        -moz-transform: rotate(-45deg); 
        -ms-transform: rotate(-45deg); 
        -o-transform: rotate(-45deg); 
        transform: rotate(-45deg); 
       -webkit-transform-origin: 0 100%; 
       -moz-transform-origin: 0 100%; 
       -ms-transform-origin: 0 100%; 
       -o-transform-origin: 0 100%; 
       transform-origin: 0 100%; 
     } 

      #heart:after { 
        left: 0; 
        -webkit-transform: rotate(45deg); 
        -moz-transform: rotate(45deg); 
        -ms-transform: rotate(45deg); 
        -o-transform: rotate(45deg); 
       transform: rotate(45deg); 
       -webkit-transform-origin: 100% 100%; 
       -moz-transform-origin: 100% 100%; 
       -ms-transform-origin: 100% 100%; 
       -o-transform-origin: 100% 100%; 
       transform-origin :100% 100%; 
     }

Please can someone explain?

2条回答
可以哭但决不认输i
2楼-- · 2019-01-18 12:36

CSS3 Mon Amour - A 4 Step Love Afair

There are a few steps for creating heart shape using CSS3:

  1. Create a block-level element such as a <div> in your DOM and assign it with id="heart" and apply CSS:

    #heart {
         position:relative; 
         width:100px; 
         height:90px;
         margin-top:10px; /* leave some space above */
    }
    
  2. Now using pseudo-element #heart:before we create a red box with one rounded edge like this:

    #heart:before {
        position: absolute; 
        content: ""; 
        left: 50px; 
        top: 0; 
        width: 52px; 
        height: 80px; 
        background: red; /* assign a nice red color */
        border-radius: 50px 50px 0 0; /* make the top edge round */ 
    }
    

    Your heart should now look like this:

    enter image description here

  3. Let us assign a little rotation to that by adding:

    #heart:before {
        -webkit-transform: rotate(-45deg); /* 45 degrees rotation counter clockwise */
           -moz-transform: rotate(-45deg); 
            -ms-transform: rotate(-45deg); 
             -o-transform: rotate(-45deg); 
                transform: rotate(-45deg); 
        -webkit-transform-origin: 0 100%; /* Rotate it around the bottom-left corner */
           -moz-transform-origin: 0 100%; 
            -ms-transform-origin: 0 100%; 
             -o-transform-origin: 0 100%; 
                transform-origin: 0 100%;
    }
    

    And we now get:

    enter image description here

    Already starting to come together :).

  4. Now for the right part we basically need the same shape only rotated 45 degrees clockwise instead of counter clockwise. To avoid code duplication we attach the css of #heart:before also to #heart:after, and then apply the change in position and in angle:

    #heart:after { 
        left: 0; /* placing the right part properly */
        -webkit-transform: rotate(45deg); /* rotating 45 degrees clockwise */
           -moz-transform: rotate(45deg); 
            -ms-transform: rotate(45deg); 
             -o-transform: rotate(45deg); 
                transform: rotate(45deg); 
        -webkit-transform-origin: 100% 100%; /* rotation is around bottom-right corner this time */
           -moz-transform-origin: 100% 100%; 
            -ms-transform-origin: 100% 100%; 
             -o-transform-origin: 100% 100%; 
                transform-origin :100% 100%; 
    } 
    

    And voilà! a complete heart shaped <div>:

    enter image description here

Snippet without any prefix:

#heart {
  position: relative;
  width: 100px;
  height: 90px;
  margin-top: 10px;
}

#heart::before, #heart::after {
  content: "";
  position: absolute;
  top: 0;
  width: 52px;
  height: 80px;
  border-radius: 50px 50px 0 0;
  background: red;
}

#heart::before {
  left: 50px;
  transform: rotate(-45deg);
  transform-origin: 0 100%;
}

#heart::after {
  left: 0;
  transform: rotate(45deg);
  transform-origin: 100% 100%;
}
<div id="heart"></div>

查看更多
做个烂人
3楼-- · 2019-01-18 12:44

Here is another idea using one element and relying on multiple backgrounds to achieve the heart shape:

.heart {
  width:200px;
  height:200px;
  background:
   radial-gradient(circle at 50% 83%, red 29%, transparent 30%) -40px -100px,
   radial-gradient(circle at 50% 83%, red 29%, transparent 30%) 40px -100px,
   linear-gradient(to bottom left,red 43%,transparent 43%) bottom left/50% 50%,
   linear-gradient(to bottom right,red 43%,transparent 43%) bottom right/50% 50%;
  background-repeat:no-repeat;
}
<div class="heart">
</div>

How it works?

The whole shape is combined using 4 gradients: 2 gradients to create the top part and 2 for the bottom parts.

The bottom part

I simply used two linear-gradient to create two triangles covering the bottom part. The first one will give this:

.heart {
  width:200px;
  height:200px;
  border:1px solid;
  background:
   linear-gradient(to bottom right,red 43%,transparent 43%) bottom right/50% 50%;
  background-repeat:no-repeat;
}
<div class="heart"></div>

The second one is a mirror image of the first one placed on the other side.

.heart {
  width:200px;
  height:200px;
  border:1px solid;
  background:
   linear-gradient(to bottom right,red 43%,transparent 43%) bottom right/50% 50%,
   linear-gradient(to bottom left,red 43%,transparent 43%) bottom left/50% 50%;
  background-repeat:no-repeat;
}
<div class="heart"></div>

Each gradient has a size of [50% 50%], both place respectively at the bottom left and bottom right

The top part

For the top part, I will logically use radial-gradient. The idea is to have two circles above each other with a truncated part at the bottom.

.heart {
  width:200px;
  height:200px;
  border:1px solid;
  background:
  radial-gradient(circle at 50% 83%, red 29%, transparent 30%);
  background-repeat:no-repeat;
}
<div class="heart">
</div>

As you can see I made the center of the circle to be at [50% 83%] with a radius of 29% to obtain the needed shape. Now, we need to adjust its position:

.heart {
  width:200px;
  height:200px;
  border:1px solid;
  background:
  radial-gradient(circle at 50% 83%, red 29%, transparent 30%) -40px -100px;
  background-repeat:no-repeat;
}
<div class="heart">
</div>

We add the same gradient with a slight different position and we have the top part:

.heart {
  width:200px;
  height:200px;
  border:1px solid;
  background:
  radial-gradient(circle at 50% 83%, red 29%, transparent 30%) -40px -100px,
  radial-gradient(circle at 50% 83%, red 29%, transparent 30%)  40px -100px;
  background-repeat:no-repeat;
}
<div class="heart">
</div>

Now we simply combine both part

.heart {
  width:200px;
  height:200px;
  background:
   radial-gradient(circle at 50% 83%, red 29%, transparent 30%) -40px -100px,
   radial-gradient(circle at 50% 83%, red 29%, transparent 30%)  40px -100px,
   linear-gradient(to bottom left,red 43%,transparent 43%) bottom left/50% 50%,
   linear-gradient(to bottom right,red 43%,transparent 43%) bottom right/50% 50%;
  background-repeat:no-repeat;
}
<div class="heart">
</div>

If you want more

We can make the shape more flexible by adding CSS variable in order to easily adjust the dimensions:

.heart {
  --d:200px;
  width:var(--d);
  height:var(--d);
  background:
   radial-gradient(circle at 50% 83%, red 29%, transparent 30%) calc(-1 * var(--d)/5) calc(-1 * var(--d)/2),
   radial-gradient(circle at 50% 83%, red 29%, transparent 30%)  calc(1 * var(--d)/5) calc(-1 * var(--d)/2),
   linear-gradient(to bottom left,red 43%,transparent 43%) bottom left/50% 50%,
   linear-gradient(to bottom right,red 43%,transparent 43%) bottom right/50% 50%;
  background-repeat:no-repeat;
  display:inline-block;
}
<div class="heart">
</div>
<div class="heart" style="--d:100px">
</div>
<div class="heart" style="--d:60px">
</div>

查看更多
登录 后发表回答