CSS实现圆形头像效果
在Web开发中经常会碰到圆形图像的样式处理。在CSS中我们有很多种方式能实现圆形图形的效果,比如《聊聊CSS中的圆》一文中我们就介绍了很多种技术方案。在这些方案中有大家熟悉的border-radius
,也有不熟悉的clip-path
。这些制作圆形的方案都可以帮助我们实现圆形头像。在这篇文章中,我们就来看看圆形头像的实现方案。
圆形头像使用背景
圆形头像或者说圆形图形在Web的开发中是非常常见,特别是人物头像,很多时候都是以圆形(或带圆形边框的头像):
而源图像有正方形也有长方形,相对来说,正方形图像变成一个圆形要比长方形要容易地多,特别是希望图像正中心在圆心上。但对于长方形来说要难处理一点。在接下来的示例中,我们主要以长方形源图像为例,比如我们有一张像下面这样的图像:
使用border-radius
实现圆形图像
制作圆形图像首先会想到border-radius
,对于正方形的图像,在img
自身上使用border-radius
就能很好的实现圆形图像。
img {
border-radius: 50%;
width: 30vw;
}
从上图中我们可以发现img
并不是正方形,这是图像源本来就不是一个正方形,img
会按图像比例做自动缩放,具体的可以阅读《聊聊img
元素》一文。
如果显式的给img
设置width
和height
属性值,有可能会给图像造成失真或扭曲,但我们可以使用object-fit
和object-position
来防止图像的失真,并且让图像中心原点在正中间:
img {
border-radius: 50%;
width: 30vmin;
height: 30vmin;
object-fit: cover;
object-position: center;
}
在这种场景下要实现带有圆形边框的图像,可以直接使用border
来实现:
有的开发者喜欢在<img>
外面添加一个容器,通过图像的容器来控制正方形,并且在img
上设置max-width: 100%
按正方形的比例来实现圆形图像:
<!-- HTML -->
<div class="img__wrapper">
<img src="https://static.fedev.cn/sites/default/files/blogs/2020/2004/css-circle-image-2.jpg" alt="">
</div>
// CSS
.img__wrapper {
width: 30vmin;
height: 30vmin;
border-radius: 50%;
overflow: hidden;
}
img {
max-width: 100%;
height: auto;
object-fit: cover;
object-position: center;
border-radius: 50%;
}
另外,还可以给<img>
设置绝对定位:
.img__wrapper {
width: 30vmin;
height: 30vmin;
border-radius: 50%;
overflow: hidden;
position: relative;
}
.img__wrapper img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
使用background-image
实现圆形头像
在Web中除了<img>
元素添加图像之外,还可以使用background-image
来添加图像。使用background-image
实现圆形头像的关键是让元素自身是一个正方形,并且让背景图像居中显示。
<!-- HTML -->
<div class="img__wrapper"></div>
// CSS
.img__wrapper {
width: 30vmin;
height: 30vmin;
border-radius: 50%;
overflow: hidden;
background: url('imgUrl') no-repeat center;
background-size: cover;
}
为了让图片不扭曲,在使用background-image
时最好添加background-size: cover
(类似于object-fit: cover
):
使用clip-path
实现圆形头像
在CSS中,除了border-radius
实现圆形之外,还可以使用clip-path
的circle()
函数来绘制圆形。也就是说,我们在img
或其容器上通过clip-path:circle()
实现圆形头像。
<!-- HTML -->
<img src="https://static.fedev.cn/sites/default/files/blogs/2020/2004/css-circle-image-2.jpg" alt="" class="clip__path-1">
// CSS
.clip__path-1 {
clip-path: circle(50% at center);
width: 30vmin;
height: 30vmin;
object-fit: cover;
object-position: center;
}
<!-- HTML -->
<div class="img__wrapper clip__path-2">
<img src="https://static.fedev.cn/sites/default/files/blogs/2020/2004/cat-toes-paw-number-paws-tiger-tabby.jpg" alt="">
</div>
// CSS
.clip__path-2 {
clip-path: circle(50% at center);
width: 30vmin;
height: 30vmin;
}
.clip__path-2 img {
max-width: 100%;
height: auto;
object-fit: cover;
object-position: center;
}
<!-- HTML -->
<div class="img__wrapper clip__path-3"></div>
// CSS
.clip__path-3 {
width: 30vmin;
height: 30vmin;
clip-path: circle(50% at center);
background: url("https://static.fedev.cn/sites/default/files/blogs/2020/2004/css-circle-image-2.jpg")
no-repeat center;
background-size: cover;
}
但使用clip-path
绘制圆形头像时,头像带有边框的话就有所欠缺了:
有关于CSS
clip-path
更详细的介绍可以阅读《探索CSS Masking模块:Clipping》一文。
使用mask
实现圆形头像
CSS中Clipping和Masking模块中除了clip-path
之外还有mask
属性。在mask-image
中我们可以使用一个圆形的图形用来遮盖图像,从而创建一个圆形头像。
作为mask-image
的圆形图像源除了使用图片之外还可以使用CSS的渐变来绘制一个圆形:
.circle {
background-image: radial-gradient(circle, #456BD9, #456BD9 70%, transparent 70%);
height: 5em;
width: 5em;
}
这样来,我们可以将上面渐变绘制的圆形当作mask-image
的图像源:
.mask {
width: 30vmin;
height: 30vmin;
mask-image: radial-gradient(circle, #000, #000 70%, rgba(0, 0, 0, 0) 70%);
mask-position: center;
mask-size: cover;
}
使用
mask
要实现带有边框的圆形头像同样存在clip-path
的现象。
使用SVG绘制圆形头像
除了上面提到的CSS方法之外,还可以使用SVG来绘制圆形头像:
<svg viewBox="0 0 200 200" width="200" height="200">
<title>Avatar</title>
<defs>
<circle id="circle" cx="100" cy="100" r="100" 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://static.fedev.cn/sites/default/files/blogs/2020/2004/cat-toes-paw-number-paws-tiger-tabby.jpg" width="100%" height="100%" preserveAspectRatio="xMidYMid slice" />
</g>
</svg>
响应式圆形头像
我们再来看看响应式的头像效果怎么处理。
小站上有多篇文章介绍过元素宽高比相关的文章,简单地说,就是元素的高度如何根据宽度来变化。
在我们这个示例中,元素的宽和高都是相等的,即是一个正方形(不管是img
自身还是其容器)。在CSS中,我们有很多种方式可以实现类似的效果,最简单的就是通过padding-bottom/top
来实现,比如下面这个示例:
<!-- HTML -->
<div></div>
// CSS
div {
width: 30vmin;
}
div::before {
content: "";
display: block;
width: 100%;
height: 0;
padding-bottom: 100%;
background: #f36;
}
基于这个,就可以很容易实现响应式的圆形头像:
.wrapper {
width: 30vmin;
min-width: 20vmin;
max-width: 80vmin;
overflow: hidden;
resize: horizontal;
border-radius: 50%;
position: relative;
}
.wrapper::before {
content: "";
display: block;
width: 100%;
height: 0;
padding-bottom: 100%;
background: #f36;
}
.wrapper img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: auto;
object-fit: cover;
object-position: center;
}
使用React构建Avatar组件
根据上面的示例,我们可以封装一个React组件,比如Avatar
。创建一个Avatar
组件:
// src/components/Avatar/index.tsx
import * as React from 'react'
interface AvatarProps {
src: string;
width: string;
radius: string;
altDes: string;
}
const Avatar = (props: AvatarProps) => {
const { src, width, radius, altDes, ...rest } = props
const avatarInnerStyle = {
width: '100%',
height: '0',
paddingBottom: '100%',
position: 'relative',
overflow: 'hidden',
borderRadius: `${radius}`,
} as React.CSSProperties;
const imgStyle={
position: `absolute`,
top: `0`,
left: `0`,
width: `100%`,
height: `auto`,
objectFit: `cover`,
objectPosition: `center`,
} as React.CSSProperties;
return <div className="avatar" {...rest} style={{width:`${width}`}}>
<div className='avatar__inner' style={avatarInnerStyle}>
<img src={src} alt={altDes} style={imgStyle} />
</div>
</div>
}
export default Avatar
在需要的地方像下面这样调用Avatar
组件:
<Avatar
src="https://static.fedev.cn/sites/default/files/blogs/2020/2004/cat-toes-paw-number-paws-tiger-tabby.jpg"
width="200px"
altDes="avatar"
radius='50%'
/>
我们创建了一个响应式的Avatar
组件。
我们再来看一个Vue构建的Avatar
组件:
有关于这方面更多的组件还可以查阅:
小结
圆形头像在Web中使用场景很多,文章中向大家介绍了多种实现圆形头像的实现方案,而且每种方案都有其自身的优势。最后封装了一个简单的响应式的Avatar
组件。如果你在这方面有更好的建议或经验,欢迎在下面的评论中与我们共享。