灏天阁

WEB前端奇淫巧计-奇妙的头像效果

· Yin灏

简介

在我们的日常开发中,难免会遇到需要显示头像的情况

但是传统的头像显示,仅仅就是一张图片摆在那里,毫无新颖性,既枯燥又乏味,多看几眼还感觉是不是头像中的人物长的有问题,害~,一言难尽

有的时候我精心选的头像,别人都不会多看一眼,甚至就假装没看见一样就草草的把页面关掉,导致用户在浏览自己做的页面时毫无体验感

所谓体验感,就是在浏览页面时,会不由自主的发出:“卧槽,这个牛!”

今天我们要介绍一个头像的展示效果,也许你看起来它实现起来有点难,但是真正实现起来一点都不简单

废话不多说了,开门见山,先看一下最终的效果

test.gif

看见没,是不是很少有看到这样的头像效果,有没有在内心中惊呼,这个牛

注意喔,这个没用到一点 js,是纯 css 实现的

但是这个实现起来雀氏没有我们想象的那么简单,不过我们可以从实现中学到很多知识

错误的想法

有些精通 css 的小伙伴们就说了,这还不简单,分分钟的事
直接在 img 标签外面放个 div,然后 div 直接 overflow:hidden,再加一个 hover 效果,放大图片
不过实现出来可能是这样的
test.gif

看到没,是不是完全感觉不一样

其实我们我们仔细想一下就知道,人物的头部是可以跨过外部的圆圈的,而身体是在圆的内部被隐藏掉的,就光这一点就会让人头皮发麻

具体的实现方案

首先我们先在身体内丢个 img,并引入心怡的图片

<body>
  <img src="./avatar.webp" />
</body>

先看下部分 css

img {
  --size: 280px; /* 头像的尺寸 */
  --borderWidth: 5px; /* 头像外边框的宽度 */
  --borderColor: #c02942; /* 头像边框的颜色*/
  width: var(--size);
  aspect-ratio: 1; /* 头像的宽高比,这里是1:1,也是就现在头像是正方形 */
  padding-top: calc(var(--size) / 5);
  cursor: pointer;
  border-radius: 0 0 calc(var(--size) / 2) calc(var(--size) / 2);
  outline: var(--borderWidth) solid var(--borderColor);
}

先来解释下

css 变量的声明和使用

我们知道在 less 和 sass 中都可以给 css 声明变量,其实在纯 css 中也可以声明变量

--变量名,就是 css 声明变量的方式,后面的值就是给变量赋的值

在使用时直接用 var(–变量名), 就可以取到这个变量的值

举个例子

--size: 280px;
width: var(--size);

等同于

width: 280px;

aspect-ratio

  • 这个属性是定义宽高比的

  • aspect-ratio:1; 这个时候宽高比是 1:1

  • aspect-ratio:4/3; 这个时候宽高比是 4:3

border-radius

  • 这个属性我们经常用,但很少有人知道它可以有四个值

  • border-radius:0 0 140px 140px;

  • 四个值分别对应盒子的是左上,右上,右下,左下四个角

  • border-radius:14px; 就相当于 border-radius:14px 14px 14px 14px;

outline

  • outline 用法和 border 类似,不过作用在 border 外面

image.png

经过以上 css 最终的呈现效果是这样的
image.png

接下来重点来了

background: radial-gradient(
    circle closest-side,
    #ecd078 calc(99% - var(--borderWidth)),
    var(--borderColor) calc(100% - var(--borderWidth)) 99%,
    #0000
  ) center / 100% no-repeat content-box;

background

  • 可详细了解下background,可点击链接查看详情

  • background 其实可以有很多值

  • background: bg-image position/bg-size bg-repeat bg-origin;

例如

background: url(./buouyu.png) center / 100% no-repeat content-box;

url 引入一个图片路径表示要显示的图片

center 表示图片的位置居中

100%表示图片的大小撑满盒子的宽高

no-repeat 表示图片不重复出现

content-box 表示图片只占用盒子的 content 区域,也就是不包含 border 和 padding

注意斜杠前面是 background-position 斜杠后面是 background-size

如 50% 50%/100% 100% 则:

background-position:50% 50%;

background-size:100% 100%;

radial-gradient

  • 注意以上的 url(./buouyu.png) 也可以换成 radial-gradient,也就是把图片换成渐变色

  • 也可详细了解下radial-gradient,点击链接可查看详情

  • radial-gradient(shape size , start-color, …, last-color);

例如

