如何创建可以流畅调整大小的 CSS 绘图?

How can I create a CSS drawing that resizes fluidly?

如何使我的 CSS 绘图流畅,以便它们可以轻松调整大小并且可以代替 SVG 图像用于网站和应用程序?例如,这张 smiley face 图。目前,window 将其切断,因为它是以绝对单位设置的。我试过使用相对单位而不是像素,但调整大小只会移动图像的所有元素。

有没有JS的方法可以均匀地改变所有单位来制作三四种尺寸的图纸?还是一种使用变量来更改每个元素同时保持相同比例和间距的方法? This 令人惊叹的绘画似乎可以像我希望的那样调整大小,但我无法通过自己查看代码来判断是什么让它响应。

我的示例图像:

  #head {
  height: 500px;
  width: 500px;
  /*   border: px solid yellow; */
  display: block;
  position: absolute;
  background-image: linear-gradient(-70deg, #c9bb34 1%, #fceb51 65%, #fcfcd7);
  left: 100px;
  border-radius: 50%;
  box-shadow: 5px 8px 10px;
}

#smile {
  position: relative;
  height: 200px;
  width: 200px;
  background-image: radial-gradient(#302e29 10%, black);
  left: 150px;
  top: 250px;
  border-radius: 10% 70% 20% 30%;
}

#smile-cover {
  /*   border: 1px solid red; */
  width: 100px;
  height: 170px;
  position: absolute;
  background: #fceb51;
  top: 260px;
  left: 100px;
  border-radius: 0 60% 20% 10%;
}

#left-eye {
  background-image: radial-gradient(#302e29 10%, black);
  position: absolute;
  width: 100px;
  height: 100px;
  top: 110px;
  border-radius: 50%;
  box-shadow: 5px 8px 10px;
}

#right-eye {
  background-image: radial-gradient(#302e29 1%, black);
  position: absolute;
  width: 130px;
  height: 150px;
  top: 100px;
  left: 240px;
  border-radius: 50%;
  box-shadow: 2px 2px 10px;
}

#left-eye-highlight {
  position: absolute;
  width: 18px;
  height: 23px;
  background-image: linear-gradient(#fceb51, #fcfcd7);
  top: 125px;
  left: 58px;
  /*   border: 1px solid red; */
  border-radius: 25% 60%;
}

#right-eye-highlight {
  position: absolute;
  width: 20px;
  height: 30px;
  background-image: linear-gradient(#fceb51, #fcfcd7);
  top: 125px;
  left: 320px;
  /*   border: 1px solid red; */
  border-radius: 25% 70%;
}

#left-eye-bottom {
  position: absolute;
  width: 70px;
  height: 60px;
  /*   border: 1px solid red; */
  border-radius: 50%;
  background-image: linear-gradient(-70deg, #fceb51 1%, #fcfcd7);
  transform: rotate(20deg);
  top: 190px;
  left: 10px;
}

#right-eye-bottom {
  position: absolute;
  width: 120px;
  height: 60px;
  /*   border: 1px solid red; */
  border-radius: 50%;
  background-image: linear-gradient(-45deg, #e3d234 1%, #fceb51 80%, #fcfcd7);
  transform: rotate(20deg);
  top: 210px;
  left: 230px;
<div id="head">
  <div id="smile"></div>
  <div id="smile-cover"></div>
  <div id="left-eye"></div>
  <div id="right-eye"></div>
  <div id="left-eye-highlight"></div>
  <div id="right-eye-highlight"></div>
  <div id="left-eye-bottom"></div>
  <div id="right-eye-bottom"></div>
</div>

}

您可以将所有固定的 px 单位更改为 %。首先,您需要定义 widthheight 的基数,然后您需要找到任何统计数据与 width / height (padding-right / widthpadding-top / height)。在这种情况下,widthheight 都等于 500px,这样就很简单了。

