Let’s meet Viewport Segments API
Introduction
Chrome VER.138 釋出了一個非常有趣的支援 — Viewport Segments API。透過這個 Web API,web developers 可以針對 fold 類型的 device 做出一些客製化的樣式與操作。
如上圖所示,這是一個地圖 Web APP,便巧妙的利用了 fold dual-screen 的特性,讓左邊區塊顯示地圖資訊,而右邊區塊則顯示地標資訊。藉此讓使用者依照當前 device 以及操作方式可以有更多元的呈現與互動。
雖然說對象僅僅針對 fold 這類型的 mobile device,但是對 front-end 來說便是多了一種與使用者互動、交心的機緣,儘早掌握這類排版設計技巧總是需要的。
Viewport Segments API
Web developers 可以從 window.viewport 下取得 segments 相關資訊。若取得的個數大於 1,則表示目前使用者處與 multi-screen 的狀態。需要特別注意的是 device 僅有在似書本打開立起來放或是似 laptop 打開的樣子下,segments 的個數才會大於 1,倘若是 180 度完全展開模式,則是 segments 個數永遠都會為 1。
const { segments = [] } = window.viewport || {};
const orientation =
window.matchMedia('(orientation: landscape)').matches
? 'landscape'
: 'portrait';
console.log(`Segments count: ${segments.length}`);
console.log(`Orientation: ${orientation}`);如上所示,我們不僅可以知道當前 segments 的個數,更可以搭配 orientation 的資訊來知曉當前是橫式還是直式展開。
CSS viewport segments media query
CSS 亦有釋出對應的 media query 供 web developers 進行樣式上的調整,其基本定義為:
@media (horizontal-viewport-segments: <count>) { }
@media (vertical-viewport-segments: <count>) { }換成人話就是偵測當前水平 / 垂直 viewport segments 個數,目前除了華為出了一隻三折機外,大部分的狀況就是 dual-screen 狀態,所以接下來的範例均會以 2 進行設置。
*-viewport-segments
@media (horizontal-viewport-segments: 2) {
/* styles applied in double-portrait (wide) mode */
/* matches Figure 1. below */
}
@media (vertical-viewport-segments: 2) {
/* styles applied in double-landscape (tall) mode */
/* matches Figure 2. below */
}筆者自身的記憶法是水平切割成兩塊就是用 horizontal-viewport-segments,若是垂直切割成兩塊則為 vertical-viewport-segments。
另外還可以透過 env() 來取得 viewport segments 的各項資訊。
env(viewport-segment-width <x> <y>);
env(viewport-segment-height <x> <y>);
env(viewport-segment-top <x> <y>);
env(viewport-segment-left <x> <y>);
env(viewport-segment-bottom <x> <y>);
env(viewport-segment-right <x> <y>);裡面 x / y 的設定就是左上角為原點,從 0 開始計數(類 grid 區塊劃分)。所以 dual-screen 類型大致上可以有兩種變化來取得各個 viewport segments 的 width / height / top / right / bottom / right 的資訊。
以上圖左邊那個水平切割為例,由左上為原點,所以第一塊的 X Y 座標便是「0 0」,第二塊因為是向右邊長出去,垂直方位沒變化,所以 X Y 座標則為「1 0」
右邊那塊垂直切割則因為水平方位都沒有變化,所以兩塊的 X 座標均為 0,下面區塊則因為向下長出去,所以 Y 座標為 1。
有了這些基礎知識後,如果我們想要取得水平切割右邊區塊的寬度,則可以這麼下:
.demo {
--inline-size: 100px;
inline-size: var(--inline-size);
@media (horizontal-viewport-segments: 2) {
--inline-size: env(viewport-segment-width 1 0);
}
}此外,media query 還有支援另一個和 fold 相關的條件陳述式 — device-posture。可以透過 continuous 以及 folded 來偵測當前 device 是否是 fold 類型且半開闔模式。搭配 *-viewport-segments 就可以玩出更多元的變化。
@media (device-posture: folded) and (orientation: portrait) {
.list-view {
margin-block-end: 60px;
}
}Example
知曉上述的玩具之後,筆者也做了些嘗試。透過實作來驗證其正確性以及深烙到自己技術櫃中。歡迎有興趣的朋友試試看。
<style>
main {
...
...
display: flex;
@media (horizontal-viewport-segments: 2) {
flex-direction: row;
.dimension--A {
flex: 0 0 env(viewport-segment-width 0 0);
}
.dimension--B {
flex: 0 0 env(viewport-segment-width 1 0);
}
}
@media (vertical-viewport-segments: 2) {
flex-direction: column;
.dimension--A {
flex: 0 0 env(viewport-segment-width 0 0);
block-size: env(viewport-segment-height 0 0);
}
.dimension--B {
flex: 0 0 env(viewport-segment-width 0 1);
block-size: env(viewport-segment-height 0 1);
}
}
}
</style>
<main>
<div class="dimension dimension--A" data-dimension="A"></div>
<div class="dimension dimension--B" data-dimension="B"></div>
</main>筆者透過 media query 以及 env() 來設置 dimension — A、dimension — B 的寬高以及排列模式。如此便可以隨著使用者當前手持方位以及開合模式進行調整。
How to test it ?
有越來越多的手機開發商推出了各式各樣 fold 類型裝置,不過基本價位依舊不好入手,尤其像筆者這樣只是單純想玩玩看 Viewport Segments API 的人來說未免太不切實際了。有這方面需求的朋友其實可以弄個模擬器來進行測試。
1.前往 Android Studio 進行下載。
2.由於我們僅僅是要使用模擬器,所以直接打開 Virtual Device Manager
3.如果陳列的裝置沒有你需要的機型,則點擊 + 來新增裝置
4.下載且安裝完後,我們便有一台 Pixel 9 Pro Fold 了
5.如果不是 Chrome VER.138 的話,記得前往 Play Store 進行 update
以上便是簡易的模擬器設定流程。
Conclusion
以上便是 Viewport Segments API 的初體驗,可以透過 Web API 來知曉當前 viewport 資訊外,CSS 亦提供了 media query 以及 env() 來讓 web developers 版型設計上有充足的發揮空間。有興趣的朋友,不妨參照上面範例玩玩看吧!