How do I create a teardrop in HTML?

2019-01-16 00:00发布

How do I create a shape like this to display on a webpage?

I don't want to use images since they would get blurry on scaling

Teardrop shape I need to make with HTML, CSS or SVG

I tried with CSS:

.tear {
  display: inline-block;
  transform: rotate(-30deg);
  border: 5px solid green;
  width: 50px;
  height: 100px;
  border-top-left-radius: 50%;
  border-bottom-left-radius: 50%;
  border-bottom-right-radius: 50%;
}
<div class="tear">
</div>

That turned out really screwed.

And then I tried with SVG:

<svg viewBox="0 100 100">
  <polygon points="50,0 100,70 50,100 0,70"/>
</svg>

It did get the shape, but the bottom part wasn't curved.

Is there a way to create this shape so it can be used in an HTML page?

12条回答
三岁会撩人
2楼-- · 2019-01-16 00:48

If you do choose to use SVG you should read up on paths. I would also suggest an SVG editor.

<svg xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="100%" height="100%" viewBox="-0.05 0 1195.1 703" preserveAspectRatio="xMidYMid meet" zoomAndPan="disable" transform="">
    <defs id="svgEditorDefs">
        <line id="svgEditorLineDefs" stroke="black" style="fill: none; vector-effect: non-scaling-stroke; stroke-width: 1px;"/>
    </defs>
    <rect id="svgEditorBackground" x="0" y="0" width="1195" height="703" style="fill: none; stroke: none;"/>
    <path stroke="black" id="e1_circleArc" style="fill: none; stroke-width: 1px; vector-effect: non-scaling-stroke;" d="M 198 207 a 117.969 117.969 0 1 0 213 8" transform=""/>
    <path stroke="black" id="e4_circleArc" style="fill: none; stroke-width: 1px; vector-effect: non-scaling-stroke;" transform="" d="M 411.348 215.696 a 349.677 349.677 0 0 0 -110.37 -131.718"/>
    <path stroke="black" style="fill: none; stroke-width: 1px; vector-effect: non-scaling-stroke;" transform="matrix(-0.182706 -0.983168 0.983168 -0.182706 157.664 417.408)" id="e6_circleArc" d="M 301.799 202.299 a 329.763 329.763 0 0 0 -102.951 -124.781"/>
</svg>

查看更多
男人必须洒脱
3楼-- · 2019-01-16 00:51

CSS Version

As there are a fair few answers here I thought why not add to it with another method. This is using both HTML and CSS to create the teardrop.

This will allow you to change the colour of the border and background of the teardrop and also re-size the top part of it.

Using a single div we can create a circle with border and border-radius. Then using pseudo elements (:before & :after) we create a CSS triangle more here, this will act as the tip of the teardrop. Using the :before as the border we place :after on top with a smaller size and the desired background colour.

div {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  border: 4px solid;
  margin: 80px auto;
  position: relative;
}
div:before,
div:after {
  content: "";
  display: block;
  position: absolute;
  width: 0;
  height: 0;
}
div:before {
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 104px solid black;
  top: -75px;
}
div:after {
  border-left: 46px solid transparent;
  border-right: 46px solid transparent;
  border-bottom: 96px solid #fff;
  top: -66px;
  left: 0;
  right: 0;
  margin: auto;
  z-index: 1;
}
<div></div>


Here is a demo of the teardrop with a background colour

div {
  width: 100px;
  height: 100px;
  border-radius: 50%;
  border: 4px solid;
  background: red;
  margin: 80px;
  position: relative;
}
div:before,
div:after {
  content: "";
  display: block;
  position: absolute;
  width: 0;
  height: 0;
}
div:before {
  border-left: 50px solid transparent;
  border-right: 50px solid transparent;
  border-bottom: 100px solid black;
  top: -70px;
}
div:after {
  border-left: 46px solid transparent;
  border-right: 46px solid transparent;
  border-bottom: 96px solid red;
  top: -66px;
  left: 0;
  right: 0;
  margin: auto;
  z-index: 1;
}
<div></div>

