原文:https://ishadeed.com/article/container-queries-for-designers/
作者:Ahmad Shadeed
譯者:Levix
網頁設計工作包括處理不同螢幕尺寸的設計,基於這些設計,開發人員使用 CSS 媒體查詢來監測視口寬度或高度,然後基於此更改設計。我們在過去的 10 年裡就是這樣設計網頁佈局的,而且它即將變得更好,我有一些好消息要告訴你。
CSS 容器查詢是網頁開發者長期以來夢寐以求的功能,即將出現在 CSS 中,現在作為 Chrome Canary 的一項試驗性功能。在本文,我將詳細介紹它是什麼,它將如何改變設計師的工作流程等等。我並不關心你是否是一個會敲代碼的設計師,因為本文的重點是介紹這一概念,以便為下一篇文章做好準備。如果你碰到完全不懂的 CSS bits(概念),你完全可以選擇跳過它們並繼續學習。
廢話不多說,我們開始吧!
響應式設計的現狀#
現在,在同一個網頁佈局的多個版本上設計仍然是可以的,以顯示內部部分將如何根據視口寬度而變化,我們設計不同的尺寸,如手機、平板電腦和桌面。
在上圖中,設計師創造了同一設計風格下的三種不同展現方式,因此開發者可以知道如何根據它進行相應開發,到目前為止,一切都挺順暢的。
現在,我將向你展示更詳細的設計和它的變化,這樣我可以闡明 CSS 容器查詢將為我們解決的問題。
注意,這是同一個組件包含著三種風格,分別是默認、card 以及 featured,作為一名設計師,你已經使用了多個版本的佈局來展示它,這就像是在說:“這是文章組件在手機上的佈局風格,而這是它在平板電腦上的風格”。
在 CSS 中,開發者需要針對該組件創建三種風格,並且每一種都是獨一無二的,參考下面的基礎樣式:
.c-media {
/* 默認樣式 */
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
@media (min-with: 400px) {
.c-media--card {
display: block;
}
.c-media--card img {
margin-bottom: 1rem;
}
}
@media (min-with: 1300px) {
.c-media--featured {
position: relative;
/* 其他樣式 */
}
.c-media--featured .c-media__content {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
}
上述(三種)風格差異取決於媒體查詢或者視口寬度,意味著我們不能根據其父容器寬度去控制它們。現在你可能在想,這有什麼問題?嗯,這是個好問題。
問題是開發者被限制住了,只能在視口寬度大於某個特定值時使用一個組件的特定樣式類。例如,如果我想在平板電腦中使用 “featured” 類,那就行不通了,為什麼?因為它的媒體查詢在視口寬度大於等於 1300px
時啟動。
不僅如此,我們還可能面臨內容比預期少的問題,有時候,創作者只會添加一篇文章,而設計稿中包含了三篇,在這種情況下,要麼我們有一個空白區域,要麼文章會適配展開以填充可用空間,請看下圖:
在第一種情況下,文章太寬導致正在使用的圖像被破壞(拉伸),而在第二種情況下,效果是相同的,但有更多的網格項正在擴大以填補可用空間,這(體驗)並不是很好。
如果使用容器查詢,我們可以通過查詢父容器來決定如何顯示特定的組件去解決這些問題。請看下圖,它展示了我們如何使用容器查詢來解決這個問題。
因此,我們將解決思路轉移到組件的父容器上會發生什麼呢?換句話說,如果我們查詢其父容器,根據其父容器的寬度或高度來決定組件的外觀,該怎麼辦?讓我們來了解下容器查詢的概念。
什麼是容器查詢?#
首先,讓我定義一個容器,包含著其他子元素的元素,有時被稱為一個 wrapper(包裝器),如果你有興趣了解更多關於容器的信息,我有一篇完整的文章。
容器查詢的功能現在可以在 Chrome Canary 瀏覽器的 flag 下開啟(譯者注,指的是 chrome://flags
)。感謝 Miriam Suzanne 以及其他朋友的努力。
當一個組件被放在一個容器中時,代表著它被包含在該容器中,這意味著,我們可以查詢其父容器的寬度並基於此對其進行修改。請看下圖:
注意,每張卡片都有一條黃色的輪廓線,它代表每個組件的父容器。通過 CSS 容器查詢,我們可以基於其父組件的寬度來修改組件,為了更清楚地說明這一點,以下是上述(佈局)的 HTML 代碼:
<div class="o-grid">
<div class="o-grid__item">
<article class="c-media"></article>
</div>
<!-- + more items -->
</div>
該子組件具有 .c-media
類,它的父容器是 .o-grid__item
元素,在 CSS 中,我們可以這樣做:
.o-grid__item {
contain: layout inline-size style;
}
.c-media {
/* 默認樣式 */
}
@container (min-width: 320px) {
.c-media {
/* 樣式 */
}
}
@container (min-width: 450px) {
.c-media {
/* 樣式 */
}
}
首先,我們告訴瀏覽器每個具有 .o-grid__item
類的元素都是一個容器,接著,我們告訴瀏覽器,如果父元素的寬度大於或等於 320px,它就應該呈現出不同的佈局,對於 450px 的查詢也是如此,這就是 CSS 容器查詢的工作方式。
此外,我們可以在任何地方定義它們,也就是說如果需要的話,我們可以在頂層容器上進行查詢。現在你已經了解了 CSS 容器查詢的基本概念,我想給你展示如下圖片。
在左側,這是一個正在調整尺寸的視口,在右側,一個組件(佈局)根據其父組件的寬度改變,這就是容器查詢的強大和有用之處。
如果你想進一步了解容器查詢的 CSS 細節,我寫了一篇關於它的詳細文章。
設計時考慮容器查詢#
作為一名設計師,你需要適應這個革命性的 CSS 功能,因為它將改善我們設計網頁和編寫 CSS 的方式。我們不僅會針對螢幕尺寸進行設計,還要考慮到組件在其容器寬度改變時應該如何適配。
現在,設計系統越來越受歡迎,設計團隊會構建一套規則和組件,以便其他成員可以基於此構建頁面,隨著 CSS 容器查詢的到來,我們還需要在設計組件時,考慮應該如何根據其父容器寬度進行適配。
考慮如下設計:
請注意,我們有標題欄、文章部分、引言和通訊,它們每一個都應該適應視口或其父容器寬度。
我可以設想將組件分為以下幾部分:
- 視口(媒體查詢)
- 父容器(容器查詢)
- 通用型:不受影響的組件,如按鈕、標籤、段落。
對於示例的用戶界面,我們可以這樣劃分組件。
當我們以這種思維方式設計用戶界面時,我們可以開始考慮組件不同的變化,這些變化取決於它們的父容器寬度,讓我們來探討一下。
在下圖中,請注意文章組件的每個變化是如何在特定的寬度中發揮作用的。
作為一名設計師,基於父容器寬度考慮如何設計,一開始可能有點奇怪,但這就是未來的發展趨勢,我們向前端開發人員提供每個組件的細節和變化,他們可以使用它們(的規範進行編碼)。
不僅如此,我們可能還有一個組件的佈局,它只在特定的環境下顯示,例如,事件列表頁面,在這種情況下,明確在哪裡使用這個佈局是很重要的。
問題是,如何告訴設計師應該在哪裡使用這些組件?
與開發人員溝通#
良好的溝通是項目成功的一個重要因素,作為一名設計師,希望你能提供指導,說明組件不同的適配應該用在哪裡,它可以是一個完整的頁面設計,也可以是一個顯示每個組件如何使用的簡單圖片。
讓我們將其應用於我們之前討論的文章組件。
請注意我如何將每個變化映射到特定上下文,而不是視口。為了進一步證明這一點,我想向你展示該組件在與 CSS grid 一起使用時會有什麼不同。
在 CSS grid 佈局中,我們可以通過使用 auto-fit
關鍵字來告訴瀏覽器,如果列的數量少於預期時,我們希望它能夠延伸(你可以閱讀更多關於它的信息這裡)。這個功能很強大,因為它可以幫助我們在同一環境下顯示不同的變化。請看下圖:
擁有一個能根據其父容器寬度做出自適應的組件是非常有用的,正如你剛才看到的,我們在桌面尺寸上查看一個頁面,並且有不同的部分,每一個部分的列數都不一樣。
設計響應式組件時要避免複雜化#
重要的是要記住,一個組件的內部組成結構就像樂高遊戲,你可以根據當前變化對它們進行排序,但凡事都有一個度,有時候,對於前端開發人員來說,與其用容器查詢來實現自適應,還不如去實現一個全新的組件。
請考慮以下幾點。
它有以下幾點:
- 頭像
- 名稱
- 按鈕
- 鍵 / 值對
如果內部結構保持不變,或者至少不包含新的結構,我們可以修改組件,並有以下多種不同佈局。
CSS 容器查詢的使用案例#
讓我們來探討一些可以使用 CSS 容器查詢實現的案例。
聊天列表#
我在 Facebook messenger 上看到了這種模式,聊天列表根據視口寬度變化,我們可以使用 CSS 容器查詢來實現。
當有足夠的空間時,列表會展開並顯示每個用戶的名字,聊天列表的父元素可以是一個被動態調整大小的元素(例如:通過使用 CSS 視口單位,或 CSS 比較功能)。
下面是我們如何在 CSS 中實現這一點。
<div class="content">
<aside>
<ul>
<li>
<img src="shadeed.jpg" alt="Ahmad Shadeed" />
<span class="name">Ahmad Shadeed</span>
</li>
</ul>
</aside>
<main>
<h2>Main content</h2>
</main>
</div>
.content {
display: grid;
grid-template-columns: 0.4fr 1fr;
}
aside {
contain: layout inline-size style;
}
@container (min-width: 180px) {
.name {
display: block;
}
}
注意側邊欄的寬度是 0.4f
,所以它是動態寬度,另外,我還添加了 contain
屬性,並且如果容器寬度大於 180px
,則會顯示用戶名。
與此類似的另一個案例是側邊導航欄,我們可以從新的一行或在圖標旁邊切換導航項標籤的位置。
注意,當容器(側邊欄)較小時,導航項標籤是如何切換為新的一行的,而當有足夠空間時,導航項標籤是如何切換到導航圖標旁邊的。
手風琴#
手風琴模式可用於像 FAQs 這樣的場景,在某些情況下,我們可能需要在側邊欄或用戶界面中的一個小區域內添加 FAQs 列表,容器查詢可以提供幫助!
下面是我們如何使用 CSS 容器查詢實現上述功能。
@container (min-width: 180px) {
.faq-title {
display: flex;
justify-content: space-between;
font-size: 1.25rem;
}
.faq__icon {
width: 60px;
height: 60px;
background-color: #4f96e7;
}
}
搜索框#
當我們在多個地方使用通用搜索框時,這可能非常有用,例如,它可以在一個主圖使用(在右側),也可以在一個較小的範圍內使用,如側邊欄(在左側)。
活動清單#
我個人喜歡這種容器查詢的用例,我們可以在多種情況下使用同一個組件,在上圖中,我們有簡單、中等和大型的佈局展示。下面是一個關於如何使用它們的例子。
同樣,這是適應其父容器寬度的相同組件,這不是很棒嗎?對我來說,是的。
作者簡介#
作者簡介是博客的常見組成部分,從上圖可以看出,它可以在多種情況下,因此它應該自適應。
社交分享#
大多數時候我實現一個社交分享組件,需要創建一個在視口大但父容器寬度小的情況下可以使用的版本(例如:側邊欄),通過容器查詢,可以通過自適應其父容器寬度來輕鬆解決這個問題。
當該組件在側邊欄中使用時(在左側),則使用小版本,當父容器較大時(例如:主區域),將使用完整版本。
感謝你的閱讀 :)