聊聊CSS中的圆

发布于 大漠

熟悉CSS的同学都知道,使用CSS可以绘制一些图形,在业内有很多这方面的案例,比如使用CSS绘制不同的纹理CSS绘制Icons、使用一个div绘制不同的图形等等。而在Web的实际开发中也经常会碰到一些图形的运用,比如我们今天要聊的圆(比如圆形容器,圆形缩略图,圆形按钮)。使用CSS绘制圆还是会碰到一些棘手的问题。如果你对这方面感兴趣的话,那么接着阅读下面的内容,你一定会有所收获。

CSS绘制圆的技术方案

在Web中,我们可以使用CSS和SVG等技术手段来绘制圆,大家常见的技术方案主要有:

  • CSS的border-radius
  • CSS的radial-gradient
  • CSS的clip-pathcircle()
  • CSS的shape-outsidecircle()
  • SVG的<circle>

上面这些技术方案都可以绘制出圆形,每种技术都有其优缺点。接下来我们来看看这些技术是如何绘制出圆,能运用于什么样的场景等。

CSS的border-radius

在CSS中绘制圆最常见的技术方案应该是border-radius。不过使用border-radius绘制圆有一个前提条件,那就是容器的widthheight必须相等,而且半径的值是其width(或height)的50%(设置100%同样等效)。比如下面这个示例:

.circle {
    width: 50vh;
    height: 50vh;
    border-radius: 50%; /*也可以是设置100%*/
    background-color: #2a394f;
}

CSS的border-radius属性绘制圆除了设置50%(或100%)之外还可以设置一个超大值(一般只要大小于容器宽度即可)。该特性用于制作类似药丸形状按钮非常有效,比如:

.button {
    width: 100vh;
    min-height: 25vh;
    border-radius: 100vw;
    background-color: #2a394f;
}

实现类似药丸形状按钮时,如果你不知道按钮高度时,可以设置一个任意大的值,比如100vw,甚至是更大的一个值,这样会更安全。

CSS的border-radius同时也会影响到元素的borderbox-shadow以及元素的可触摸(可点击)区域:

上面的示例我们使用的是vh单位(视窗单位),当你改变视窗大小的时候,可以看到圆的大小也随之改变。看上去实现了响应式的圆。其实在CSS中我们还可以利用宽高比的技术方案来实现CSS绘制响应式的圆,只不过需要注意的是宽高比应该采用的1:1的比例

使用border-radius除了绘制圆形之外,我们还可以绘制椭圆,扇形,半圆等等:

在使用border-radius绘制圆形时,有的时候在一些浏览器中会有一些锯齿的边缘。如果你对这方面感兴趣的话,可以阅读下面文章:

比如下面这个示例,对比左右两个圆的效果,仔细看哟:

CSS的radial-gradient

第一次让我领略到CSS渐变的强大之处那就是使用CSS渐变绘制的背景纹理

正如上图所示,我们可以使用radial-gradient来绘制圆形,通过background-image填充到元素中。

