Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

巧用 CSS 实现高频出现的复杂怪状按钮 - 内凹平滑圆角 #272

Open
chokcoco opened this issue Nov 21, 2024 · 0 comments
Open

Comments

@chokcoco
Copy link
Owner

chokcoco commented Nov 21, 2024

接上篇,巧用 CSS 实现高频出现的复杂怪状按钮

上篇中,我们通过渐变的高阶技巧,实现了如下的内凹圆角边框:

本文,我们将探讨另外一个非常有意思的图形 -- 内凹平滑圆角

有点类似于 Chrome Tab 按钮造型,此图形我们在 使用 CSS 轻松实现高频出现的各类奇形怪状按钮 讨论过如何解决实现。

常见于这样的设计中:

内凹平滑圆角实现上的难点

上面提到的 Chrome TAB 图形,常见的解决方案如下:

但是内凹平滑圆角实现上的难点在于 -- 内凹部分要求是透明的

什么意思呢?思考上面的图形,如果红色部分要求是整个透明,而白色部分进行颜色填充,试想一下,是不是比较难实现呢?

巧妙通过 mask 图形拼接实现内凹平滑圆角

好的,如果不考虑透明这个因素,要拼接出内凹平滑圆角其实并不困难。

下面我通过一个动画,给出内凹平滑圆角的拼接过程:

<div class="inner-curve-1">
    <div class="g-rect"></div>
</div>
@property --ca {
  syntax: '<color>';
  inherits: false;
  initial-value: #000;
}
@property --cb {
  syntax: '<color>';
  inherits: false;
  initial-value: #ce03f1;
}
@property --cc {
  syntax: '<color>';
  inherits: false;
  initial-value: #ce03f1;
}

.inner-curve-1 {
    width: 300px;
    height: 100px;
    background: radial-gradient(circle at 50% -10px, var(--cc), var(--cc) 40px, #3f51b5 calc(40px + 0.5px), #3f51b5);
    animation: colorChange 6s infinite linear;
    
    .g-rect {
        position: absolute;
        width: 300px;
        height: 20px;
        left: 0;
        top: -15px;
        background: linear-gradient(90deg,var(--ca), var(--ca) 93px, transparent 93px, transparent calc(300px - 93px), var(--ca) calc(300px - 93px), var(--ca));
        z-index: -1;
        animation: colorChange 6s infinite linear;
        
    }
    
    &::before,
    &::after {
        content: "";
        position: absolute;
        width: 40px;
        height: 40px;
        border-radius: 50%;
        background: var(--cb);
        top: -15px;
        left: 72px;
        animation: colorChange 6s infinite linear;
    }
    
    &::after {
        left: unset;
        right: 72px;
    }
}

@keyframes colorChange {
    0% {
        --ca: #000;
        --cb: #ce03f1;
        --cc: #ce03f1;
    }
    70%,
    100% {
        --ca: #3f51b5;
        --cb: #3f51b5;
        --cc: #fff;
    }
}

我们能得到这么一个有意思的变换效果,本质上还是不同形状图形的拼接,动画示意下,应该非常好理解:

当然,这里为了让大家更好的理解,利用了几个元素(算上伪元素),并且,实际最后白色的部分并非透明的!

重点来了,利用多重 mask 实现裁剪拼接

如果我们希望白色部分一整个是透明的,可以如何处理呢?这里就需要运用上 mask,通过在一个元素内部进行裁剪、拼接,最终得到一个镂空的内凹平滑圆角:

<div class='inner-curve-2'></div>
.inner-curve-2 {
  --r: 20px;  
  --s: 40px;  
  --a: 20deg; 

  --_m:0/calc(2*var(--r)) var(--r) no-repeat
    radial-gradient(50% 100% at bottom,#000 calc(100% - 1px), transparent);
  --_d:(var(--s) + var(--r))*cos(var(--a));

  width: 300px;
  height: 100px;
  mask:
    calc(50% + var(--_d)) var(--_m),calc(50% - var(--_d)) var(--_m),
    radial-gradient(var(--s) at 50% calc(-1*sin(var(--a))*var(--s)),
      transparent 100%,#000 calc(100% + 1px)) 0 calc(var(--r)*(1 - sin(var(--a)))),
    linear-gradient(90deg,#000 calc(50% - var(--_d)), transparent 0 calc(50% + var(--_d)),#000 0);
  mask-repeat: no-repeat;
}

效果如下:

并且,它是真实的支持镂空的。我们将上面两种方式实现的镂空的内凹平滑圆角,放在一个渐变背景下,就能看出差别:

上述两种方式的完整代码,你在这里可以看到:CodePen Demo -- 内凹平滑圆角 - inner curve

此方法,最早见于 CSS Shape - Inner Curve/Notch,如果觉得的对于上述的 CSS 变量有点难以理解,可以通过上述链接,实现角度大小的在线编辑:

最后

好了,本文到此结束,一个非常有意思的通过 CSS 拼接/裁剪/遮罩方式得到内凹圆角的技巧,希望本文对你有所帮助 :)

想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻 😄

更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。

如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。

@chokcoco chokcoco changed the title [WIP]巧用 CSS 实现高频出现的复杂怪状按钮(二) [WIP]巧用 CSS 实现高频出现的复杂怪状按钮 - 内凹平滑圆角 Feb 5, 2025
@chokcoco chokcoco changed the title [WIP]巧用 CSS 实现高频出现的复杂怪状按钮 - 内凹平滑圆角 巧用 CSS 实现高频出现的复杂怪状按钮 - 内凹平滑圆角 Feb 5, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant