如何用有趣的形状、字形和表情符号创建CSS图表

163 阅读5分钟

让我们放弃我们通常在图表中看到的圆形和条形,而采用更古怪的形状。随着在线演示越来越普遍,一个快速的方法是给图表做一个形状上的改造,从而使你的网页幻灯片变得更加突出🪄。

我将向你展示如何使用字形、CSS形状和emojis,以最小的努力创建具有有趣形状的图表。

让我们从一个简单的例子开始。

使用字形

<div id="chart">
  <div id="chart-shape">⬠</div>
  <div id="chart-value"></div> 
</div>
#chart {
  width: 300px; 
  height: 300px;
  display: grid;
  background: white;
}
#chart * {
  height: inherit;
  grid-area: 1 / 1;
}

我们首先给图表一些尺寸,并通过将它们分配到同一个网格单元来堆叠里面的两个div。它们也可以使用任何其他方式堆叠起来--比如说,使用position 属性。

再看一下上面的HTML。其中一个div有一个五边形符号--我们想要的图表形状。我使用 "Emoji and Symbols "键盘添加了这个符号,尽管它也可以用五边形的HTML实体值&#x2B20; ,在div内完成。

然后用CSS字体属性以及所需的图表颜色对带有该符号的div进行样式设置。它足够大并且居中。

#chart-shape {
  font: 300px/300px serif;
  text-align: center; 
  color: limegreen;
}

到HTML中的第二个div包含一个圆锥梯度背景图像。梯度的百分比代表了图表的视觉价值。同一个div也有mix-blend-mode: screen;

#chart-value {
  background: conic-gradient(transparent 75%, darkseagreen 75%);
  mix-blend-mode: screen;
}

mix-blend-mode属性将元素内部的颜色与背景相混合。screen 混合模式的值会导致较浅的混合。在darkseagreen 彩色圆锥渐变部分与limegreen 彩色五角星重叠的部分显示出较浅的绿色,而darskseagreen 渐变的其余部分则在图表的白色背景下消失了。

在HTML中添加图表形状的另一种方法是在CSS中把它作为另一个背景层,并使用。 [background-blend-mode](https://css-tricks.com/almanac/properties/b/background-blend-mode/)而不是mix-blend-mode 。然而,CSS中的图表形状的代码在快速浏览时可能不太清晰。因此,你要看在哪里添加图表形状会更容易。HTML或CSS。你有两种选择。

#chart {
  width: 300px; 
  height: 300px;
  background:
  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><div xmlns='http://www.w3.org/1999/xhtml' style='font:300px/300px serif;color:limegreen;text-align: center;background:white'>⬠</div></foreignObject></svg>"),
  conic-gradient(transparent 75%, darkseagreen 75%);
  background-blend-mode: screen;
}

除了圆锥渐变外,五边形符号被添加为背景图像。然后,最后,属性-值对background-blend-mode: screen; ,结果看起来与之前的演示相同。

五角形背景图像是通过将带有五角形符号的HTML ()嵌入到一个SVG中来创建的,这个SVG被嵌入到一个数据URL中。

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='100%'>
    <div xmlns='http://www.w3.org/1999/xhtml' 
         style='
          font:300px/300px serif;
          color:limegreen;
          text-align: center;
          background:white;'></div>
  </foreignObject>
</svg>

在CSS中就变成了这样。

background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><div xmlns='http://www.w3.org/1999/xhtml' style='font:300px/300px serif;color:limegreen;text-align: center;background:white'></div></foreignObject></svg>");

使用CSS形状

接下来,让我们用CSS形状来代替符号。CSS形状主要是通过使用边框属性来创建的。我们在档案中收集了一些CSS形状供你参考。

这里有一组属性,可以在我们稍后添加到SVG中的一个元素中创建一个简单的三角形形状,取代符号。

border: 150px solid white; 
border-bottom: 300px solid lime; 
border-top: unset;

当与圆锥形渐变和背景混合在一起时,结果是。

<div id="chart"></div>
#chart {
  width: 300px;
  height: 300px;
  background:
  url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><html xmlns='http://www.w3.org/1999/xhtml'><div style='border:150px solid white; border-bottom:300px solid lime; border-top:unset'></div><div style='border:150px solid transparent; border-bottom:300px solid white; border-top:unset; transform:scale(0.8) translateY(-360px);'></div></html></foreignObject></svg>"),
  conic-gradient(transparent 75%, darkseagreen 75%);
  background-blend-mode: screen;
}

为了将设计限制在边界上,在设计中加入了一个较小的白色三角形。

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='100%'>
   <html xmlns='http://www.w3.org/1999/xhtml'>
    /* green triangle */
    <div style='
         border: 150px solid white; 
         border-bottom: 300px solid lime; 
         border-top: unset'></div>
    /* smaller white triangle */
    <div style='
         border: 150px solid transparent; 
         border-bottom: 300px solid white; 
         border-top: unset; 
         transform: scale(0.8) translateY(-360px);'></div>
   </html>
  </foreignObject>
