【翻译】4种CSS画圆的方法
四种方法
1. Border Radius
.circle { background: #456BD9; border: 0.1875em solid #0F1C3F; border-radius: 50%; box-shadow: 0.375em 0.375em 0 0 rgba(15, 28, 63, 0.125); height: 5em; width: 5em; }
将border-radius设为50%是最常见、支持最广泛的方法。border-radius属性同时会影响边框、阴影,以及元素的点击面积。
2. SVG
<svg viewBox="0 0 80 80" width="80" height="80"> <circle class="circle" cx="40" cy="40" r="38"/> </svg>
SVG有circle元素,可以实现圆形。SVG的支持也很广泛,而且用作动画性能很好,但代码量略大。要注意,为了防止圆形视觉上被遮罩,确保圆的半径(如果有笔画宽度,也要加上)比SVG的viewBox略小一点。
3. Clip Path
.circle { background: #456BD9; clip-path: circle(50%); height: 5em; width: 5em; }
Clip path是新的技术。支持也很广但一致性不足。Clip Path不会影响元素的布局,也就是说它不会影响边框,同时会隐藏outer shadow。取决于你所要达到的效果,这可能是有用的。
4. Radial Gradient
.circle { background-image: radial-gradient(circle, #456BD9, #456BD9 66%, transparent 66%); height: 5em; width: 5em; }
我们可以用background-image和radial-gradient来视觉上用圆形填充一个元素。任何内容可以在这个圆形之上,但它的布局(包括可点击面积)不会被影响。这是我最不喜欢的方式,因为不同浏览器下,圆的边缘可能看上去会模糊、锯齿。但它不失为是一个为背景增色的不错办法。
居中内容
任何用来居中元素的CSS方法都可以使用。但有的时候,你会发现内容没有完全的居中。这在元素变小时尤为明显。这种情况不只出现在圆形元素中。
对应代码@codepen
这个问题源于浏览器计算sub-pixel的方法。我们用相对单位、viewport单位或em单位的时候,浏览器可能会计算出非整数的数值。过去,这个问题可能会妨碍栅格布局或者导致其它的问题。现在,浏览器会针对不同的元素、属性、上下文优化计算结果,但仍有不完美。
我的经验是,最灵活的办法就是使用绝对定位来建立一个中心点,然后transform(将子元素移至中心点)
<div class="circle"> <svg class="circle-icon" viewBox="0 0 24 24" width="24" height="24"> <line x1="2" x2="22" y1="5" y2="5" stroke-width="3" stroke-linecap="round"/> <line x1="2" x2="22" y1="12" y2="12" stroke-width="3" stroke-linecap="round"/> <line x1="2" x2="22" y1="19" y2="19" stroke-width="3" stroke-linecap="round"/> </svg> </div>
.circle-icon { fill: currentColor; height: 50%; left: 50%; position: absolute; stroke: currentColor; stroke-width: 0; top: 50%; transform: translate(-50%, -50%); width: 50%; }
剪裁内容
用图片填充一个圆形。
用HTML/CSS
我们可以用border-radius来裁剪一个<img>元素。
.circle { background: rgba(15, 28, 63, 0.125); border-radius: 50%; height: 8em; object-fit: cover; width: 8em; }
局限性:
- 这个元素对于它的容器不是响应式的
- 我们无法应用inner shadow来让这个图片从背景中偏移
- 我们使用object-fit来防止非正方形图片的变形,但这在IE11中未得到支持。
这是一个更精致的例子,解决了以上问题。
使用SVG
使用svg也可以达到相同的效果。但要注意svg的image元素不支持srcset或sizes。
<svg viewBox="0 0 100 100" width="100" height="100"> <title>Tyler</title> <defs> <circle id="circle" cx="50" cy="50" r="49" vector-effect="non-scaling-stroke"/> <clipPath id="circle-clip"> <use xlink:href="#circle"/> </clipPath> </defs> <g clip-path="url(#circle-clip)"> <image xlink:href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/62127/penguin.jpg" width="100%" height="100%" preserveAspectRatio="xMidYMid slice"/> <use xlink:href="#circle" fill="none" stroke="#0F1C3F" stroke-width="2" opacity="0.25"/> </g> </svg>
Sub-pixel 间隙
如果你在圆形元素上增加阴影、边框等属性,可能会注意到一些半像素的缺陷问题。
这个暂时还没有解决方案。
文字环绕
使用shape-outside属性,可以使文字圆形环绕。(注意圆形周围的margin)
内部填充文字
未来w3c可能会有shape-inside属性。目前通过一个hack,可以实现。
但这个方法不是响应式的。通过padding可以达到一个类似的响应式结果。
文字沿着圆周
可以通过SVG和<textPath>元素,让文字沿着圆周。
<svg viewBox="0 0 100 100" width="100" height="100"> <defs> <path id="circle" d=" M 50, 50 m -37, 0 a 37,37 0 1,1 74,0 a 37,37 0 1,1 -74,0"/> </defs> <text font-size="17"> <textPath xlink:href="#circle"> You spin me right round, baby... </textPath> </text> </svg>
并不是所有的浏览器都支持<circle>的<textPath>,但将circle转换为path并不难。