CSS corner-shape, the best partner of border
Introduction
透過 CSS border 渲染,Web developers 總能將 element 點綴得更加雀躍活潑,從 border-radius 盤據 CSS 常用屬性的前幾名便可窺知一二。導圓角的使用總能讓基本的 element shape 多采多姿,不再只是一成不變的方正。除此之外,由於該渲染是屬於即時運算類型,所以不管是 element size 或者是 view scale 的變化,它…總能完美的呈現,銳利中不失柔和,更不會出現擾人的鋸齒補強現象。
CSS > corner-shape
Chrome VER.139 的更新支援了 CSS > corner-shape 這個屬性,更大大的擴展了 border 的使用時機,讓它能有更多元的呈現。它目前支援「round」、「squircle」、「scoop」、「bevel」、「notch」以及「square」等屬性。Web developers 可以依照不同情境進行設置。
以下為基本的設置方式,可以透過 border-radius 改變其「水平」以及「垂直」軸距,再搭配 corner-shape 改變兩點之間的邊線呈現即可。
<style>
.container {
inline-size: 100px;
aspect-ratio: 4/3;
border-radius: 16px;
corner-shape: round;
}
</style>
<div class="container"></div>Understanding CSS corner-shape and the Power of the Superellipse 這篇文章有非常詳盡的介紹,是篇不容錯過的好文。
Example
既然知曉了這些新穎的變化,筆者自然想要透過實例中進行練習以及記憶刻印,恰巧最近浸淫在 PlayStation 的世界中。所以便以 PlayStation 著名的 controller button shape 進行繪製。亦會透過範例跟大家介紹實作方式~
圓形以及正方形單獨使用 border-radius 便可以完成,所以以下僅針對 △ 以及 ✖ 的 CSS 進行介紹。
△ style
<style>
.canvas {
--size: 80px;
--border-size-default: 8px;
--border-size: var(--border-size-default);
--border-color: rgba(236 135 195);
--border-radius: 0;
--corner-shape: initial;
inline-size: var(--size);
aspect-ratio: 1/1;
background-color: rgba(255 255 255/.05);
box-sizing: border-box;
border: var(--border-size) solid var(--border-color);
border-radius: var(--border-radius);
corner-shape: var(--corner-shape);
&.canvas--triangle {
--border-color: rgba(2 224 141);
--corner-shape: bevel;
--border-radius: calc(var(--size) / 2) / var(--size);
border-end-start-radius: 0;
border-end-end-radius: 0;
}
}
</style>
<div class="canvas canvas--triangle"></div>筆者習慣將未來有機會異動的部分抽離成 custom properties,以便未來 maintain。所以可以看到範例把 border 相關屬性進行抽離。
樣式導讀:
- 由於我們要繪製的是三角型,所以筆者先設定 corner-shape 為 bevel,因為想要端點直線連結的樣式。
- 調整 border-radius 的水平以及垂直軸距,水平的部分僅需要容器 50% 寬度,垂直則需要 100% 容器高度。透過 shorthand 寫法,讓四個角都能套用該軸距。
- 因為只需要左上以及右上的 border,所以直接取消左下以及右下的 border-radius。
以上,便可輕鬆繪出 △ 了~
✖ style
<style>
.canvas {
--size: 80px;
--border-size-default: 8px;
--border-size: var(--border-size-default);
--border-color: rgba(236 135 195);
--border-radius: 0;
--corner-shape: initial;
inline-size: var(--size);
aspect-ratio: 1/1;
background-color: rgba(255 255 255/.05);
box-sizing: border-box;
border: var(--border-size) solid var(--border-color);
border-radius: var(--border-radius);
corner-shape: var(--corner-shape);
&.canvas--cross {
--border-color: rgba(96 140 205);
--border-size: calc(var(--border-size-default) / 2);
--border-radius: calc((var(--size) - (var(--border-size) * 2)) / 2);
--corner-shape: notch;
rotate: 45deg;
}
}
</style>
<div class="canvas canvas--cross"></div>和 △ 相比會略微複雜一點點。
樣式導讀:
- 筆者先設定 corner-shape 為 notch,因為想要內凹矩形的呈現效果。
- 由於是兩個 border 做結合,所以如果要維持我們需要的 border-size 就需要減半處理。
- 水平以及垂直軸距均為容器尺寸減掉邊長寬度後再對分。
- 完成上面設置後,我們便可以得到一個 + 的呈現。距離 ✖ 只差一步之遙,這時候對整體旋轉 45 度角後,便可以完成了。
以上便是 △ 以及 ✖ 的 CSS 樣式設置。呼應本文開頭所述,由於是即時運算,所以不管是 element size 或者是 view scale 的變化,它…總能完美的呈現不會出現鋸齒補強現象喔!
以下為完整 sample code,有興趣的朋友也可以點擊這裡一覽實際渲染效果。
<style>
.container {
--gap: 1em;
--size: 80px;
--border-size-default: 8px;
--border-size: var(--border-size-default);
--border-color: rgba(236 135 195);
--border-radius: 0;
--corner-shape: initial;
inline-size: fit-content;
display: flex;
gap: var(--gap);
flex-wrap: nowrap;
.startdust {
position: absolute;
inset-inline-start: attr(data-x type(<length>), 0px);
inset-block-start: attr(data-y type(<length>), 0px);
inline-size: attr(data-size type(<length>), 24px);
aspect-ratio: 1/1;
box-sizing: border-box;
box-shadow: 0 0 1px rgba(0 0 0 / 0.1), 0 2px 4px rgba(0 0 0 / 0.08);
corner-shape: scoop;
border: 8px solid rgba(255 255 255);
border-radius: var(--size);
background-color: rgba(255 255 255);
}
.canvas {
flex-shrink: 0;
inline-size: var(--size);
aspect-ratio: 1/1;
background-color: rgba(255 255 255/.05);
box-sizing: border-box;
border: var(--border-size) solid var(--border-color);
border-radius: var(--border-radius);
corner-shape: var(--corner-shape);
&[data-type=square] {
--border-color: rgba(236 135 195);
--border-radius: 0;
}
&[data-type=triangle] {
--border-color: rgba(2 224 141);
--corner-shape: bevel;
--border-radius: calc(var(--size) / 2) / var(--size); /* horizontal / vertical */
border-end-start-radius: 0;
border-end-end-radius: 0;
}
&[data-type=circle] {
--border-color: rgba(255 0 29);
--border-radius: var(--size);
}
&[data-type=cross] {
--border-color: rgba(96 140 205);
--border-size: calc(var(--border-size-default) / 2);
--border-radius: calc((var(--size) - (var(--border-size) * 2)) / 2);
--corner-shape: notch;
rotate: 45deg;
}
}
}
</style>
<div class="container">
<div class="canvas" data-type="triangle"></div>
<div class="canvas" data-type="circle"></div>
<div class="canvas" data-type="cross"></div>
<div class="canvas" data-type="square"></div>
<div class="startdust" data-size="16px" data-x="-36px" data-y="-38px"></div>
<div class="startdust" data-size="24px" data-x="-18px" data-y="-30px"></div>
<div class="startdust" data-size="6px" data-x="-30px" data-y="-14px"></div>
</div>Feature detect
Web developers 可以透過 CSS 或是 JavaScript 偵測當前環境是否支援 CSS > corner-shape。實作方法如下所示:
CSS:
<style>
@supports (corner-shape: notch) {
/* corner-shape ready */
...
}
</style>JavaScript:
<script type="module">
const supported = CSS.supports('corner-shape', 'notch');
if (supported) {
/* corner-shape ready */
...
}
</script>Conclusion
有了新玩具的加持,相信大家對於 border render 有了更多想像空間,閒暇之餘不妨動手試試看,定會有不同意會。
以上便是筆者透過實作所做的一些分享,感謝您的閱讀亦希望以上內容對於你以及未來得我均能有所助益。 #CSS