新時代布局中一些有意思的特性!
在最新的 Chrome Canary 中,一個有意思的 CSS 語法 Container Queries 得到了支持。
Chrome Canary[1]:開發(fā)者專用的每日構(gòu)建版,站上網(wǎng)絡科技最前沿。當然,不一定穩(wěn)定~
而在最近幾個 Chrome 版本中,有一些挺有意思的屬性相繼得到支持,本文就將介紹一下,在今天,新時代布局中,我們能逐漸去使用的一些有意思的新特性,通過本文,你將能了解到:
- flex 布局中的 gap 屬性
- 控制容器寬高比屬性 aspect-ratio
- firefox 下的 CSS Grid 瀑布流布局(grid-template-rows: masonry)
- CSS 容器查詢(Container Queries)
flex 布局中的 gap 屬性
gap 并非是新的屬性,它一直存在于多欄布局 multi-column 與 grid 布局中,其中:
- column-gap 屬性用來設置多欄布局 multi-column 中元素列之間的間隔大小
- grid 布局中 gap 屬性是用來設置網(wǎng)格行與列之間的間隙,該屬性是 row-gap 和 column-gap 的簡寫形式,并且起初是叫 grid-gap
譬如我們有如下一個 grid 布局:
- <div class="grid-container">
- <div class="item">1</div>
- <div class="item">2</div>
- <div class="item">3</div>
- <div class="item">4</div>
- <div class="item">5</div>
- </div>
- .grid-container {
- display: grid;
- border: 5px solid;
- padding: 20px;
- grid-template-columns: 1fr 1fr 1fr;
- }
- .item {
- width: 100px;
- height: 100px;
- background: deeppink;
- border: 2px solid #333;
- }
效果如下:
grid 布局
通過給 grid-container 添加 gap 屬性,可以非常方便的設置網(wǎng)格行與列之間的間隙:
- .grid-container {
- display: grid;
- border: 5px solid;
- padding: 20px;
- grid-template-columns: 1fr 1fr 1fr;
- + gap: 5px;
- }
而從 Chromium 84 開始,我們可以開始在 flex 布局中使用 gap 屬性了!Can i use -- gap property for Flexbox[2]
Can i use -- gap property for Flexbox
它的作用與在 grid 布局中的類似,可以控制水平和豎直方向上 flex item 之間的間距:
- .flex-container {
- width: 500px;
- display: flex;
- flex-wrap: wrap;
- gap: 5px;
- justify-content: center;
- border: 2px solid #333;
- }
- .item {
- width: 80px;
- height: 100px;
- background: deeppink;
- }
gap 屬性的優(yōu)勢在于,它避免了傳統(tǒng)的使用 margin 的時候需要考慮第一個或者最后一個元素的左邊距或者右邊距的煩惱。正常而言,4 個水平的 flex item,它們就應該只有 3 個間隙。gap 只生效于兩個 flex item 之間。
控制容器寬高比屬性 aspect-ratio
保持元素容器一致的寬高比(稱為長寬比)對于響應式 Web 設計和在某些布局當中至關(guān)重要?,F(xiàn)在,通過 Chromium 88 和 Firefox 87,我們有了一種更直接的方法來控制元素的寬高比 -- aspect-ratio。Can i use -- aspect-ratio[3]
Can i use -- aspect-ratio
首先,我們只需要設定元素的寬,或者元素的高,再通過 aspect-ratio 屬性,即可以控制元素的整體寬高:
- <div class="width"></div>
- <div class="height"></div>
- div {
- background: deeppink;
- aspect-ratio: 1/1;
- }
- .width {
- width: 100px;
- }
- .height {
- height: 100px;
- }
都可以得到如下圖形:
其次,設定了 aspect-ratio 的元素,元素的高寬其中一個發(fā)生變化,另外一個會跟隨變化:
- <div class="container">
- <div>寬高比1:1</div>
- <div>寬高比2:1</div>
- <div>寬高比3:1</div>
- </div>
- .container {
- display: flex;
- width: 30vw;
- padding: 20px;
- gap: 20px;
- }
- .container > div {
- flex-grow: 1;
- background: deeppink;
- }
- .container > div:nth-child(1) {
- aspect-ratio: 1/1;
- }
- .container > div:nth-child(2) {
- aspect-ratio: 2/1;
- }
- .container > div:nth-child(3) {
- aspect-ratio: 3/1;
- }
當容器大小變化,每個子元素的寬度變寬,元素的高度也隨著設定的 aspect-ratio 比例跟隨變化:
CodePen Demo -- aspect-ratio Demo[4]
firefox 下的 CSS Grid 瀑布流布局(grid-template-rows: masonry)
grid-template-rows: masonry 是 firefox 在 firefox 87 開始支持的一種基于 grid 布局快速創(chuàng)建瀑布流布局的方式。并且 firefox 一直在推動該屬性進入標準當中。
從 firefox 87 開始,在瀏覽器輸入網(wǎng)址欄輸入 about:config 并且開啟 layout.css.grid-template-masonry-value.enabled 配置使用。Can i use -- grid-template-rows: masonry[5]
正常而言,我們想要實現(xiàn)瀑布流布局還是需要花費一定的功夫的,即便是基于 grid 布局。在之前,我們通過 grid 布局,通過精細化控制每一個 grid item,也可以實現(xiàn)一些偽瀑布流布局:
- <div class="g-container">
- <div class="g-item">1</div>
- <div class="g-item">2</div>
- <div class="g-item">3</div>
- <div class="g-item">4</div>
- <div class="g-item">5</div>
- <div class="g-item">6</div>
- <div class="g-item">7</div>
- <div class="g-item">8</div>
- </div>
- .g-container {
- height: 100vh;
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- grid-template-rows: repeat(8, 1fr);
- }
- .g-item {
- &:nth-child(1) {
- grid-column: 1;
- grid-row: 1 / 3;
- }
- &:nth-child(2) {
- grid-column: 2;
- grid-row: 1 / 4;
- }
- &:nth-child(3) {
- grid-column: 3;
- grid-row: 1 / 5;
- }
- &:nth-child(4) {
- grid-column: 4;
- grid-row: 1 / 6;
- }
- &:nth-child(5) {
- grid-column: 1;
- grid-row: 3 / 9;
- }
- &:nth-child(6) {
- grid-column: 2;
- grid-row: 4 / 9;
- }
- &:nth-child(7) {
- grid-column: 3;
- grid-row: 5 / 9;
- }
- &:nth-child(8) {
- grid-column: 4;
- grid-row: 6 / 9;
- }
- }
效果如下:
CSS Grid 實現(xiàn)偽瀑布流布局
CodePen Demo -- CSS Grid 實現(xiàn)偽瀑布流布局[6]
在上述 Demo 中,使用 grid-template-columns、grid-template-rows 分割行列,使用 grid-row 控制每個 grid item 的所占格子的大小,但是這樣做的成本太高了,元素一多,計算量也非常大,并且還是在我們提前知道每個元素的高寬的前提下。
而在有了 grid-template-rows: masonry 之后,一切都會變得簡單許多,對于一個不確定每個元素高度的 4 列的 grid 布局:
- .container {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- }
正常而言,看到的會是這樣:
簡單的給容器加上 grid-template-rows: masonry,表示豎方向上,采用瀑布流布局:
- .container {
- display: grid;
- grid-template-columns: repeat(4, 1fr);
- + grid-template-rows: masonry;
- }
便可以輕松的得到這樣一種瀑布流布局:
如果你在使用 firefox,并且開啟了 layout.css.grid-template-masonry-value.enabled 配置,可以戳進下面的 DEMO 感受一下:
CodePen Demo -- grid-template-rows: masonry 實現(xiàn)瀑布流布局[7]
當然,這是一個最簡單的 DEMO,關(guān)于更多 grid-template-rows: masonry 相關(guān)知識,你可以詳細的看看這篇文章:Native CSS Masonry Layout In CSS Grid[8]
CSS 容器查詢(Container Queries)
什么是 CSS 容器查詢[9](Container Queries)?
在之前,對于同個樣式,我們?nèi)绻M鶕?jù)視口大小得到不一樣效果,通常使用的是媒體查詢。
但是,一些容器或者組件的設計可能并不總是與視口的大小有關(guān),而是與組件在布局中的放置位置有關(guān)。
所以在未來,新增了一種方式可以對不同狀態(tài)下的容器樣式進行控制,也就是容器查詢。在最新的 Chrome Canary[10] 中,我們可以通過 chrome://flags/#enable-container-queries 開啟 Container Queries 功能。
假設我們有如下結(jié)構(gòu):
- <div class="wrap">
- <div class="g-container">
- <div class="child">Title</div>
- <p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Necessitatibus vel eligendi, esse illum similique sint!!</p>
- </div>
- </div>
正常情況下的樣式如下:
- .g-container {
- display: flex;
- flex-wrap: nowrap;
- border: 2px solid #ddd;
- .child {
- flex-shrink: 0;
- width: 200px;
- height: 100px;
- background: deeppink;
- }
- p {
- height: 100px;
- font-size: 16px;
- }
- }
結(jié)構(gòu)如下:
在未來,我們可以通過 @container query 語法,設定父容器 .wrap 在不同寬度下的不同表現(xiàn),在上述代碼基礎(chǔ)上,新增下述代碼:
- .wrap {
- contain: layout inline-size;
- resize: horizontal;
- overflow: auto;
- }
- .g-container {
- display: flex;
- flex-wrap: nowrap;
- border: 2px solid #ddd;
- .child {
- flex-shrink: 0;
- width: 200px;
- height: 100px;
- background: deeppink;
- }
- p {
- height: 100px;
- font-size: 16px;
- }
- }
- // 當 .wrap 寬度小于等于 400px 時下述代碼生效
- @container (max-width: 400px) {
- .g-container {
- flex-wrap: wrap;
- flex-direction: column;
- }
- .g-container .child {
- width: 100%;
- }
- }
注意這里要開啟 @container query,需要配合容器的 contain 屬性,這里設置了 contain: layout inline-size,當 .wrap 寬度小于等于 400px 時,@container (max-width: 400px) 內(nèi)的代碼則生效,從橫向布局 flex-wrap: nowrap 變換成了縱向換行布局 flex-wrap: wrap:
如果你的瀏覽器已經(jīng)開啟了 chrome://flags/#enable-container-queries,你可以戳這個代碼感受一下:
CodePen Demo -- CSS @container query Demo[11]
媒體查詢與容器查詢的異同,通過一張簡單的圖看看,核心的點在于容器的寬度發(fā)生變化時,視口的寬度不一定會發(fā)生變化:
這里僅僅是介紹了 @container query 的冰山一角,更多內(nèi)容你可以戳這里了解更多:say-hello-to-css-container-queries[12]
最后
好了,本文到此結(jié)束,希望對你有幫助 :)
更多精彩 CSS 技術(shù)文章匯總在我的 Github -- iCSS[13] .
參考資料
- [1]Chrome Canary: https://www.google.com/chrome/canary/
- [2]Can i use -- gap property for Flexbox: https://caniuse.com/?search=flex%20gap
- [3]Can i use -- aspect-ratio: https://caniuse.com/?search=aspect-ratio
- [4]CodePen Demo -- aspect-ratio Demo: https://codepen.io/Chokcoco/pen/eYgjbqG
- [5]Can i use -- grid-template-rows: masonry: https://caniuse.com/?search=grid-template-rows
- [6]CodePen Demo -- CSS Grid 實現(xiàn)偽瀑布流布局: https://codepen.io/Chokcoco/pen/KGXqyo
- [7]CodePen Demo -- grid-template-rows: masonry 實現(xiàn)瀑布流布局: https://codepen.io/Chokcoco/pen/NWdBojd
- [8]Native CSS Masonry Layout In CSS Grid: https://www.smashingmagazine.com/native-css-masonry-layout-css-grid/
- [9]CSS 容器查詢: https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Container_Queries
- [10]Chrome Canary: https://www.google.com/chrome/canary/
- [11]CodePen Demo -- CSS @container query Demo: https://codepen.io/Chokcoco/pen/PoWBOQR
- [12]say-hello-to-css-container-queries: https://ishadeed.com/article/say-hello-to-css-container-queries/
- [13]Github -- iCSS: https://github.com/chokcoco/iCSS