Media Query
這件事情應該是講到爛掉了,我們稍微複習一下就好,
@media (min-width: 32rem) {}
收工(欸)!
爾或者是,
/* 請不要這樣做 */
@media (min-width: 90ch) {}
等等好歹也解釋一下
ch
好的,這邊這個單位 ch 是一種字元長度單位,但是他不代表你的 字有多長,以下是 w3c 的解釋,
Equal to the used advance measure of the "0" (ZERO, U+0030) glyph found in the font used to render it. (The advance measure of a glyph is its advance width or height, whichever is in the inline axis of the element.)
根據 caniuse.com 的回報,普及率也算高。這個單位很適合用來規劃文字內容區塊的排版。然而如果無法正確量測尺寸,這個單位會使用 0.5em 來當作預設值。
通常這個單位會搭配一些運算,並且放入 Flex 或 Grid 當中,最外面的 Media Query 只是輔助。也就是說,我們在面對排版的大前提下,針對「尺寸」這件事情,所配用的順序是這樣,
- @media指定各種裝置尺寸所需要的外層容器尺寸。
- Grid 用以規劃容器內的元件流。
- Flex 用以規劃元件內更小級別的元件流。
所以,當你不需要針對特殊斷點做設定的話,甚至連 @media 都可以省略。
Flex 與 Grid
我先來兩個比較魔術的寫法,
.grid {
    grid-template-columns: repeat(auto-fit, minmax(15ch, 1fr));
}
.flex-item {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: calc((48rem - 100%) * 9999);
}
可以不解釋嗎?
好的,為了防止路上被人賭到,我先解釋一下上面這些個魔術方法在做什麼事情。首先,請先自行複習一下 repeat 跟 auto-fit 這兩件事情,後面的 minmax(15ch, 1fr) 我來解釋解釋,
首先,我們的尺寸使用了 minmax 亦即他的尺寸會介於 15ch 跟 1fr 之間。我知道這是廢話,然後那個 15ch 是依照字元寬度來設定成 最小 尺寸,接著使用 1fr 來當作最大尺寸,我知道這還是廢話。這樣設定主要的用意就是,
- 格線容器的內容會自動緊湊符合(auto-fit)。
- 當格線容器寬度小於 15ch的時候,會變成只有一個column,這個column的尺寸是1fr。
- 當格線容器大於 15ch的時候,會從15ch開始分column排列,然後自動切斷成row。
- 當有多欄(column)出現時,每個欄位的寬度都會是1fr,然後會套用自動緊湊符合(auto-fit)。
所以我們會有一下這些結果,



我們接著來看 Flex 的設定,
.flex-item {
    flex-grow: 1;
    flex-shrink: 1;
    flex-basis: calc((48rem - 100%) * 9999);
}
上面的 flex-grow: 1;, flex-shrink: 1; 就不解釋了。這邊的魔法在於 calc() 這個方法。一般來說,我們在設定 flex-basis 的時候,通常會指定一個數值,或是項這樣透過 calc() 做運算,但是,這邊混合了一個包含單位的絕對數值,與一個相對數值,然後後面還乘上了一個無單位數字。那,到底這樣會發生什麼事情?
- 當尺寸大於 48rem的時候,他會變成多欄(column)的形式呈現。
- 多欄的形式會呈現出不固定的欄位寬度,此時是因為 flex-grow的關係會將欄位寬度撐滿容器。
- 如果尺寸小於 48rem的時候,他會變成單欄多行(row)的形式。
- 這個時候的欄位寬度,會因為 flex-grow的關係會將欄位寬度撐滿容器。
- 後面那個 * 9999是為了避免中間值誤差。
所以,我們會有以下兩種結果,


何謂 中間值誤差,我們看圖,

為何會稱他為誤差,請回頭看一下 Grid 那邊的操作,照理來說,我們會希望 1, 2, 3, 4 這四個元件的尺寸會相同,頂多就是因為寬度不夠而被換行,但是,在 Flex 的呈現,卻變成了 4 填滿了整個容器。所以,為了避免這種偏差值存在,所以我們後面再加上 * 9999 這樣的設定。
我再解釋一次 calc() 在 48rem - 100% 這邊的操作,
- 當容器尺寸為 900px,是大於48rem的狀況(假設1rem = 16px),運算結果為:-132然後乘上9999變成了:-1319868px。
- 當 calc()計算出負數,對於flex-basis來說負數是不被允許的數值,會自動變成auto。
- 當容器尺寸為 600px,是小於48rem的狀況,運算結果為:1679832px。
- 此時對於 flex-basis來說是正確數值,但是由於flex-shrink: 1;的關係,他會縮小到符合容器尺寸。
這樣可以理解 flex-basis 到底發生了什麼事情了吧。另外,你要把 9999 換成 999 應該也是可以,只要你確認你的裝置不會這麼巨大的話應該是沒有問題的。
你說,誰還會需要
@media呢?
所以說那個手機版
話說我今天去換輪胎,然後四傳一次要換四顆。換完師傅試車後跟我說,我的輪軸有異音應該要換了。
我難過。
所以如果你使用了 Media Query,在搭配上面兩種魔術方法,基本上可以更彈性的來調整內容。不過,這邊有一個比較大的前提是,你的內容不會因為彈性大小而造成差異,也就是我一開始說的,這些方式比較適合在文字展示區塊。
 
 
        ![[CSS] Flex/Grid Layout Modules, part 16](/content/images/size/w960/2022/05/grid-sample-80-1.png) 
            ![[CSS] Flex/Grid Layout Modules, part 15](/content/images/size/w960/2022/01/grid-sample-73-1.png) 
            ![[CSS] Flex/Grid Layout Modules, part 14](/content/images/size/w960/2021/09/grid-sample-70-1.png)