计算方法:

  1. #head 的基础值为 500 - width & height。暂时不要更改它们。
  2. 取一个固定值(100px),计算100 / 500 * 100得到百分比值。
  3. 用结果20%替换固定值。
  4. 运行代码看一切都还在原地
  5. 重复 2-4 所有固定单元(除了头部的 width/height)都被替换了。
  6. 替换头部的 widthheight 值。我使用 vmin 值,您可以从 JS 控制它们。

结果:

#head {
  height: 100vmin;
  width: 100vmin;
  /*   border: px solid yellow; */
  display: block;
  position: absolute;
  background-image: linear-gradient(-70deg, #c9bb34 1%, #fceb51 65%, #fcfcd7);
  left: 20%;
  border-radius: 50%;
  box-shadow: 1% 1.6% 2%;
}

#smile {
  position: relative;
  height: 40%;
  width: 40%;
  background-image: radial-gradient(#302e29 10%, black);
  left: 30%;
  top: 50%;
  border-radius: 10% 70% 20% 30%;
}

#smile-cover {
  /*   border: 1px solid red; */
  width: 20%;
  height: 34%;
  position: absolute;
  background: #fceb51;
  top: 52%;
  left: 20%;
  border-radius: 0 60% 20% 10%;
}

#left-eye {
  background-image: radial-gradient(#302e29 10%, black);
  position: absolute;
  width: 20%;
  height: 20%;
  top: 22%;
  border-radius: 50%;
  box-shadow: 1% 1.6% 2%;
}

#right-eye {
  background-image: radial-gradient(#302e29 1%, black);
  position: absolute;
  width: 26%;
  height: 30%;
  top: 20%;
  left: 48%;
  border-radius: 50%;
  box-shadow: 0.4% 0.4% 2%;
}

#left-eye-highlight {
  position: absolute;
  width: 3.6%;
  height: 4.6%;
  background-image: linear-gradient(#fceb51, #fcfcd7);
  top: 25%;
  left: 11.6;
  /*   border: 1px solid red; */
  border-radius: 25% 60%;
}

#right-eye-highlight {
  position: absolute;
  width: 4%;
  height: 6%;
  background-image: linear-gradient(#fceb51, #fcfcd7);
  top: 25%;
  left: 64%;
  /*   border: 1px solid red; */
  border-radius: 25% 70%;
}

#left-eye-bottom {
  position: absolute;
  width: 14%;
  height: 12%;
  /*   border: 1px solid red; */
  border-radius: 50%;
  background-image: linear-gradient(-70deg, #fceb51 1%, #fcfcd7);
  transform: rotate(20deg);
  top: 38%;
  left: 2%;
}

#right-eye-bottom {
  position: absolute;
  width: 24%;
  height: 12%;
  /*   border: 1px solid red; */
  border-radius: 50%;
  background-image: linear-gradient(-45deg, #e3d234 1%, #fceb51 80%, #fcfcd7);
  transform: rotate(20deg);
  top: 42%;
  left: 46%;
}
<div id="head">
  <div id="smile"></div>
  <div id="smile-cover"></div>
  <div id="left-eye"></div>
  <div id="right-eye"></div>
  <div id="left-eye-highlight"></div>
  <div id="right-eye-highlight"></div>
  <div id="left-eye-bottom"></div>
  <div id="right-eye-bottom"></div>
</div>

您可以使用 vh、vw 或 vmax 单位

这些不同单位的例子

/* for test purpose */
#px:checked~#head {
  --unit: 1px;
}

#vh:checked~#head {
  --unit: 0.1vh;
}

#vw:checked~#head {
  --unit: 0.1vw;
}

#vmin:checked~#head {
  --unit: 0.1vmin;
}

#vmax:checked~#head {
  --unit: 0.1vmax;
}
/* var() inside calc() is used for test and update value's unit */
* {transition:0.5s}
#head {
  height: calc( var(--unit) * 500);
  width: calc( var(--unit) * 500);
  /*   border: px solid yellow; */
  display: block;
  position: absolute;
  background-image: linear-gradient(-70deg, #c9bb34 1%, #fceb51 65%, #fcfcd7);
  left: calc( var(--unit) * 100);
  border-radius: 50%;
  box-shadow: 5px 8px 10px;
}

