问题
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?
回答1:
CSS3 Mon Amour - A 4 Step Love Afair
There are a few steps for creating heart shape using CSS3:
Create a block-level element such as a
<div>
in your DOM and assign it withid="heart"
and apply CSS:#heart { position:relative; width:100px; height:90px; margin-top:10px; /* leave some space above */ }
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:
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:
Already starting to come together :).
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>
:
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>
回答2:
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>
来源:https://stackoverflow.com/questions/17386168/how-to-create-css-heart-why-is-this-css-creating-a-heart-shape