.circle {
    background-image: radial-gradient(circle, #d9456f, #d9456f 66%, transparent 66%);
    height: 50vh;
    width: 50vh;
}

使用径向渐变配合background-size属性,我们可以做一些特殊的效果,比如下面这样的一个效果:

使用CSS渐变除了可以绘制圆,还可以绘制其他的一些图形,前面向大家展示过相关的示例。但径向渐变绘制的圆会因为浏览器的不同,圆圈的边缘可能会有锯齿状或模糊的形状(和border-radius有相似之处)。

除此之外,我们还可以使用repeating-radial-gradient()绘制循环的圆:

还可以使用最新的渐变属性conic-gradient()实现下面示例的效果:

有关于repeating-radial-gradient()conic-gradient()的更多介绍,要是感兴趣的话,可以阅读下面相关文章:

如果将repeating-radial-gradient()conic-gradient()和CSS的animation结合起来,还可以实现一些有趣的动效:

CSS中的circle()函数

如今的CSS也有一些函数特性,其中circle()就是图形函数中的一个,可以用来绘制圆。该函数主要用于CSS的shape-outsideshape-insideclip-path几个属性中。目前可能用于clip-path属性要多于shape-outside。其语法很简单:

circle() = circle( [<shape-radius>]? [at <position>]? )

其中<shape-radius>可取值:

<shape-radius> = <length> | <percentage> | closest-side | farthest-side

其中closest-side是默认值,另外<position>可取值:

<position> = [
    [ left | center | right | top | bottom | <length-percentage> ]
    |
    [ left | center | right | <length-percentage> ]
    [ top | center | bottom | <length-percentage> ]
    |
    [ center | [ left | right ] <length-percentage>? ] &&
    [ center | [ top | bottom ] <length-percentage>? ]
]

常见的使用方式:

circle()
circle(100px at 30% 50%)
circle(farthest-side at 25% 25%);
circle(10em at 500px 300px);

其中circle()<shape-radius>取值为closest-sidefarthest-side需要特意拿出来,我用下图来向大家解释,会更一目了然:

前面提到过了,circle()函数可以运用于CSS的clip-pathshape-outside(或者未来的shape-inside)属性上。我们先来看一下被运用于clip-path属性上的效果:

clip-path除了可以绘制一些基本图形之外,而且将其运用于CSS Masking Module Level 1规范MaskingClipping中的话,可以轻易地帮助你实现很多实际需求。

circle()另外还可以运用于CSS Shapes中的shape-outsideshape-inside中,实现一些打破规则布局的效果,比如下图:

比如下图的效果就是circle()被运用于shape-outside中的一个布局效果:

CSS Shapes现代Web布局中与常规布局中唯一与众不同的一种方式,该布局可以打破常规的矩形布局风格,可以实现流水式的布局效果,即打破常规规则布局效果。如果你对这方面的知识感兴趣的话,可以点击这里进行了解

SVG的<circle>

SVG中的<circle>元素是绘制基本图形的其中之一。使用该元素可以轻易的绘制出一个圆形:

<!-- SVG -->
<svg viewBox="0 0 80 80" width="80" height="80">
    <circle class="circle" cx="40" cy="40" r="38"/>
</svg>

// CSS
.circle {
    fill: #f90;
    stroke: red;
    stroke-width: 0.1875em;
}

效果如下:

圆在Web中的运用场景

在Web中,圆的使用场景还是蛮多的,估计大家最为熟悉的应该是用户头像制作成圆形。实现这样的效果,最简单的方式之一就是在<img>上使用border-radius

该方法虽然简单,但对于响应式方面就差强人意。尽管使用了object-fit:cover来防止非正方形图形失真。不过,我们可以通过CSS的技术手段,让头像具备响应式的效果。比如下面这个效果:

其实实现上面示例的效果,除了使用CSS的属性之外,还可以使用SVG来实现,比如下面之个示例:

上面看到的是一些最基本的效果,其实我们还可以实现一些动效,比如下面这个loading的动效:

而SVG制作圆的使用场景也很多,比如在很多图表的运用场景就特别的明显。另外在实现一些圆形进度条,使用SVG会更容易。比如下面这个示例效果:

上面我们看到的是使用SVG绘制圆,或者说实现圆形进度条效果。其实在SVG中,使用<textPath><circle>或者SVG的<path>还可以实现圆形文本环绕的效果:

如果你对SVG方面其他的知识感兴趣的话,可以点击这里阅读更多关于SVG的文章

使用clip-path除了可以在Masking和Clipping的场景运用之外,还可以实现一些其他效果,比如类似支付宝芝麻信用效果:

前面提到过,circle()函数除了可运用于clip-path属性中之外,还可以运用于shape-outsideshape-inside属性中实现一些不规则的布局效果。比如说文本围绕圆形边缘布局或文本在圆形内布局。其中shape-outside在一些主流浏览器中能看到效果,但是shape-inside支持的浏览器有限。如果我们要实现文本在一个圆内排列这样的效果,可以借助shape-outside来模拟。比如下面这个示例:

小结

这篇文章都是聊圆的事情。正如文章中和大家所聊的内容,实现CSS的技术方案有很多种,不同的技术方案可以运用于不同的场景而且每一种实现方案都有其自己的局限性,也有自己的优势。并且可运用的场景也特别多的,大家应该根据自己所需来选择相应的方案。另外,可能上文中还有很多我遗漏的没有想到的方案,如果你在这方面有经验,或者有相应的使用场景,欢迎在下面的评论中与我们一起分享。