#smile {
  position: relative;
  height: calc( var(--unit) * 200);
  width: calc( var(--unit) * 200);
  background-image: radial-gradient(#302e29 10%, black);
  left: calc( var(--unit) * 150);
  top: calc( var(--unit) * 250);
  border-radius: 10% 70% 20% 30%;
}

#smile-cover {
  /*   border: 1px solid red; */
  width: calc( var(--unit) * 100);
  height: calc( var(--unit) * 170);
  position: absolute;
  background: #fceb51;
  top: calc( var(--unit) * 260);
  left: calc( var(--unit) *100);
  border-radius: 0 60% 20% 10%;
}

#left-eye {
  background-image: radial-gradient(#302e29 10%, black);
  position: absolute;
  width: calc( var(--unit) * 100);
  height: calc( var(--unit) * 100);
  top: calc( var(--unit) * 110);
  border-radius: 50%;
  box-shadow: 5px 8px 10px;
}

#right-eye {
  background-image: radial-gradient(#302e29 1%, black);
  position: absolute;
  width: calc( var(--unit) * 130);
  height: calc( var(--unit) * 150);
  top: calc( var(--unit) * 100);
  left: calc( var(--unit) * 240);
  border-radius: 50%;
  box-shadow: 2px 2px 10px;
}

#left-eye-highlight {
  position: absolute;
  width: calc( var(--unit) * 18);
  height: calc( var(--unit) * 23);
  background-image: linear-gradient(#fceb51, #fcfcd7);
  top: calc( var(--unit) * 125);
  left: calc( var(--unit) * 58);
  /*   border: 1px solid red; */
  border-radius: 25% 60%;
}

#right-eye-highlight {
  position: absolute;
  width: calc( var(--unit) * 20);
  height: calc( var(--unit) * 30);
  background-image: linear-gradient(#fceb51, #fcfcd7);
  top: calc( var(--unit) * 125);
  left: calc( var(--unit) * 320);
  /*   border: 1px solid red; */
  border-radius: 25% 70%;
}

#left-eye-bottom {
  position: absolute;
  width: calc( var(--unit) * 70);
  height: calc( var(--unit) * 60);
  /*   border: 1px solid red; */
  border-radius: 50%;
  background-image: linear-gradient(-70deg, #fceb51 1%, #fcfcd7);
  transform: rotate(20deg);
  top: calc( var(--unit) * 190);
  left: calc( var(--unit) * 10);
}

#right-eye-bottom {
  position: absolute;
  width: calc( var(--unit) * 120);
  height: calc( var(--unit) * 60);
  /*   border: 1px solid red; */
  border-radius: 50%;
  background-image: linear-gradient(-45deg, #e3d234 1%, #fceb51 80%, #fcfcd7);
  transform: rotate(20deg);
  top: calc( var(--unit) * 210);
  left: calc( var(--unit) * 230);
}
<!-- for test purpose -->
Resize smiley from unit :
<input type=radio name="unit" checked id="px">
<label for="px">px</label>
<input type=radio name="unit" id="vh">
<label for="px">vh</label>
<input type=radio name="unit" id="vw">
<label for="px">vw</label>
<input type=radio name="unit" id="vmin">
<label for="px">vmin</label>
<input type=radio name="unit" id="vmax">
<label for="px">vmax</label>
<!-- end test tag -->

<div id="head">
  <div id="smile"></div>
  <div id="smile-cover"></div>
  <div id="left-eye"></div>
  <div id="right-eye"></div>
  <div id="left-eye-highlight"></div>
  <div id="right-eye-highlight"></div>
  <div id="left-eye-bottom"></div>
  <div id="right-eye-bottom"></div>
</div>

分叉https://codepen.io/gc-nomade/pen/wvvQYzy

一些信息https://web-design-weekly.com/2014/11/18/viewport-units-vw-vh-vmin-vmax/

关于演示和 css 变量 https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties