英文: Rachel Andrew? ?
譯文:大漠
www.w3cplus.com/css/css-grid-gotchas-stumbling-blocks.html
2017年3月壤玫,CSS Grid在幾個星期內(nèi)就被發(fā)送到Chrome园爷、Firefox和Safari的生產(chǎn)版本中伶氢。很高興,大家可以使用它來解決實際問題郑诺。
CSS Grid是一種不同的布局方式,在大家開始使用規(guī)范的時候,有很多常見的問題。這篇文章的目的是回答其中的一些問題鲫惶,并且將會是Smashing Magazine中有關(guān)于CSS Grid一系列文章中的一篇。
為什么使用CSS Grid而不是CSS Flexbox实抡?
在CSS網(wǎng)格布局在瀏覽器中可用之前欠母,很多人都認為Flexbox是我們所有設(shè)計相關(guān)問題的答案欢策。然而,F(xiàn)lexbox并沒有提供比浮動更好的網(wǎng)格系統(tǒng)赏淌,盡管它確實比浮動創(chuàng)建一個網(wǎng)格系統(tǒng)更簡單踩寇。一個真正的網(wǎng)格是二維的。這兩個維度就是行和列猜敢,并且使用網(wǎng)格布局姑荷,你可以同時控制它們。使用Flexbox缩擂,你可以選擇是否將這些項列成一行或列鼠冕,一個或另一個,而不是兩個胯盯。
這里有一個簡單的示例懈费,突出其區(qū)別。第一個布局使用Flexbox博脑,為了能盡可能多的使用盒子憎乙,以適合可用的寬度。這里我們控制了整個行中的布局叉趣。允許Flex項目進行包裹泞边,因此會創(chuàng)建新的行,但是每一行都是一個新的Flex容器疗杉≌笱瑁空間分布在行中發(fā)生,所以取決于最后一行多少項烟具,它們有時不會與上面的Flex項對齊梢什。
DEMO1:https://codepen.io/airen/pen/mxOdYE
第二個示例使用CSS Grid實現(xiàn)相同的布局,但是朝聋,你可以看到嗡午,最后一行中的項目始終保持在它們的列中。這是因為在網(wǎng)格中冀痕,我們將項目排列成行和列 —— 二維布局荔睹。
?DEMO2:https://codepen.io/airen/pen/qoqBGe
你還可以在第二個示例中看到,在CSS Grid布局中金度,我們不需要向網(wǎng)格添加任何內(nèi)容來進行布局应媚。所有東西都被放在容器上。在Flexbox布局中猜极,你必須針對Flex項目來設(shè)置flex-grow
中姜、flex-shrink
和flex-basis
屬性。這是理解網(wǎng)格布局關(guān)鍵所在,也可能是大家有很多困惑的地方丢胚。Grid主要是關(guān)于包含元素的翩瓜,而我們之前的所有布局方法都依賴于我們在布局中設(shè)置的寬度,使某些東西看起來像一個網(wǎng)格携龟。
如果你使用一個簡化版本的浮動12列“網(wǎng)格”兔跌,我們必須計算每一列的百分比大小,加上每個列之間間距的百分比大小峡蟋。要創(chuàng)建跨多個列的項坟桅,需要將所有項的寬度加上用于分隔它們的邊界寬度。
DEMO3:https://codepen.io/airen/pen/eMBYqQ
使用Flexbox創(chuàng)建的網(wǎng)格也是如此蕊蝗。當我們在父節(jié)點上通過display:flex
創(chuàng)建Flex布局時仅乓,F(xiàn)lex所有的大小都需要在單個Flex項目上進行。為了制作一個Flexbox的“網(wǎng)格”蓬戚,我們必須阻止Flexbox做靈活的操作夸楣,而是應(yīng)該設(shè)置百分比寬度,就像我們前面的浮動網(wǎng)格示例一樣子漩。使用Flexbox要比浮動更有一些優(yōu)勢豫喧,比如控制對齊和列等高之類的要簡易得多。然而幢泼,在Flexbox和浮動的方法中仍然沒有網(wǎng)格紧显,只是通過設(shè)置項目的大小,并將它們排列起來缕棵,讓其看起來像網(wǎng)格的東西鸟妙。
DEMO4:https://codepen.io/airen/pen/PRbwwp
在網(wǎng)格中,所有的大小都發(fā)生在容器上挥吵。一旦我們創(chuàng)建了我們的網(wǎng)格軌道,我們就可以告訴單個項目(Grid項目)有多少個軌道可以跨越花椭,但我們卻有一個實際的網(wǎng)格忽匈。我們可以完全拋棄行的容器,因為網(wǎng)格已經(jīng)有行了矿辽。這也意味著丹允,我們也可以使用相同的方式進行跨列。這對于以前而言是件很難做的事情袋倔。
?DEMO5:https://codepen.io/airen/pen/JLboYP
是否應(yīng)該將網(wǎng)格用于主布局和Flexbox用于組件布局
隨著大家開始接觸和學習CSS Grid的布局雕蔽,這個神話不斷涌現(xiàn)。也許它來自于網(wǎng)格系統(tǒng)的使用宾娜,比如在Bootstrap或Foundation批狐,大家關(guān)心的是一個整體網(wǎng)格上放置項目。這當然是使用網(wǎng)格布局的一種方法。不過嚣艇,我還是會考慮在上一節(jié)提到的不同之處承冰。問問你自己,這個布局是一維的還是二維的食零?
如果你可以使用你的組件困乒,并且用行和列在它的上面繪制一個網(wǎng)格。它是二維的贰谣,那就使用CSS Grid來布局娜搂。
如果相反,你希望單個項目在一行中進行擴展吱抚,而不考慮上面一行中發(fā)生的情況百宇,那就應(yīng)該使用Flexbox布局更為合適。
不管你想要展示的是一個完整的頁面频伤,還是一個很小的組件恳谎。重要的是你想在布局里面的項目分配空間和相互關(guān)聯(lián)。
網(wǎng)格軌道大小是否由內(nèi)容來決定憋肖?
我們已經(jīng)看到了如何在使用網(wǎng)格布局時因痛,在容器上設(shè)置網(wǎng)格和網(wǎng)格大小。但是岸更,網(wǎng)格中的項可以指定網(wǎng)格軌道大小鸵膏。這里要記住的關(guān)鍵是,一個單元格大小的改變將會改變整個軌道的大小怎炊。如果你不希望這種情況發(fā)生谭企,你可能需要一個單一維度的Flexbox布局。
最簡單的方法就是使用auto
评肆,因為它會默認在隱式網(wǎng)格中創(chuàng)建網(wǎng)格軌道债查。一個自動大小的網(wǎng)格軌道將擴展到包含所有的內(nèi)容。在下面的示例中瓜挽,我有一個兩列布局盹廷,在右邊的列中添加更多的內(nèi)容會導致整個行的擴展。第二行也是自動大小久橙,再擴展以包含內(nèi)容俄占。
?DEMO6:https://codepen.io/airen/pen/NYbPdY
我們可以使用兩個參數(shù)來控制網(wǎng)格軌道大小,例如創(chuàng)建一個最小的網(wǎng)格軌道淆衷,但其仍然會增長以適應(yīng)較大的網(wǎng)格項目缸榄。我們可以使用minmax()
函數(shù)來做這個。傳給minmax()
函數(shù)的第一個值祝拯,它是網(wǎng)格軌道最小的值甚带,第二個值是網(wǎng)格軌道最大的值。因此,你可以設(shè)置200px
的行欲低,但通過auto
設(shè)置為網(wǎng)格軌道最大值辕宏,那么當有較多的內(nèi)容時,不會出現(xiàn)內(nèi)容溢出砾莱。
DEMO7:https://codepen.io/airen/pen/oqYgWx
也有一些有趣的關(guān)鍵詞可以設(shè)置大小瑞筐,將在以后的文章中對它們進行適當?shù)年U述。這些關(guān)鍵詞在指定網(wǎng)格中允許內(nèi)容來改變網(wǎng)格軌道大小腊瑟,并且可以在CSS內(nèi)部和外部的大小模塊(CSS Intrinsic and Extrinsic Sizing Module)中找到相關(guān)的詳細內(nèi)容聚假。例如min-content
關(guān)鍵詞的示例,使用它創(chuàng)建一個網(wǎng)格軌道時闰非,將會創(chuàng)建盡可能小的網(wǎng)格軌道膘格。
在我的例子中,這個詞意味著其成為最寬的東西财松,網(wǎng)格軌首縮小以適應(yīng)它瘪贱。
?DEMO8:https://codepen.io/airen/pen/geLbXG
相反,如果你使用的是max-content
辆毡,你會得到一個盡可能大的網(wǎng)格軌道菜秦。這可能會導致溢出情況,在下面的示例中舶掖,使用了overflow: scroll
設(shè)置了網(wǎng)格溢出球昨,所以max-content
的網(wǎng)格軌道會導致滾動條出現(xiàn)。
DEMO9:https://codepen.io/airen/pen/WzobdK
關(guān)鍵要記住的是眨攘,這將會發(fā)生在整個網(wǎng)格軌道上主慰。你需要確保網(wǎng)格軌道的其他網(wǎng)格項目也能巧妙地吸收額外的空間。
了解了如何對網(wǎng)格軌道大小進行調(diào)整鲫售,以及內(nèi)容將如何改變網(wǎng)格軌道大小共螺,這可能是新手使用CSS Grid布局中會感到最為困惑的事情之一。這需要花一點時間來理解 —— 我們之前沒有任何類似的行為情竹。這是理解事物如何運作的最好方法璃谨。
可以使用CSS Grid來實現(xiàn)瀑布流布局?
很多同學有一種誤解鲤妥,認為網(wǎng)格布局與瀑布流或Pinterest布局一樣的。這通常是基于在網(wǎng)格布局中自動放置網(wǎng)格項目拱雏,這樣的效果看上去的確有點像瀑布流布局棉安。在下一個示例中,我有一個布局铸抑,使用grid-auto-flow
設(shè)置為dense
贡耽,實現(xiàn)網(wǎng)格項目自動流的布局。這將導致網(wǎng)格項目從源程序中取出,并嘗試在網(wǎng)格填充空白區(qū)域蒲赂。
DEMO10:https://codepen.io/airen/pen/KoNwRb
然而這并不是真正的瀑布流布局阱冶,因為我們?nèi)匀挥幸粋€網(wǎng)格(具有行和列),并且潛在的網(wǎng)格項目從源代碼中移出滥嘴。一個真正的瀑布流布局將使事物在源代碼中工作木蹬。項目被推上去填充部分空間。它更像是在兩個維度上做Flexbox布局若皱。
你可以通過對所有的Grid項目進行定位處理來得到一個瀑布流外觀的網(wǎng)格布局镊叁,但是自動流的瀑布流布局,網(wǎng)格布局還無法具備這方面的能力走触。不過晦譬,未來的規(guī)范正在做這方面的考慮。
如何向網(wǎng)格區(qū)域添加背景和邊框互广?
一個網(wǎng)格尚未完成的問題敛腌,網(wǎng)格區(qū)域本身的背景和邊框的樣式。能在網(wǎng)格區(qū)域上直接添加背景和邊框的樣式嗎惫皱?到目前是不可能的像樊,如果要實現(xiàn)這樣的一個效果需要插入一個元素或者添加一個偽元素來完成。
下面的這個示例中逸吵,我在網(wǎng)格中通過偽元素來完成凶硅,將其放置在基于行的位置,然后添加一個背景和邊框到該網(wǎng)格區(qū)域扫皱。
DEMO11:https://codepen.io/airen/pen/GxNJba
有時候可以繞過背景和邊框來實現(xiàn)足绅,比如通過網(wǎng)格間距(grid-gap
) —— 用一個1px
來模擬背景或邊框,比如下面的這個示例:
?DEMO12:https://codepen.io/airen/pen/KoNdPg
為了能夠?qū)W(wǎng)格區(qū)域進行適當?shù)臉邮交裕覀冃枰刖W(wǎng)格區(qū)域偽元素的概念氢妈,這是一種特殊的生成內(nèi)容。在?CSS WG上有一個關(guān)于這方面的問題段多,所以你可以在這里參加討論首量,把你的想法與大家一起參與討論。
跨越到網(wǎng)格的末端
網(wǎng)格布局具有隱式和顯式網(wǎng)格的概念进苍。顯式網(wǎng)格是我們使用grid-template-rows
和grid-template-columns
定義的網(wǎng)格加缘。這個網(wǎng)格軌道定義了顯式網(wǎng)格的范圍。當我們在顯式網(wǎng)格之外放置一個網(wǎng)格項目觉啊,或者我們通過自動旋轉(zhuǎn)更多的網(wǎng)格項目時拣宏,隱式網(wǎng)格就將被創(chuàng)建。
除非你使用grid-auto-rows
或grid-auto-columns
創(chuàng)建的網(wǎng)格軌道杠人,否則在隱式網(wǎng)格中創(chuàng)建的網(wǎng)格軌道的大小將是自動的勋乾。
在很多情況下宋下,隱式和顯式網(wǎng)格的渲染行為是相同的,對于很多的布局辑莫,你會發(fā)現(xiàn)你定義了列学歧,然后允許將行創(chuàng)建為隱式網(wǎng)格。不同的是各吨,當你開始使用負的行號來引用網(wǎng)格的最后一行時枝笨,你會發(fā)現(xiàn)還是有一定區(qū)別的。
對于網(wǎng)格布局中的寫作模式绅你。在從左到右的語言(ltr
)中伺帘,列第一行是在左邊,而你可以用-1
來指向右邊的列忌锯。在從右到左的語言(rtl
)中伪嫁,列的第一行在右側(cè),而-1
則指向左邊的列偶垮。
?DEMO13:https://codepen.io/airen/pen/NYbGNN
或許你已經(jīng)發(fā)現(xiàn)了张咳,只有顯式的網(wǎng)格才可以向后計數(shù)。如果你在隱式網(wǎng)格中添加了行似舵,然后嘗試以-1
來指定目標脚猾,你將會發(fā)現(xiàn)你得到是顯式網(wǎng)格的最后網(wǎng)格線,而不是實際網(wǎng)格最末端的網(wǎng)格線砚哗。
DEMO14:https://codepen.io/airen/pen/xWRwOJ
百分比的問題
在文章開頭之處龙助,我描述了網(wǎng)格布局與之前的布局方法與眾不同之處。由于浮動和基于Flexbox的網(wǎng)格的限制蛛芥,我們需要變得擅長計算百分比來做布局提鸟,所以大多數(shù)人做的第一件事就是嘗試在他們的網(wǎng)格布局中使用相同的方法。然而仅淑,在這樣做之前不要忘記我們有一個新單位fr
称勋。這個單位是專門為網(wǎng)格布局設(shè)計的,因為網(wǎng)格設(shè)置父元素的大小涯竟。
fr
單位允許我們分配可用網(wǎng)格布局中的可用空間赡鲜。其通過查看網(wǎng)格容器中可用的空間(去掉間距所需的空間、固定寬度的網(wǎng)格項目或定義網(wǎng)格軌道)庐船,然后按照我們?yōu)榫W(wǎng)格軌道指定的比例來對剩余的網(wǎng)格空間進行分配银酬。這意味著,我們使用浮動或Flexbox布局的場景筐钟,必須有靈活的間距揩瞪。
?DEMO15:https://codepen.io/airen/pen/VXmvpN
在大多數(shù)情況下,fr
單位是一個比百分比更好的選擇盗棵。你可能選擇使用百分比的原因是你需要一個網(wǎng)格布局壮韭,以便與其他元素匹配使用其他布局方法,并依賴于百分比大小纹因。然而喷屋,如果不是這樣的話,看看fr
單位是否能滿足你的需求瞭恰,然后對其進行計算屯曹。
網(wǎng)格可以嵌套使用?
網(wǎng)格項目也可以成為網(wǎng)格容器惊畏,就好比Flex項目也可以成為一個Flex容器一樣恶耽。但是,這些嵌套網(wǎng)格也父網(wǎng)格沒有任何關(guān)系颜启,因此不能使用它們與其他嵌套網(wǎng)格對齊內(nèi)部元素偷俭。
DEMO16:https://codepen.io/airen/pen/GxNpvg
在將來的網(wǎng)格布局中,很可能會有一種創(chuàng)建嵌套網(wǎng)格的方法缰盏,它可以維護與父網(wǎng)格的關(guān)系涌萤。這意味著,除了網(wǎng)格的直接子節(jié)點口猜,其他網(wǎng)格項目可能參與整個網(wǎng)格布局负溪。
網(wǎng)格布局有對應(yīng)的Polyfill嗎?
我經(jīng)常會被問到是否有網(wǎng)格布局的Polyfill济炎,大家都想知道是否有一種方法可以支持舊的瀏覽器川抡。
我的建議是,這并不是你需要做的事情须尚。這可能會為那些已經(jīng)在努力渲染現(xiàn)代網(wǎng)站的瀏覽器造成一定的性能影響崖堤,帶來不好的用戶體驗。如果你南非要較舊的瀏覽器與現(xiàn)代瀏覽器相同恨闪,那么你可能要考慮在這個項目中是否使用網(wǎng)格布局倘感。不過,在大多數(shù)情況下咙咽,可以使用較老的方法來為不支持的設(shè)備創(chuàng)建一個簡單的降級處理老玛,而不需要創(chuàng)建兩個完全不同的CSS代碼。這方面真的需要用一篇文章來詳細闡述钧敞,所以我將盡快在Smashing Magazine發(fā)布這方面的教程蜡豹。
調(diào)試網(wǎng)格布局
當你開始使用網(wǎng)格布局時,你肯定希望能看到你的網(wǎng)格和其網(wǎng)格項目是如何布局的溉苛。我建議你使用Firefox Nightly镜廉,并在Firefox 瀏覽器開發(fā)者工具中使用網(wǎng)格檢查器。如果你選擇一個網(wǎng)格愚战,可以點擊這個小網(wǎng)格圖標 —— 我喜歡把它想像成一個華夫餅(Waffle) —— 來顯示網(wǎng)格娇唯。
Firefox已經(jīng)在這方面做得很好了齐遵,而且Chrome也在著手在Chrome開發(fā)者工具中實現(xiàn)這方面的功能。
有關(guān)于在Firefox瀏覽器中怎么使用網(wǎng)格檢查器來調(diào)試網(wǎng)格布局塔插,可以閱讀以前翻譯的一篇文章《使用Firefox 網(wǎng)格檢查器調(diào)試 CSS網(wǎng)格布局》梗摇。
這對于我們所有人來說仍然是新東西
我很了解CSS網(wǎng)格規(guī)范,但是我從3月份就開始使用它了想许,就像其他人一樣伶授。當我們從創(chuàng)建小示例開始,也可以說真正的在生產(chǎn)中開始推動Grid相關(guān)的規(guī)范流纹,我們將開始尋找使用網(wǎng)格的新方法糜烹,當然還有新問題要解決!我很樂意看到你自己編寫的有關(guān)于網(wǎng)格相關(guān)的案例漱凝。在接下來的幾個月的時間里疮蹦,我還將在Smashing Magazine中深入探討網(wǎng)格布局相關(guān)的問題。
感興趣的小伙伴碉哑,可以關(guān)注公眾號【grain先森】挚币,回復關(guān)鍵詞 “小程序”,獲取更多資料扣典,更多關(guān)鍵詞玩法期待你的探索~