It is as simple as putting a background colour onto the div and changing :after bottom-border colour to the same. To change the border you will need to change div border colour and :before background colour too.

查看更多
放我归山
4楼-- · 2019-01-16 00:54

Here are four progressively simpler SVG teardrop shapes:

enter image description here

<svg viewbox="-20 -20 180 180">
  <g stroke="black" fill="none">
    
    <path transform="translate(0)"
     d="M   0  0
        C   0 10  10 17  10 27
        C  10 40 -10 40 -10 27
        C -10 17   0 10   0  0
        Z"/>

    <path transform="translate(40)"
     d="M   0  0
        C   0 16  15 25   5 34
        Q   0 38         -5 34
        C -15 25   0 16   0  0
        Z"/>
    
    <path transform="translate(80)"
     d="M   0  0
        C   0 10  18 36   0 36
        S          0 10   0  0
        Z"/>

    <path transform="translate(120)"
     d="M   0  0
        Q  18 36   0 36
        T          0  0
        Z"/>
    
    
    
    
    <g stroke-width="0.25" stroke="red">
      <g transform="translate(0)">
        <ellipse rx="1" ry="1" cx="0"   cy="0" />
        <ellipse rx="1" ry="1" cx="0"   cy="10"/>
        <ellipse rx="1" ry="1" cx="10"  cy="17"/>
        <ellipse rx="1" ry="1" cx="10"  cy="27"/>
        <ellipse rx="1" ry="1" cx="10"  cy="40"/>
        <ellipse rx="1" ry="1" cx="-10" cy="40"/>
        <ellipse rx="1" ry="1" cx="-10" cy="27"/>
        <ellipse rx="1" ry="1" cx="-10" cy="17"/>
        <line x1="0"   y1="0"  x2="0"   y2="10"/>
        <line x1="10"  y1="17" x2="10"  y2="40"/>
        <line x1="-10" y1="40" x2="-10" y2="17"/>
      </g>
      <g transform="translate(40)">
        <ellipse rx="1" ry="1" cx="0"   cy="0" />
        <ellipse rx="1" ry="1" cx="0"   cy="16"/>
        <ellipse rx="1" ry="1" cx="15"  cy="25"/>
        <ellipse rx="1" ry="1" cx="5"   cy="34"/>
        <ellipse rx="1" ry="1" cx="0"   cy="38"/>
        <ellipse rx="1" ry="1" cx="-5"  cy="34"/>
        <ellipse rx="1" ry="1" cx="-15" cy="25"/>
        <line x1="0"  y1="0"  x2="0"   y2="16"/>
        <line x1="15" y1="25" x2="0"   y2="38"/>
        <line x1="0"  y1="38" x2="-15" y2="25"/>
      </g>
      <g transform="translate(80)">
        <ellipse rx="1" ry="1" cx="0"   cy="0" />
        <ellipse rx="1" ry="1" cx="0"   cy="10"/>
        <ellipse rx="1" ry="1" cx="18"  cy="36"/>
        <ellipse rx="1" ry="1" cx="0"   cy="36"/>
        <ellipse rx="1" ry="1" cx="-18" cy="36" stroke="gray"/>
        <line x1="0"  y1="0"  x2="0"   y2="10"/>
        <line x1="18" y1="36" x2="0"   y2="36"/>
        <line x1="0"  y1="36" x2="-18" y2="36" stroke="gray" stroke-dasharray="0.5"/>
      </g>
      <g transform="translate(120)">
        <ellipse rx="1" ry="1" cx="0"   cy="0" />
        <ellipse rx="1" ry="1" cx="18"  cy="36"/>
        <ellipse rx="1" ry="1" cx="0"   cy="36"/>
        <ellipse rx="1" ry="1" cx="-18" cy="36" stroke="gray"/>
        <line x1="18" y1="36" x2="0"   y2="36"/>
        <line x1="0"  y1="36" x2="-18" y2="36" stroke="gray" stroke-dasharray="0.5"/>
      </g>
    </g>    
  </g>
  <g font-size="6" transform="translate(-1.5,-4)">
    <text x="-10" y="-8"># of unique points:</text>
    <text transform="translate(  0)">8</text>
    <text transform="translate( 40)">7</text>
    <text transform="translate( 80)">4</text>
    <text transform="translate(120)">3</text>
  </g>
