大多數現代網站使用響應性網頁設計技術,以確保其外觀良好、可讀性好,並在任何螢幕大小的裝置上保持可用性,如手機、平板電腦、膝上型電腦、臺式電腦顯示器、電視、投影儀等。
使用這些技術的站點有一個模板,該模板根據螢幕尺寸修改佈局:
較小的螢幕通常顯示線性、單列檢視,其中通過單擊(漢堡)圖示啟用選單等UI控制元件。
更大的螢幕顯示更多資訊,可能帶有水平對齊的側欄。UI控制元件(如選單項)可能始終可見,以便於訪問。
響應式web設計的一個重要部分是實現CSS或JavaScript媒體查詢,以檢測裝置大小並自動提供適合該大小的設計。我們將討論為什麼這些查詢很重要以及如何使用它們,但首先,讓我們討論一般的響應式設計。
- 為什麼響應式設計很重要?
- 響應式設計如何工作?
- 媒體查詢最佳實踐
- 媒體查詢備選方案
- 您是否需要JavaScript中的媒體查詢?
- 選項 1:監視視場維度
- 選項 2:定義和監視CSS自定義屬性(可變)
- 選項 3: 使用匹配媒體API
為什麼響應式設計很重要?
不可能只提供一個頁面佈局,而期望它在任何地方都能工作。
當手機在21世紀初首次獲得基本的web訪問時,網站所有者通常會建立兩到三個單獨的頁面模板,鬆散地基於手機和桌面檢視。隨著裝置種類呈指數級增長,這種做法變得越來越不切實際。
今天,有許多螢幕尺寸,從微型手錶顯示器到巨大的8K顯示器甚至更大。即使你只考慮手機,最近的裝置可以比許多低端膝上型電腦具有更高的解析度。
移動裝置的使用量也超過了臺式電腦。除非你的網站有一組特定的使用者,否則你可以期望大多數人通過智慧手機訪問它。儘管大多數網頁設計師、開發人員和客戶繼續使用標準PC機,但小螢幕裝置已不再是後知後覺,應該從一開始就加以考慮。
谷歌已經認識到移動裝置的重要性。當網站在智慧手機上可用且表現良好時,在谷歌搜尋中排名會更好。好的內容仍然至關重要,但載入速度慢、無法適應使用者群螢幕尺寸的網站可能會損害您的業務。
最後,考慮可訪問性。一個適合所有人的網站,無論他們使用什麼裝置,都會吸引更多的觀眾。可訪問性是許多國家的法律要求,但即使不是你所在的地方,也要考慮到更多的觀眾會帶來更多的轉換和更高的盈利能力。
響應式設計如何工作?
響應式設計的基礎是媒體查詢:一種CSS技術,可以根據輸出型別(螢幕、印表機甚至語音)、螢幕尺寸、顯示縱橫比、裝置方向、顏色深度和指標精度等指標應用樣式。媒體查詢還可以考慮使用者偏好,包括減少動畫、明暗模式和更高對比度。
我們展示的示例演示了僅使用螢幕寬度的媒體查詢,但是站點可以更加靈活。有關詳細資訊,請參閱MDN上的全套選項。
媒體查詢支援非常出色,已經在瀏覽器中使用了十多年。只有IE8及以下版本沒有支援。它們忽略了媒體查詢應用的樣式,但這有時會帶來好處(請參閱下面的最佳實踐部分)。
使用媒體查詢應用樣式有三種標準方法。第一個載入HTML程式碼中的特定樣式表。例如,當裝置的螢幕寬度至少為800畫素時,以下標記將載入wide.css樣式表:
<link rel="stylesheet" media="screen and (min-width: 800px)" href="wide.css" />
其次,樣式表可以使用@import
規則有條件地載入到CSS檔案中:
/* main.css */ @import url('wide.css') screen and (min-width: 800px);
請注意,應避免使用
@import
,因為每個匯入的CSS檔案都是渲染塊。HTML的<link>
標記是並行下載的,而@import
則是序列下載檔案。
更典型的是,您將使用@media CSS規則塊在樣式表中應用媒體查詢,該規則塊修改特定的樣式。例如:
/* default styles */ main { width: 400px; } /* styles applied when screen has a width of at least 800px */ @media screen and (min-width: 800px) { main { width: 760px; } }
開發人員可以應用任何必要的媒體查詢規則來調整站點的佈局。
媒體查詢最佳實踐
最初設計媒體查詢時,許多網站選擇了一套固定的佈局。這在概念上更易於設計和編碼,因為它有效地複製了一組有限的頁面模板。例如:
- 小於600px的螢幕寬度使用400px寬的移動式佈局。
- 600px和999px之間的螢幕寬度使用600px寬的平板電腦佈局。
- 大於1000px的螢幕寬度使用1000px寬的桌面式佈局。
這項技術有缺陷。在非常小和非常大的螢幕上的結果可能看起來很差,並且隨著裝置和螢幕尺寸的變化,可能需要CSS維護。
一個更好的選擇是使用帶有斷點的“移動第一流體”設計,該斷點可以在特定大小下調整佈局。本質上,預設佈局使用最簡單的小螢幕樣式,將元素定位線上性垂直塊中。
例如,<article>
和<aside>
在<main>
容器內:
/* default small-screen device */ main { width: 100%; } article, aside { width: 100%; padding: 2em; }
以下是所有瀏覽器的結果-即使是不支援媒體查詢的非常舊的瀏覽器:
不支援媒體查詢的示例螢幕截圖。
當支援媒體查詢且螢幕超過特定寬度(例如500px)時,<article>
和<aside>
元素可以水平放置。本例使用CSS網格,其中主要內容使用大約三分之二的寬度,次要內容使用剩餘的三分之一:
/* larger device */ @media (min-width: 500px) { main { display: grid; grid-template-columns: 2fr 1fr; gap: 2em; } article, aside { width: auto; padding: 0; } }
以下是大螢幕上的結果:
支援媒體查詢的示例螢幕截圖
媒體查詢替代方案
響應性設計也可以在現代CSS中使用更新的屬性實現,這些屬性本質上適應佈局,而無需檢查視口尺寸。選擇包括:
calc
,min-width
,max-width
,min-height
,max-height
和較新的clamp
屬性都可以定義尺寸標註,根據已知限制和可用空間調整圖元的大小。- 視口單位
vw
,vh
,vmin
和vmax
可以根據螢幕尺寸分數調整元素的大小。 - 文字可以顯示在CSS列中,在空間允許的情況下顯示或消失。
- 可以使用
min-content
,fit-content
和max-content
維度,根據元素的子元素大小調整元素的大小。 - CSS flexbox可以在元素開始超出可用空間時進行換行或不換行。
- CSS網格元素可以使用比例分數
fr
單位調整大小。repeat CSS函式可以與minmax
,auto-fit
和auto-fill
結合使用,以分配可用空間。 - 新的和(當前)實驗性的CSS容器查詢可以對佈局中元件可用的部分空間作出反應。
這些選項超出了本文的範圍,但它們通常比只能響應螢幕尺寸的粗糙媒體查詢更實用。如果您可以在沒有媒體查詢的情況下實現佈局,那麼隨著時間的推移,它可能會使用更少的程式碼,更高效,並且需要更少的維護。
也就是說,在某些情況下,媒體查詢仍然是唯一可行的佈局選項。當你需要考慮其他螢幕因素時,它們仍然是必不可少的,比如縱橫比、裝置方向、顏色深度、指標精度,或者使用者偏好,比如動畫和光/暗模式。
您是否需要JavaScript中的媒體查詢?
到目前為止,我們主要討論CSS。這是因為大多數佈局問題都可以而且應該單獨用CSS來解決。
但是,在某些情況下,使用JavaScript媒體查詢而不是CSS是可行的,例如:
- 諸如選單之類的元件在小螢幕和大螢幕上具有不同的功能。
- 切換縱向/橫向會影響web應用程式的功能。
- 基於觸控的遊戲必須更改
<canvas>
佈局或調整控制按鈕。 - web應用程式遵循使用者偏好,如暗/光模式、減少動畫、觸控粗糙度等。
以下部分演示了在JavaScript中使用媒體查詢或類似於媒體查詢的選項的三種方法。所有示例都返回一個狀態字串,其中:
- 小檢視=寬度小於400畫素的螢幕;
- 中檢視=寬度在400到799畫素之間的螢幕;
- 大檢視=寬度為800畫素或更多的螢幕。
選項 1:監視視場維度
在媒體查詢實施之前的黑暗日子裡,這是唯一的選擇。JavaScript將偵聽瀏覽器“調整大小”事件,使用window.innerWidth
和window.innerHeight
(或舊IE中的document.body.clientWidth
和document.body.clientHeight
)分析視口尺寸,並做出相應的反應。
此程式碼將計算出的小、中或大字串輸出到控制檯:
const screen = { small: 0, medium: 400, large: 800 }; // observe window resize window.addEventListener('resize', resizeHandler); // initial call resizeHandler(); // calculate size function resizeHandler() { // get window width const iw = window.innerWidth; // determine named size let size = null; for (let s in screen) { if (iw >= screen[s]) size = s; } console.log(size); }
您可以在此處檢視工作演示。(如果使用桌面瀏覽器,請在新視窗中開啟此連結,以便於調整大小。移動使用者可以旋轉裝置。)
上面的示例在調整瀏覽器大小時檢查視口大小;確定它是小型、中型還是大型;並將其設定為body元素上的類,從而更改背景顏色。
這種方法的優點包括:
- 它可以在每一個可以執行JavaScript的瀏覽器中執行——甚至是古老的應用程式。
- 您正在捕獲準確的尺寸,並可以做出相應的反應。
缺點是:
- 這是一種需要大量程式碼的老技術。
- 是不是太精確了?你真的需要知道寬度是966px還是967px嗎?
- 您可能需要手動將維度匹配到相應的CSS媒體查詢。
- 使用者可以快速調整瀏覽器大小,使處理程式功能每次都再次執行。這會通過限制事件來過載較舊和較慢的瀏覽器。它只能每500毫秒觸發一次。
總之,除非有非常具體和複雜的大小調整要求,否則不要監視視口尺寸。
選項 2:定義和監視CSS自定義屬性(可變)
這是一種稍微不尋常的技術,它在觸發媒體查詢時更改CSS中自定義屬性字串的值。所有現代瀏覽器(但不是IE)都支援自定義屬性。
在下面的示例中,@media程式碼塊內的--screen custom property
設定為“small”、“medium”或“large”:
body { --screen: "small"; background-color: #cff; text-align: center; } @media (min-width: 400px) { body { --screen: "medium"; background-color: #fcf; } } @media (min-width: 800px) { body { --screen: "large"; background-color: #ffc; } }
可以使用偽元素單獨在CSS中輸出該值(但請注意,它必須包含在單引號或雙引號中):
p::before { content: var(--screen); }
您可以使用JavaScript獲取自定義屬性值:
const screen = getComputedStyle(window.body) .getPropertyValue('--screen');
但這並不是全部,因為返回值包含CSS中冒號後定義的所有空格和引號字元。字串將為”large”,因此需要稍微整理一下:
// returns small, medium, or large in a string const screen = getComputedStyle(window.body) .getPropertyValue('--screen') .replace(/\W/g, '');
您可以在此處檢視工作演示。(如果使用桌面瀏覽器,請在新視窗中開啟此連結,以便於調整大小。移動使用者可以旋轉裝置。)
該示例每兩秒鐘檢查一次CSS值。它需要一點JavaScript程式碼,但需要輪詢更改—您無法使用CSS自動檢測到自定義屬性值已更改。
也不可能將值寫入偽元素,並使用DOM變異觀察器檢測更改。偽元素不是DOM的“真實”部分!
優點:
- 這是一種簡單的技術,主要使用CSS並匹配真實的媒體查詢。可以同時修改任何其他CSS屬性。
- 無需複製或解析JavaScript媒體查詢字串。
主要缺點是無法自動對瀏覽器視口尺寸的更改作出反應。如果使用者將手機從縱向旋轉到橫向,JavaScript永遠不會知道。您可以經常輪詢更改,但這是低效的,並且會導致您在演示中看到的時間延遲。
監視CSS自定義屬性是一種新穎的技術,但只有在以下情況下才實用:
- 佈局可以固定在頁面最初呈現的位置。一個資訊亭或銷售點終端是可能的,但它們可能有固定的解析度和單一的佈局,因此JavaScript媒體查詢變得無關緊要。
- 該網站或應用程式已經頻繁執行基於時間的功能,如遊戲動畫。可以同時檢查自定義屬性,以確定是否需要更改佈局。
選項 3: 使用matchMedia API
matchMedia API有點不同尋常,但它允許您實現JavaScript媒體查詢。IE10以上的大多數瀏覽器都支援它。建構函式返回一個MediaQueryList物件,該物件的matches屬性針對其特定的媒體查詢計算為true或false。
當瀏覽器視口寬度為800px或更大時,以下程式碼輸出true:
const mqLarge = window.matchMedia( '(min-width: 800px)' ); console.log( mqLarge.matches );
“change”事件可應用於MediaQueryList物件。每次matches屬性的狀態更改時都會觸發此操作:它在先前為false(低於800px)後變為true(高於800px),反之亦然。
將MediaQueryList物件作為第一個引數傳遞給接收處理程式函式:
const mqLarge = window.matchMedia( '(min-width: 800px)' ); mqLarge.addEventListener('change', mqHandler); // media query handler function function mqHandler(e) { console.log( e.matches ? 'large' : 'not large' ); }
處理程式僅在matches屬性更改時執行。當頁面最初載入時,它不會執行,因此您可以直接呼叫函式來確定啟動狀態:
// initial state mqHandler(mqLarge);
當您在兩個不同的狀態之間移動時,API工作得很好。要分析三種或三種以上的狀態,如small, medium和large,需要更多的程式碼。
首先用關聯的matchMedia物件定義螢幕狀態物件:
const screen = { small : null, medium: window.matchMedia( '(min-width: 400px)' ), large : window.matchMedia( '(min-width: 800px)' ) };
無需在small狀態上定義matchMedia物件,因為在small和medium之間移動時,medium事件處理程式將觸發。
然後可以為medium和large事件設定事件偵聽器。它們呼叫相同的mqHandler()處理程式函式:
// media query change events for (let [scr, mq] of Object.entries(screen)) { if (mq) mq.addEventListener('change', mqHandler); }
處理程式函式必須檢查所有MediaQueryList物件,以確定當前是活動的small、medium還是large。比賽必須按大小順序進行,因為999px的寬度可以匹配中型和大型-只有最大的才能“獲勝”:
// media query handler function function mqHandler() { let size = null; for (let [scr, mq] of Object.entries(screen)) { if (!mq || mq.matches) size = scr; } console.log(size); }
您可以在此處檢視工作演示。(如果使用桌面瀏覽器,請在新視窗中開啟此連結,以便於調整大小。移動使用者可以旋轉裝置。)
使用的示例有:
- CSS中的媒體查詢以設定和顯示自定義屬性(如上面的選項2所示)。
- matchMedia物件中的相同媒體查詢,以監視JavaScript中的維度更改。JavaScript輸出將在同一時間發生變化。
使用matchMedia API的主要優點是:
- 它是事件驅動的,能夠高效地處理媒體查詢更改。
- 它使用與CSS相同的媒體查詢字串。
缺點是:
- 處理兩個或多個媒體查詢需要更多的思考和程式碼邏輯。
- 您可能需要在CSS和JavaScript程式碼中複製媒體查詢字串。如果不保持同步,這可能會導致錯誤。
為了避免媒體查詢不匹配,可以考慮在構建系統中使用設計令牌。媒體查詢字串在JSON(或類似)檔案中定義,值在構建時插入CSS和JavaScript程式碼。
總之,matchMedia API可能是實現JavaScript媒體查詢的最有效、最實用的方法。它有一些怪癖,但在大多數情況下它是最好的選擇。
小結
固有的CSS大小選擇越來越可行,但媒體查詢仍然是大多數網站響應性web設計的基礎。它們在處理更復雜的佈局和使用者偏好(如明暗模式)時總是必需的。
儘可能將媒體查詢單獨儲存到CSS。當您別無選擇,只能進入JavaScript領域時,matchMedia API為JavaScript媒體查詢元件提供了額外的控制,這些元件需要額外的基於維度的功能。
評論留言