height: 200px;
width: 200px;
background-color: yellow; /* 浏览器不支持的时候显示 */
border-radius: 50%;
background-image: radial-gradient(
  circle closest-side,
  red 90%,
  green 90% 95%,
  #0000
);

在 radial-gradient 里

circle 表示指定圆形的径向渐变

closest-side 表示指定径向渐变的半径长度为从圆心到离圆心最近的边

red 90% 表示从 0 到 90%的区域都是红色

green 90% 95% 表示从 90%到 95%都是绿色

#0000 这个其实是个透明色,#000000 和 #000 都表示黑色,#0000 是 #0000000 的简写,后面两位表示透明度

从 95%到 100%为绿色到透明色的渐变

最终展现出来是这样的

image.png

我们的头像加了那段代码就变成了这样

image.png

到这一步我们发现,头像的上半圆和下半圆并没有对齐

这时我们需要设置下轮廓框架在 border 边缘外的偏移

outline-offset: -5px;

outline-offset

这个表示轮廓和 border 之间的距离

举个例子

border: 2px solid black;
outline: 2px solid red;
outline-offset: 15px;

看下效果

image.png

图片上的黑色框到红色框之间的距离就是 15px

再来看下设置 outline-offset 后我们的头像效果

image.png

哦吼,感觉快完成啦

现在我们需要把圆以外的框框隐藏掉就行啦

-webkit-mask: linear-gradient(#000 0 0) no-repeat 50% calc(
      1px + var(--borderWidth)
    ) / calc(100% - 2 * var(--borderWidth) - 2px) 50%, radial-gradient(
      circle closest-side,
      #000 99%,
      #0000
    ) center / 100% 100% no-repeat content-box;

-webkit-mask 可能有很多小伙伴没见过,别急别急

让我来跟你解释

-webkit-mask

我们来直接看一个例子

background: url("images/logo.png") no-repeat;
-webkit-mask: url("images/mask.png");

看一下原理

image.png

怎么样是不是一目了然,接下来我们需要画出需要显示的区域就行啦

linear-gradient

创建线性渐变的图片

详情可参考官方文档linear-gradient

linear-gradient(#000 0 0)是生成背景为纯黑的图片

height: 200px;
width: 200px;
border: 1px solid red;
background: linear-gradient(#000 0 0) no-repeat 50% 6px / calc(
    100% - 10px - 2px
  )
  50%;

效果是

image.png

加上下面的圆

background: linear-gradient(#000 0 0) no-repeat 50% 6px / calc(
      100% - 10px - 2px
    )
    50%, radial-gradient(
      circle closest-side,
      #000 calc(100% - 6px),
      #0000 calc(100% - 6px) 100%
    ) 50% / 100% 100% no-repeat content-box;

效果是

image.png

此时放在我们头像上就是这样的

image.png

最终的原理就是这样纸

终于能看到一个完整的图片啦

但看上去和普通的头像没什么区别

我们需要加上动画和稍加微调,这是头像的灵魂

下面是完整代码

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>mytest</title>
    <style>
      img {
        --size: 280px;
        /* 头像的尺寸 */
        --borderWidth: 5px;
        /* 头像外边框的宽度 */
        --borderColor: #c02942;
        /* 头像边框的颜色*/
        width: var(--size);
        aspect-ratio: 1;
        /* 头像的宽高比,这里是1:1,也是就现在头像是正方形 */
        padding-top: calc(var(--size) / 5);
        cursor: pointer;
        border-radius: 0 0 calc(var(--size) / 2) calc(var(--size) / 2);
        outline: var(--borderWidth) solid var(--borderColor);
        --f: 1;
        /* 初始化大小*/
        --_g: 50% / calc(100% / var(--f)) 100% no-repeat content-box;
        --_o: calc((1 / var(--f) - 1) * var(--size) / 2 - var(--borderWidth));

        background: radial-gradient(
            circle closest-side,
            #ecd078 calc(99% - var(--borderWidth)),
            var(--borderColor) calc(100% - var(--borderWidth)) 99%,
            #0000
          ) var(--_g);
        outline-offset: var(--_o);
        -webkit-mask: linear-gradient(#000 0 0) no-repeat 50% calc(
              1px - var(--_o)
            ) / calc(100% / var(--f) - 2 * var(--borderWidth) - 2px) 50%, radial-gradient(
              circle closest-side,
              #000 99%,
              #0000
            ) var(--_g);
        transform: scale(var(--f));
        transition: 0.5s;
      }
      img:hover {
        --f: 1.35;
      }
    </style>
  </head>

  <body>
    <img src="./avatar.webp" />
  </body>
</html>

最终效果

test.gif

- Book Lists -