</svg>

查看更多
5楼-- · 2019-01-16 00:56

Your main issue with your CSS code was:

  1. You used a different height than width
  2. You haven't rotated the correct angle size

So, by 'fixing' these issues, you would generate:

.tear {
  display: inline-block;
  transform: rotate(-45deg);
  border: 5px solid green;
  width: 100px;
  height: 100px;
  border-top-left-radius: 50%;
  border-bottom-left-radius: 50%;
  border-bottom-right-radius: 50%;
}
/***for demo only***/

.tear {
  margin: 50px;
}
<div class="tear">
</div>

Please also note to save on CSS length, you could re-write your border-radius properties to:

border-radius: 50% 0 50% 50%;

this could be enhanced with pseudo elements as shown in this fiddle

Alternatives

I found this by Vinay Challuru on codepen.

Please note that with the logic here, I was able to create the SVG to nearly any possible build shape/etc. For example, a quick output was:

<svg viewBox='0 0 400 400'>
  <path fill="none" stroke="#333" stroke-width="5" d="M200,40 C200,115 280,180 280,240 A80,80,0 0,1,120,240 C120,180 200,115 200,40" stroke-linejoin='miter'></path>
</svg>

It's using an SVG and allows you to alter the shape in multiple ways, having the ability to alter its shape to the desired result:

var SVG = function() {
  this.element = document.getElementsByTagName("svg")[0];
  this.namespace = "http://www.w3.org/2000/svg";
  this.width = 400;
  this.height = 400;
}

/****Let's initialise our SVG ready to draw our shape****/
var svg = new SVG();

/****This sets up the user interface - we've included the script for this as an external library for the codepen****/
var gui = new dat.GUI();

/****Here's where the code to create the shape begins!****/
var Teardrop = function() {
  this.x = svg.width * 0.5;
  this.y = svg.height * 0.1;
  this.width = svg.width * 0.4;
  this.triangleHeight = svg.height * 0.5;
  this.yCP1 = svg.height * 0.2;
  this.yCP2 = svg.height * 0.45;
  this.element = null;
  this.ctrlPoints = [];
  this.anchors = [];
  this.fill = "none";
  this.stroke = "#333";
  this.strokeWidth = 2;
  this.showCtrlPoints = true;
  this.init();
}

Teardrop.prototype.init = function() {
  this.element = document.createElementNS(svg.namespace, "path");
  svg.element.appendChild(this.element);
  this.element.setAttribute("fill", this.fill);
  this.element.setAttribute("stroke", this.stroke);
  this.element.setAttribute("stroke-width", this.strokeWidth);

  for (var i = 0; i < 3; i++) {
    this.ctrlPoints.push(document.createElementNS(svg.namespace, "circle"));
    svg.element.appendChild(this.ctrlPoints[i]);

    this.ctrlPoints[i].setAttribute("fill", this.fill);
    this.ctrlPoints[i].setAttribute("stroke", 'red');
    this.ctrlPoints[i].setAttribute("stroke-width", 1);


    this.anchors.push(document.createElementNS(svg.namespace, "line"));
    svg.element.appendChild(this.anchors[i]);

    this.anchors[i].setAttribute("stroke-width", 1);
    this.anchors[i].setAttribute("stroke", this.stroke);
    this.anchors[i].setAttribute("stroke-dasharray", "3,2");
  }

  this.draw();
}