</svg>

这一点,在CSS中又变成了这样。

background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='100%'><html xmlns='http://www.w3.org/1999/xhtml'><div style='border:150px solid white; border-bottom:300px solid lime; border-top:unset'></div><div style='border:150px solid transparent; border-bottom:300px solid white; border-top:unset; transform:scale(0.8) translateY(-360px);'></div></html></foreignObject></svg>");

使用emojis

emojis能与这种方法的图表一起使用吗?你肯定会的!🥳

一个块状颜色的表情符号被送入SVG图像,与HTML符号的方式相同。表情符号的块状颜色是通过给它一个透明的color ,然后再添加一个想要的颜色作为text-shadow 。我在另一篇文章中介绍了这种技术。

<div id="chart"></div>
#chart {
  width: 300px; 
  height: 300px;
  background: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='300px'><body style='margin:0;text-align:center;color:transparent;' xmlns='http://www.w3.org/1999/xhtml'><div style='text-shadow: 0 0 limegreen;font:200px/300px serif;background:white;'>🍏</div><div style='text-shadow:0 0 white;font:170px/300px serif;position:relative;top:-300px;'>🍏</div></body></foreignObject></svg>"),
  conic-gradient(transparent 64%, darkseagreen 64%);
  background-blend-mode: screen;
}

就像上一个演示一样,在中心添加一个较小的白色苹果形状,以创建边界设计。

<!-- Unwrapped SVG code from the Data URL -->
<svg xmlns='http://www.w3.org/2000/svg'>
  <foreignObject width='300px' height='300px'>
    <body xmlns='http://www.w3.org/1999/xhtml' style='
          margin: 0;
          text-align: center;
          color:transparent;'>
       /* green apple shape */
       <div style='
            text-shadow: 0 0 limegreen; 
            font-size: 200px; 
            background: white;'>🍏</div>
       /* smaller white apple shape */
       <div style='
            text-shadow:0 0 white; 
            font-size: 170px; 
            position: relative; 
            top: -300px;'>🍏</div>
    </body>
  </foreignObject>
</svg>

我在<body> 元素内添加了两个div,这样div的重复样式属性就只在body元素中声明一次。然后,这些div将自动继承这些属性。

克里斯有一个想法,就是将圆锥梯度--具体来说就是它的百分比值--做成动画,使用CSS [@property](https://css-tricks.com/property/)(@property 是一个明确定义自定义CSS属性的CSS at-rule。在支持的浏览器中,当使用@property 来定义一个自定义属性时,它可以被动画化。

@property --n {
  syntax: '<percentage>';
  inherits: true;
  initial-value: 30%;
}
#chart {
  width: 300px; 
  height: 300px;
  --n: 30%;  /*declaration for browsers with no @property support */
  background: 
    url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg'><foreignObject width='300px' height='300px'><body style='margin:0;text-align:center;color:transparent;' xmlns='http://www.w3.org/1999/xhtml'><div style='text-shadow: 0 0 limegreen;font:200px/300px serif;background:white;'>🍏</div><div style='text-shadow:0 0 white;font:170px/300px serif;position:relative;top:-300px;'>🍏</div></body></foreignObject></svg>"),
    conic-gradient(transparent var(--n), darkseagreen var(--n));
  background-blend-mode: screen;
  transition: --n 2s ease-in-out	
}
#chart:hover { --n: 70%; }

上面的图表将在悬停时改变其值。在Chrome浏览器中,这种变化将看起来是动画的。

虽然它不会像CSS动画那样平滑,但你也可以尝试用JavaScript来制作梯度动画。当光标在图表上移动时,下面的JavaScript将引起与上面有点类似的动画效果。

const chart = document.querySelector('#chart')
chart.onpointerover = ()=>{
  var i = 30,
      timer = setInterval(()=> {
        if (i < 70)
          chart.style.setProperty('--n', i++ + '%')
        else clearInterval(timer)
      }, 10)
}
chart.onpointerout = ()=>{
  var i = 70,
      timer = setInterval(()=> {
        if (i >= 30) 
          chart.style.setProperty('--n', i-- + '%')
        else clearInterval(timer)
      }, 10)
}

当尝试你自己的设计时,请记住不同的混合模式是如何工作的。我在我所有的演示中使用了screen 混合模式,只是为了保持简单。但不同的混合模式,以及不同的背景颜色,你会得到不同的结果。所以,我建议如果你还没有深入了解 混合模式的话。

另外,如果你想把一个元素的颜色从最终结果中排除,可以试试isolation: isolate; ,在应用混合模式时,浏览器会忽略这个背景色。

即使有各种不寻常的古怪形状,我们也可以使用任何我们想要的野生颜色,但始终要注意可读性,使图表值足够大和清晰。