巧用 CSS 實(shí)現(xiàn) Deepseek 都無(wú)法實(shí)現(xiàn)的復(fù)雜怪狀按鈕 - 內(nèi)凹平滑圓角
本文,我們將探討另外一個(gè)非常有意思的圖形 -- 內(nèi)凹平滑圓角:
有點(diǎn)類似于 Chrome Tab 按鈕造型,此圖形我們?cè)?span> 使用 CSS 輕松實(shí)現(xiàn)高頻出現(xiàn)的各類奇形怪狀按鈕[2] 討論過(guò)如何解決實(shí)現(xiàn)。
常見于這樣的設(shè)計(jì)中:
內(nèi)凹平滑圓角實(shí)現(xiàn)上的難點(diǎn)
上面提到的 Chrome TAB 圖形,常見的解決方案如下:
但是內(nèi)凹平滑圓角實(shí)現(xiàn)上的難點(diǎn)在于 -- 內(nèi)凹部分要求是透明的!
什么意思呢?思考上面的圖形,如果紅色部分要求是整個(gè)透明,而白色部分進(jìn)行顏色填充,試想一下,是不是比較難實(shí)現(xiàn)呢?
巧妙通過(guò) mask 圖形拼接實(shí)現(xiàn)內(nèi)凹平滑圓角
好的,如果不考慮透明這個(gè)因素,要拼接出內(nèi)凹平滑圓角其實(shí)并不困難。
下面我通過(guò)一個(gè)動(dòng)畫,給出內(nèi)凹平滑圓角的拼接過(guò)程:
<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;
}
}
我們能得到這么一個(gè)有意思的變換效果,本質(zhì)上還是不同形狀圖形的拼接,動(dòng)畫示意下,應(yīng)該非常好理解:
當(dāng)然,這里為了讓大家更好的理解,利用了幾個(gè)元素(算上偽元素),并且,實(shí)際最后白色的部分并非透明的!
重點(diǎn)來(lái)了,利用多重 mask 實(shí)現(xiàn)裁剪拼接
如果我們希望白色部分一整個(gè)是透明的,可以如何處理呢?這里就需要運(yùn)用上 mask,通過(guò)在一個(gè)元素內(nèi)部進(jìn)行裁剪、拼接,最終得到一個(gè)鏤空的內(nèi)凹平滑圓角:
<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;
}
效果如下:
并且,它是真實(shí)的支持鏤空的。我們將上面兩種方式實(shí)現(xiàn)的鏤空的內(nèi)凹平滑圓角,放在一個(gè)漸變背景下,就能看出差別:
上述兩種方式的完整代碼,你在這里可以看到:CodePen Demo -- 內(nèi)凹平滑圓角 - inner curve[3]
此方法,最早見于 CSS Shape - Inner Curve/Notch[4],如果覺(jué)得的對(duì)于上述的 CSS 變量有點(diǎn)難以理解,可以通過(guò)上述鏈接[5],實(shí)現(xiàn)角度大小的在線編輯:
AI 挑戰(zhàn)
那么,這種復(fù)雜度的圖形,現(xiàn)在的 AI 模型能夠?qū)崿F(xiàn)嗎?我們嘗試一下,分別把樣式造型傳給 豆包 與 deepseek。
豆包實(shí)現(xiàn)
豆包顯然沒(méi)這個(gè)能力,最終的實(shí)現(xiàn)一看就知道是錯(cuò)誤的。
將代碼貼到 IDE 上,展示為一個(gè)矩形:
deepseek 實(shí)現(xiàn)
再試一下 deepseek。由于 deepseek 不支持不帶文字的圖片,且上傳圖片后補(bǔ)支持聯(lián)網(wǎng)搜索,我們只能盡可能的描述清楚需求:
deepseek 需求描述:使用 HTML +CSS 實(shí)現(xiàn)一個(gè)內(nèi)凹的平滑圓角圖形,類似中文漢字中的凹字,但是凹陷部分是平滑曲線,在凹字上方的四個(gè)拐角,都是平滑曲線。整個(gè)凹字內(nèi)部填充為一個(gè)顏色,其余部分皆為透明色。
deepseek 思考過(guò)程:
好的,我現(xiàn)在需要幫用戶用HTML和CSS實(shí)現(xiàn)一個(gè)內(nèi)凹的平滑圓角圖形,類似“凹”字,但凹陷部分是平滑曲線。整個(gè)內(nèi)部填充顏色,其余透明。首先,我得考慮如何構(gòu)造這樣的形狀。
常見的 CSS 形狀制作方法有幾種:使用邊框、偽元素、clip-path,或者 SVG。因?yàn)樾枰獌?nèi)凹的曲線,可能 clip-path 或徑向漸變比較合適。但 clip-path 的瀏覽器支持可能有問(wèn)題,特別是如果需要更復(fù)雜的路徑的話。或者,可以考慮使用多個(gè)元素疊加,通過(guò)overflow:hidden 來(lái)隱藏部分區(qū)域。
用戶要求凹陷部分是平滑曲線,所以可能需要貝塞爾曲線或者圓形切割。比如,可以用一個(gè)大的矩形,然后在中間用兩個(gè)圓形來(lái)切割出凹陷的效果。或者使用徑向漸變來(lái)創(chuàng)建凹陷的陰影效果,但可能不夠精確。
另一個(gè)思路是使用偽元素。主元素是一個(gè)矩形,然后使用 ::before或 ::after 偽元素來(lái)創(chuàng)建凹陷的部分。比如,主元素設(shè)置背景色,然后用偽元素覆蓋中間部分,形成凹陷。但這樣需要偽元素的形狀是圓形或橢圓,并且通過(guò)定位來(lái)覆蓋中間區(qū)域,同時(shí)設(shè)置mix-blend-mode 或者背景剪切,但可能比較復(fù)雜。
或者,使用 CSS 的 mask 屬性,通過(guò)遮罩來(lái)創(chuàng)建透明區(qū)域。這可能更靈活。比如,創(chuàng)建一個(gè)矩形,然后用徑向漸變作為 mask,中間部分透明,周圍不透明,這樣顯示出來(lái)的就是中間凹陷的形狀。但需要注意瀏覽器兼容性。
或者,使用 SVG 內(nèi)聯(lián),直接繪制路徑,這樣更精確,但用戶可能希望純 CSS 實(shí)現(xiàn)。
再仔細(xì)想,clip-path 屬性可以用多邊形或圓形來(lái)剪切元素。比如,可以定義一個(gè)矩形的 clip-path,然后在中間挖一個(gè)圓形的區(qū)域。但 clip-path 目前不支持排除操作,無(wú)法直接挖洞。可能需要組合多個(gè)形狀。
另一種方法是使用 CSS 漸變。比如,在元素中間放置一個(gè)徑向漸變,從透明到顏色,這樣中間看起來(lái)是凹陷的。但這樣可能只是顏色漸變,而不是真正的形狀凹陷。
或者,使用多個(gè) box-shadow 來(lái)模擬凹陷效果,但可能不夠精確。
綜合考慮,可能使用偽元素疊加的方法。主元素是一個(gè)矩形,設(shè)置 overflow:hidden,然后內(nèi)部有一個(gè)偽元素,定位到中間,用更大的尺寸和背景色,然后通過(guò) border-radius 和 transform 來(lái) 創(chuàng)建凹陷效果。或者,主元素是一個(gè)圓角矩形,然后偽元素是一個(gè)圓形,覆蓋在中間上方,通過(guò)背景色和位移來(lái)形成凹陷。
例如,主元素是一個(gè)矩形,背景色為紅色,然后偽元素是一個(gè)更大的圓形,背景色為透明,通過(guò) border 來(lái)顯示周圍的部分,但這樣可能不太容易。
或者,使用兩個(gè)元素疊加:外部容器是一個(gè)矩形,內(nèi)部有一個(gè)圓形元素,通過(guò)overflow:hidden和定位,讓內(nèi)部元素遮蓋中間部分,形成凹陷。但這樣需要外部容器背景透明,內(nèi)部元素背景色,中間被遮蓋的部分透明,可能比較復(fù)雜。
或者,使用 CSS 的 mask-composite 屬性,但兼容性可能不好。
deepseek 實(shí)現(xiàn)效果
Wow,從我的角度,看上面的分析,deepseek 的思考能力已經(jīng)超強(qiáng)了,并且能夠?qū)?CSS 中一些比較高階的屬性 clip-path、mask、mix-blend-mode 進(jìn)行組合使用,實(shí)屬不易!
最終,看看 deepseek 給出的解法:
<div></div>
div {
position: relative;
margin: auto;
width: 200px;
height: 100px;
}
/* 主體顏色層 */
div::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
background: #2196F3;
clip-path: path('M0 10 Q0 0 10 0 H190 Q200 0 200 10 V40 Q180 50 200 60 V90 Q200 100 190 100 H10 Q0 100 0 90 V60 Q20 50 0 40 V10');
border-radius: 8px;
}
/* 平滑過(guò)渡層 */
div::after {
content: '';
position: absolute;
width: calc(100% - 4px);
height: calc(100% - 4px);
top: 2px;
left: 2px;
background: #2196F3;
clip-path: path('M2 12 Q2 2 12 2 H188 Q198 2 198 12 V38 Q178 50 198 62 V88 Q198 98 188 98 H12 Q2 98 2 88 V62 Q22 50 2 38 V12');
filter: blur(1px);
opacity: 0.8;
}
最終效果如下:
已經(jīng)非常接近了,當(dāng)然,內(nèi)凹上方的曲線并非平滑連接。但是,如此復(fù)雜的圖形,dp 已經(jīng)可以通過(guò)思考過(guò)程,給我們實(shí)現(xiàn)它提供非常多的參考。假以時(shí)日,這種圖形化問(wèn)題,對(duì)于大模型而言,應(yīng)該也都不在話下了。
最后
好了,本文到此結(jié)束,一個(gè)非常有意思的通過(guò) CSS 拼接/裁剪/遮罩方式得到內(nèi)凹圓角的技巧,希望本文對(duì)你有所幫助。
參考資料:
[1]巧用 CSS 實(shí)現(xiàn)高頻出現(xiàn)的復(fù)雜怪狀按鈕 - 鏤空的內(nèi)凹圓角邊框: https://github.com/chokcoco/iCSS/issues/271。
[2]使用 CSS 輕松實(shí)現(xiàn)高頻出現(xiàn)的各類奇形怪狀按鈕: https://github.com/chokcoco/iCSS/issues/152。
[3]CodePen Demo -- 內(nèi)凹平滑圓角 - inner curve: https://codepen.io/Chokcoco/pen/ExqzaXd。
[4]CSS Shape - Inner Curve/Notch: https://css-shape.com/inner-curve/。
[5]上述鏈接: https://css-shape.com/inner-curve/。
[6]Github -- iCSS: https://github.com/chokcoco/iCSS。