Teardrop.prototype.draw = function() {
  this.radius = this.width / 2;
  path = [
    "M", this.x, ",", this.y,
    "C", this.x, ",", this.yCP1, " ", this.x + this.width / 2, ",", this.yCP2, " ", this.x + this.width / 2, ",", this.y + this.triangleHeight,
    "A", this.radius, ",", this.radius, ",", "0 0,1,", this.x - this.width / 2, ",", this.y + this.triangleHeight,
    "C", this.x - this.width / 2, ",", this.yCP2, " ", this.x, ",", this.yCP1, " ", this.x, ",", this.y
  ];
  this.element.setAttribute("d", path.join(""));

  cpCoords = [];
  cpCoords[0] = [this.x, this.yCP1];
  cpCoords[1] = [this.x - this.width / 2, this.yCP2];
  cpCoords[2] = [this.x + this.width / 2, this.yCP2];

  anchorCoords = [];
  anchorCoords[0] = [this.x, this.y];
  anchorCoords[1] = [this.x - this.width / 2, this.y + this.triangleHeight];
  anchorCoords[2] = [this.x + this.width / 2, this.y + this.triangleHeight];

  for (var i = 0; i < 3; i++) {
    this.ctrlPoints[i].setAttribute("cx", cpCoords[i][0]);
    this.ctrlPoints[i].setAttribute("cy", cpCoords[i][1]);

    this.anchors[i].setAttribute("x1", cpCoords[i][0]);
    this.anchors[i].setAttribute("x2", anchorCoords[i][0]);
    this.anchors[i].setAttribute("y1", cpCoords[i][1]);
    this.anchors[i].setAttribute("y2", anchorCoords[i][1]);

    if (this.showCtrlPoints) {
      this.ctrlPoints[i].setAttribute("r", 2);
      this.anchors[i].setAttribute("stroke-width", 1);
    } else {
      this.ctrlPoints[i].setAttribute("r", 0);
      this.anchors[i].setAttribute("stroke-width", 0);
    }
  }
}

var teardrop = new Teardrop();

gui.add(teardrop, 'triangleHeight', 0, svg.height * 0.75);
gui.add(teardrop, 'width', 0, 200);
gui.add(teardrop, 'yCP1', 0, svg.height);
gui.add(teardrop, 'yCP2', 0, svg.height);
gui.add(teardrop, 'showCtrlPoints', 0, svg.height);

for (var i in gui.__controllers) {
  gui.__controllers[i].onChange(function() {
    teardrop.draw();
  });
}
html,
body {
  height: 100%;
}
svg {
  display: block;
  margin: 0 auto;
  background: url('http://unitedshapes.com/images/graph-paper/graph-paper.png');
}
<script src="//cdnjs.cloudflare.com/ajax/libs/dat-gui/0.5/dat.gui.min.js"></script>
<svg width='400px' height='400px'></svg>

Disclaimer I did not write the above pen, only sourced it.


CSS Version

Although this is far from complete, you may also be able to generate this shape using CSS.

.tear{
    height:200px;
    width:200px;
    background: linear-gradient(to bottom, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 29%,rgba(0,0,0,1) 30%,rgba(0,0,0,1) 100%);
    border-radius:50%;
    margin:120px;
    position:relative;
}
.tear:before{
    content:"";
    position:absolute;
    top:-70%;left:0%;
    height:100%;width:50%;
    background: radial-gradient(ellipse at -50% -50%, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 75%,rgba(0,0,0,1) 76%,rgba(0,0,0,1) 100%);
}
.tear:after{
    content:"";
    position:absolute;
    top:-70%;left:50%;
    height:100%;width:50%;
    background: radial-gradient(ellipse at 150% -50%, rgba(0,0,0,0) 0%,rgba(0,0,0,0) 75%,rgba(0,0,0,1) 76%,rgba(0,0,0,1) 100%);
}
<div class="tear"></div>

SVG Version

I should know that SVG should be at the top of this answer, however, I like a challenge and so here is an attempt with SVG.

svg {
  height: 300px;
}
svg path {
  fill: tomato;
}
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 0 100 100">

  <path d="M49.015,0.803
    c-0.133-1.071-1.896-1.071-2.029,0
    C42.57,36.344,20,43.666,20,68.367   
    C20,83.627,32.816,96,48,96
    s28-12.373,28-27.633
    C76,43.666,53.43,36.344,49.015,0.803z 
    M44.751,40.09   
    c-0.297,1.095-0.615,2.223-0.942,3.386
    c-2.007,7.123-4.281,15.195-4.281,24.537
    c0,5.055-2.988,6.854-5.784,6.854   
    c-3.189,0-5.782-2.616-5.782-5.831
    c0-11.034,5.315-18.243,10.005-24.604
    c1.469-1.991,2.855-3.873,3.983-5.749   
    c0.516-0.856,1.903-0.82,2.533,0.029
    C44.781,39.116,44.879,39.619,44.751,40.09z"/>


