4

I found this answer "css: how to draw circle with text in middle?" , but I need the same, but with a heart shape. I found a lot of heart shape figures online, but none of this with text inside. At the same time, I need the heart only with borders, and when click, filled the background.

My code until now:

.heart {
  width: 100px;
  height: 90px;
  font-size: 50px;
  color: #fff;
  line-height: 100px;
  text-align: center;
}
.heart:before,
.heart:after {
  position: absolute;
  content: "";
  left: 50px;
  top: 0;
  width: 50px;
  height: 80px;
  background: red;
  -moz-border-radius: 50px 50px 0 0;
       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%;
}
<div class="heart">Heart</div>
Community
  • 1
  • 1
oldkefka
  • 95
  • 2
  • 9
  • 1
    Show what you have so far. – Mr Lister Aug 27 '15 at 12:40
  • Can you use JavaScript? It's the best way to get a click event... Can't you use [HTML5 canvas](http://www.w3.org/TR/2014/REC-html5-20141028/scripting-1.html#the-canvas-element)? It's the best way to draw something... – Dinei Aug 27 '15 at 12:49
  • 1
    I think it would be easier using a png as background-img... – DZanella Aug 27 '15 at 12:50
  • 1
    Very quick Google for "css draw heart shape" found [this](http://stackoverflow.com/questions/17386168/how-to-create-css-heart-why-is-this-css-creating-a-heart-shape) . Its amazing what you can find with Google... – ElPedro Aug 27 '15 at 13:00

4 Answers4

5

In order to get text to appear on the heart, you need to set the heart container as relative and the text inside of it as absolute as shown below.

I set the border of the :before and :after to give the heart a border.

The toggling of the fill uses functionality from YouMightNotNeedJQuery.com.

function toggleFill(heart, className) {  
  if (!hasClass(heart, className)) {
    addClass(heart, className);
  } else {
    removeClass(heart, className);
  }
}

function addClass(el, className) {
  if (el.classList) {
    el.classList.add(className);
  } else {
    el.className += ' ' + className;
  }
}

function removeClass(el, className) {
  if (el.classList) {
    el.classList.remove(className);
  } else {
    el.className = el.className.replace(
      new RegExp('(^|\\b)' + className.split(' ').join('|') +
                 '(\\b|$)', 'gi'), ' ');
  }
}

function hasClass(el, className) {
  if (el.classList) {
    return el.classList.contains(className);
  } else {
    return new RegExp('(^| )' + className +
               '( |$)', 'gi').test(el.className);
  }
}
.unselectable {
   -webkit-user-select: none;
    -khtml-user-select: none;
      -moz-user-select: none;
       -ms-user-select: none;
           user-select: none;
}
.filled:before,
.filled:after {
  background: red !important;
}
#wrapper {
  width: 300px;
  height: 180px;
  background: #444;
}
.heart {
  position: relative;
  top: calc(50% - 45px);   /* 1/2 height of wrapper - 1/2 height of heart */
  left: calc(50% - 50px);  /* 1/2 width of wrapper  - 1/2 width of heart */
  width: 100px;
  height: 90px;
}
.heart:before,
.heart:after {
  position: absolute;
  content: "";
  top: 0px;
  width: 50px;
  height: 80px;
  background: inherit;
  -moz-border-radius: 50px 50px 0 0;
       border-radius: 50px 50px 0 0;
}
.heart:before {
  left: 50px;
  -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%;
  
  border-left: 2px solid red;
  border-top: 2px solid red;
  border-bottom: 1px solid red;
}
.heart:after {
  left: 0px;
  -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%;
  
  border-right: 2px solid red;
  border-top: 2px solid red;
  border-bottom: 1px solid red;
}
.heart-text {
  position: absolute;
  top: 0;
  left: calc(50px - 30px); /* 1/2 width of heart  - 1/2 width of text */
  z-index: 100;
  line-height: 66px;
  text-align: center;
  font-size: 24px;
  font-weight: bold;
  color: #FFF;
}
<div id="wrapper">
  <div class="heart" onclick="toggleFill(this, 'filled')">
    <div class="heart-text unselectable">
      Heart
    </div>
  </div>
</div>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
3

A quick search and there is a good article about creating shapes with CSS over @ css-tricks.com that can be seen here.

If we take the example of how to create a heart and extend upon it a little we can get the following snippet that gives you a heart that starts out simply as a border;

(function(){
  var heart = document.querySelector('#heart');
  heart.addEventListener('click', function(e) {
    this.className += ' is--filled'
  });
}());
#heart {
    position: relative;
    width: 100px;
    height: 90px;
    text-align: center;
    font-size: 16px;
    position: relative;
}
#heart span {
  width: 100%;
  display: block;
  top: 50%;
  margin-top: -16px;
  line-height: 16px;
  left: 0;
  right: 0;
  position: absolute;
  z-index: 1;
}
#heart.is--filled:before,
#heart.is--filled:after {
  background-color: red;
}
#heart:before,
#heart:after {
    position: absolute;
    content: "";
    left: 50px;
    top: 0;
    width: 50px;
    height: 80px;
    border: 1px solid red;
    transition: background-color .25s ease 0s;
    -webkit-transition: background-color .25s ease 0s;
    -moz-border-radius: 50px 50px 0 0;
    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%;
}

#heart:before {
  border-right: none;
  border-bottom: none;
}
#heart:after {
  border-left: none;
  border-bottom: none;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
</head>
<body>
  <div id='heart'>
    <span>Hey</span>
  </div>
</body>
</html>

However, as someone else has mentioned in the comments it may be an easier approach to use images or the canvas element. I say this purely because it may prove difficult to get just the heart border you desire before clicking the heart (easier to see if you run the snippet). You could opt for much softer opaque background color before you click and then transition to red maybe?

Hope this helps you out!

Jhey
  • 1,377
  • 7
  • 10
3

Use pseudo elements of css3.

.text {
  position: absolute;
  color: #eee;
  z-index: 99;
  top: 40%;
  left: 50%;
  transform: translate(-50%, -50%);
}
#heart {
  position: relative;
  width: 100px;
  height: 90px;
}
#heart:before,
#heart:after {
  position: absolute;
  content: "";
  left: 50px;
  top: 0;
  width: 50px;
  height: 80px;
  background: red;
  -moz-border-radius: 50px 50px 0 0;
  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%;
}
<div id="heart">
  <div class="text">ABC</div>
</div>
Suresh Karia
  • 17,550
  • 18
  • 67
  • 85
1

Use this

HTML

$('#change').click(function() {
   var className = $(this).attr('class');
    if(className == "heart"){
     $(this).removeClass('heart');
 $(this).addClass('heart1');
    }
    else{
    $(this).removeClass('heart1');
 $(this).addClass('heart');
    }
});
.txt{
    z-index:1;
    font-size: 20px;
  color: #000;
    position:relative;
    text-align:center;
    top:15px;
    right:5px;
}
.heart {
  width: 100px;
  height: 90px;

}
.heart1 {
  width: 100px;
  height: 90px;

}
.heart:before,
.heart:after {
  position: absolute;
  content: "";
  left: 50px;
  top: 0;
  width: 50px;
  height: 80px;
  background: yellow;
  -moz-border-radius: 50px 50px 0 0;
       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%;
}
.heart1:before,
.heart1:after {
  position: absolute;
  content: "";
  left: 50px;
  top: 0;
  width: 50px;
  height: 80px;
  background: red;
  -moz-border-radius: 50px 50px 0 0;
       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%;
}
.heart1: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%;
}
.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%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="change" class="heart"><div class="txt">Heart</div></div>
Ankit
  • 502
  • 1
  • 4
  • 20