如何在 CSS 中制作一个带边框的可调整大小的心形

How to make a resizable heart in CSS with a border

我想制作一个心形,用户可以将其调整为任意宽度和高度,边框为 1 像素。

  1. 我试过一颗纯正的心CSS:

  2. 我试过使用这样的字体: https://www.w3schools.com/charsets/tryit.asp?deci=9829&ent=hearts

  3. 还试了一张SVG图片: https://css-tricks.com/hearts-in-html-and-css/#inline-svg

但是我的问题是:

  1. 无法自由轻松地缩放到 500x200 像素。很难在其周围添加边框

  2. 它不能拉伸到其他比例,也不能放大以适应例如。 500x400 框

  3. 它几乎是完美的,但边框(描边)随着大小而延伸。我希望边框始终为 1px 宽,无论比例如何

我也尝试制作另一个形状的副本作为阴影(填充为黑色并略微偏移,z-index 较低)但它并不完美(边框各处的宽度不同):

可能 my heart 会做得更好,即使仍然不完美

.heart {
  width:200px;
  height:200px;
  background:
   radial-gradient(90% 90% at 60% 65%, transparent calc(64% - 1px), black 64%, transparent calc(64% + 1px)) top left,
   radial-gradient(90% 90% at 40% 65%, transparent calc(64% - 1px), black 64%, transparent calc(64% + 1px)) top right,
   linear-gradient(to bottom left,     transparent calc(43% - 1px), black 43%, transparent calc(43% + 1px)) bottom left ,
   linear-gradient(to bottom right,    transparent calc(43% - 1px), black 43%, transparent calc(43% + 1px)) bottom right;
  background-size:50% 50%;
  background-repeat:no-repeat;
  border:2px solid red;
  overflow:hidden;
  resize:both;
}
<div class="heart">
</div>

对于 SVG,如果要保持边框(描边宽度)相同的相对大小,
然后在 resize

上重新计算笔画宽度

path.setAttribute("stroke-width", startWidth / divWidth());

(需要更好的计算)

使用 shadowDOM 包装在 W3C Web 组件中(所有现代浏览器都支持),
封装CSS简单,可以使用多个<my-hearts>标签

<style>
  my-heart { --heartwidth: 80px  }
</style>

<my-heart></my-heart>
<my-heart style="--heartwidth:100px"></my-heart>
<my-heart style="--heartwidth:150px"></my-heart>
<my-heart></my-heart>

<script>
  customElements.define("my-heart", class extends HTMLElement {
    constructor() {
      super() // super sets and returns this scope
        .attachShadow({mode:"open"}) // sets and return this.shadowRoot
        .innerHTML = // no need for a Template
        `<style>:host{display: inline-block}
          div {
            width:var(--heartwidth,100px); height:var(--heartwidth,100px);
            resize:both; overflow:auto;
          }
          svg{  
            width:100%; height:100%; background:#ddd; vertical-align:top;
          }
          </style><div><svg preserveAspectRatio="none" viewBox="0 0 34 34">
    <path fill='lightcoral' stroke='red' stroke-width='1' d='m25 2c-3 0-6 3-8 6c-1-3-4-6-8-6c-4 0-8 4-8 8c0 9 10 12 16 21c6-9 16-12 16-21c0-4-4-8-8-8z'/>
    </svg></div>`; // end innerHTML
      let div = this.shadowRoot.querySelector("div");
      let path = this.shadowRoot.querySelector("path");
      let divWidth = () => ~~getComputedStyle(div).width.replace("px", "");
      let startWidth = divWidth();
      div.onmousemove =e=> path.setAttribute("stroke-width", startWidth / divWidth());
    }
  });
</script>

下面的例子是基于一个简单的web component that is based on iconocss。该示例的缺点是它使用 CSS scale() 来实现您想要的效果,因此需要 Javascript 动态更改比例部分。

html,
body {
  height: 100%;
  width: 100%;
}

:host {
  display: block;
}

pd-indicator:not(:defined) {
  display: none;
}

pd-indicator,
pd-indicator:defined {
  display: block;
  position: absolute;
  top: 20%;
  left: 30%;
  padding: .75rem;
}
pd-indicator:first-child {
  transform: scale(5);
}
pd-indicator:last-child {
  transform: scale(8);
}
<script type="module" src="https://unpkg.com/pd-indicator@1.1.7/pd-indicator.js"></script>
<div class="parent">
  <pd-indicator type="icon-heart" color="000099" active-color="990000"></pd-indicator>
  <pd-indicator type="icon-heart" color="000099" active-color="990000"></pd-indicator>
</div>