</svg>

Altering the path values, you would be able to alter the shape of your teardrop design.

查看更多
时光不老,我们不散
6楼-- · 2019-01-16 00:58

Or if your viewers' font supports it, use the Unicode characters

DROPLET:

查看更多
一夜七次
7楼-- · 2019-01-16 00:58

I also found this on Codepen made by user Ana Tudor using CSS and the box-shadow style and parametric equations. Very simple, very little code. And many browsers support the CSS3 Box-shadow style:

body {
  background-color: black;
}
.tear {
  position: absolute;
  top: 50%;
  left: 50%;
  margin: -0.125em;
  width: 0.25em;
  height: 0.25em;
  border-radius: 50%;
  box-shadow: 0em -5em red, 0.00118em -4.97592em #ff1800, 0.00937em -4.90393em #ff3000, 0.03125em -4.7847em #ff4800, 0.07283em -4.6194em #ff6000, 0.13915em -4.40961em #ff7800, 0.23408em -4.15735em #ff8f00, 0.36em -3.86505em #ffa700, 0.51777em -3.53553em #ffbf00, 0.70654em -3.17197em gold, 0.92382em -2.77785em #ffef00, 1.16547em -2.35698em #f7ff00, 1.42582em -1.91342em #dfff00, 1.69789em -1.45142em #c7ff00, 1.97361em -0.97545em #afff00, 2.2441em -0.49009em #97ff00, 2.5em 0.0em #80ff00, 2.73182em 0.49009em #68ff00, 2.93032em 0.97545em #50ff00, 3.08681em 1.45142em #38ff00, 3.19358em 1.91342em #20ff00, 3.24414em 2.35698em #08ff00, 3.23352em 2.77785em #00ff10, 3.15851em 3.17197em #00ff28, 3.01777em 3.53553em #00ff40, 2.81196em 3.86505em #00ff58, 2.54377em 4.15735em #00ff70, 2.21783em 4.40961em #00ff87, 1.84059em 4.6194em #00ff9f, 1.42017em 4.7847em #00ffb7, 0.96608em 4.90393em #00ffcf, 0.48891em 4.97592em #00ffe7, 0.0em 5em cyan, -0.48891em 4.97592em #00e7ff, -0.96608em 4.90393em #00cfff, -1.42017em 4.7847em #00b7ff, -1.84059em 4.6194em #009fff, -2.21783em 4.40961em #0087ff, -2.54377em 4.15735em #0070ff, -2.81196em 3.86505em #0058ff, -3.01777em 3.53553em #0040ff, -3.15851em 3.17197em #0028ff, -3.23352em 2.77785em #0010ff, -3.24414em 2.35698em #0800ff, -3.19358em 1.91342em #2000ff, -3.08681em 1.45142em #3800ff, -2.93032em 0.97545em #5000ff, -2.73182em 0.49009em #6800ff, -2.5em 0.0em #7f00ff, -2.2441em -0.49009em #9700ff, -1.97361em -0.97545em #af00ff, -1.69789em -1.45142em #c700ff, -1.42582em -1.91342em #df00ff, -1.16547em -2.35698em #f700ff, -0.92382em -2.77785em #ff00ef, -0.70654em -3.17197em #ff00d7, -0.51777em -3.53553em #ff00bf, -0.36em -3.86505em #ff00a7, -0.23408em -4.15735em #ff008f, -0.13915em -4.40961em #ff0078, -0.07283em -4.6194em #ff0060, -0.03125em -4.7847em #ff0048, -0.00937em -4.90393em #ff0030, -0.00118em -4.97592em #ff0018;
}
<div class="tear"></div>

查看更多
登录 后发表回答