头像悬停花式效果

<!-- @format -->

<!DOCTYPE html>
<html lang="zh-CN">
    <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>Document</title>
        <style>
            body {
                margin: 0;
                min-height: 100vh;
                display: grid;
                place-content: center;
                background: #e0e4cc;
            }
            img {
                --s: 280px; /* 图片尺寸 */
                --b: 5px; /* 边框尺寸 */
                --c: #e03770; /* 边框演示 */
                --f: 1; /* 初始缩放比例 */

                width: var(--s);
                aspect-ratio: 1;
                cursor: pointer;

                /* 定义反向缩放变量,content-box 用于确保背景不会超出内容 */
                --g: 50% / calc(100% / var(--f)) 100% no-repeat content-box;
                --o: calc((1 / var(--f) - 1) * var(--s) / 2 - var(--b));
                /* 使用径向渐变生成背景圆及边框 */
                background: radial-gradient(
                        circle closest-side,
                        #01b1af calc(99% - var(--b)),
                        var(--c) calc(100% - var(--b)) 99%,
                        #0000
                    )
                    /* 该变量用于将背景圆圈进行反向缩放 */
                    var(--g);

                /* 通过 outline 创建一个边框,将其与背景圆重叠 */
                /* outline 可以调整定位,而 border 无法调整,因此不使用 border */
                border-radius: 0 0 999px 999px;
                outline: var(--b) solid var(--c);
                /* 需要将 outline 反向缩放以贴合背景圆 */
                outline-offset: var(--o);

                /* 添加顶部填充,只要确保轮廓不会触及图片顶部即可,否则图片会被裁剪 */
                padding-top: calc(var(--s) / 5);

                /* mask 在此处作为最终的一步 */
                /* 这里是一个简单的数学计算,但是代码写起来真是复杂 */
                
                /* 
                    linear-gradient 用于创建上面的矩形部分

                    宽度,等于背景圆的宽度减去边框厚度的两倍
                    同时要将 outline 进行偏移,得到代码为:
                    calc(100% / var(--f) - 2 * var(--b) - 2px)

                    高度,等于元素大小的一半,因此为 50%

                    mask 的定位是先水平再垂直
                    水平定位,50%
                    垂直定位,从顶部偏移与 outline 偏移的值相同
                            但由于 outline 由外移动到内是需要负值,
                            而 mask 正值才是往下移动,因此需要一个 1px 去减,得到代码为:
                            calc(1px - var(--o))
                /* 
                    radial-gradient 用于创建下面的圆形部分

                */
                -webkit-mask: linear-gradient(#000 0 0) no-repeat 50%
                        calc(1px - var(--o)) /
                        calc(100% / var(--f) - 2 * var(--b) - 2px) 50%,
                    radial-gradient(circle closest-side, #000 99%, #0000)
                        var(--g);
                mask: linear-gradient(#000 0 0) no-repeat 50%
                        calc(1px - var(--o)) /
                        calc(100% / var(--f) - 2 * var(--b) - 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="./8.png" alt="" />
    </body>
</html>
Last Updated:
Contributors: af