整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          css flex 實戰-常見的網頁布局

          篇系統介紹了flex的語法及基本知識,如果您還不熟悉flex知識,點擊這里先看看《 前端入門——彈性布局(Flex)》。本篇將結合flex基本知識去實現常見的網頁布局效果,常見的經典網頁布局有:

          上下結構,頭部高度固定,下部區域高度自適應。

          上下結構

          html:

          <main>
            <header>header</header>
            <section>content</section>
          </main>

          css:

          main{
            width:100%;
            height:100vh;
            display:flex;
            flex-direction: column;
          }
          main > header{
            height: 100px;
            background: #cdf0fd;
          }
          main > section{
            flex-grow:1;
          }

          左右結構,左邊寬度固定,右邊區域寬度自適應。

          左右結構

          html:

          <main>
            <nav>left nav</nav>
            <section>content</section>
          </main>

          css:

          main{
            width:100%;
            height:100vh;
            display:flex;
          }
          main > nav{
            width:150px;
            background: #cdf0fd;
          }
          main > section{
            flex-grow:1;
          }

          上中下結構,頭部和底部高度固定,中間區域高度自適應。

          上中下結構

          html:

          <main>
          <header>header</header>
          <section>content</section>
          <footer>footer</footer>
          </main>

          css:

          main{
            width:100%;
            height:100vh;
            display:flex;
            flex-direction: column;
          }
          main > header,
          main > footer{
              height: 100px;
              background: #cdf0fd;
            }
          main > section{
            flex-grow:1;
          }

          左中右結構,左邊和右邊寬度固定,中間區域寬度自適應。

          左中右結構

          html:

          <main>
          <nav>left nav</nav>
          <section>content</section>
          <aside>right aside</aside>
          </main>

          css:

          main{
            width:100%;
            height:100vh;
            display:flex;
          }
          main > nav,
          main > aside{
              width:150px;
              background: #cdf0fd;
            }
          main > section{
            flex-grow:1;
          }

          圣杯布局,就是中間區域再嵌套其它結構。

          1、上中下結構里,中間區域嵌套左中右結構

          圣杯布局1

          html:

          <main>
           <header>header</header>
          <section>
             <!--嵌套左中右結構-->
              <nav>left nav</nav>
              <section>content</section>
              <aside>right aside</aside>
          </section>
          <footer>footer</footer>
          </main>

          css:

          main{
            width:100%;
            height:100vh;
            display:flex;
            flex-direction: column;
          }
          main > header,
            main > footer{
              height: 100px;
              background: #cdf0fd;
            }
          main > section{
            flex-grow:1;
            display:flex;
          }
          /*嵌套的左中右結構*/
          main > section > nav,
          main > section > aside{
              width:150px;
              background: #fdcdcd;
           }
          main > section > section{
            width:100%;
            flex-grow:1;
          }

          2、左中右結構里,中間區域嵌套上中下結構

          圣杯布局2

          html:

          <main>
            <nav>left nav</nav>
            <section>
              <!--嵌套上中下結構-->
                <header>header</header>
                <section>content</section>
                <footer>footer</footer>
            </section>
          	<aside>right aside</aside>
          </main>

          css:

           main{
             width:100%;
             height:100vh;
             display:flex;
           }
          main > nav,
          main > aside{
              width:150px;
              background: #cdf0fd;
            }
          main > section{
            flex-grow:1;
            width:100%;
            display:flex;
            flex-direction: column;
          }
          /*嵌套的上中下結構*/
          main > section > header,
          main > section > footer{
              height: 100px;
              background: #fdcdcd;
            }
          main > section > section{
            flex-grow:1;
          }

          9宮格布局

          9宮格

          html:

          <main>
                  <section>content 1 </section>
                  <section>content 2 </section>
                  <section>content 3 </section>
                  <section>content 4 </section>
                  <section>content 5 </section>
                  <section>content 6 </section>
                  <section>content 7 </section>
                  <section>content 8 </section>
                  <section>content 9 </section>
              </main>

          css:

           main{
             width:100%;
             height:100vh;
             display:flex;
             flex-wrap: wrap;
           }
          main > section{
            width: 30%;
            background:#55ff00;
            margin: 1.5%;
          }

          總結

          以上是常見的經典布局,在這些布局的基礎上可以組合、拆分制作各種各樣的布局,如果結合position:fixed定位還可以實現頭部或側邊欄固定的布局效果。

          以上布局使用傳統的float、position也可以實現,只是相對來說比較麻煩一些,已不建議使用,所以了解下就可以了。

          雖然flex可以滿足大部分布局,但是flex并不擅長柵格布局,后面會介紹display:grid(網格布局),網格是一組相交的水平線和垂直線,它定義了網格的列和行。所以使用網格布局能夠構建更加復雜的網頁設計。

          感謝關注,希望能夠給你有所幫助,歡迎提出錯誤,補充。


          上篇:前端入門——彈性布局(Flex)

          下篇:前端入門 —— 網格布局(Grid)


          源碼鏈接: https://pan.baidu.com/s/1bdZM8ZcdU3FdSCp2u0sx8A?pwd=9ub2
          提取碼: 9ub2

          )CSS 標準盒子模型(Box Model)

          在網頁中所有HTML元素可以看作盒子,在CSS中,"box model"術語是用來設計和布局時使用的;CSS盒模型本質上是一個盒子,封裝周圍的HTML元素包括:外邊距(margin)邊框(border)內邊距(padding)實際內容(content)四個屬性,所以布局時每個元素所占的總寬高是這4個屬性的總和;比如寬度:總元素的寬度=寬度+左填充+右填充+左邊框+右邊框+左邊距+右邊距

          1.1Margin(外邊距)清除邊框外的區域,外邊距是透明的

          1.2Border(邊框)圍繞在內邊距和內容外的邊框

          1.3Padding(內邊距)清除內容周圍的區域,內邊距是透明的

          1.4Content(內容)盒子里填充的內容比如文本,圖像等

          標準盒子模型

          寬度為100px的div

          根據盒子模型得出該元素的總寬度為:100+(20+20)+(15+15)+(15+15)(由里至外)因此如果想在此div中放置一個寬度為100px的元素,此元素的總寬度必須小于等于100px

          2)DIV+CSS布局

          Div+CSS布局就是將網頁內容用<div>分割為塊,之后使用css設置每個塊的大小,位置等

          DIV+CSS布局最重要的是靈活運用float(浮動)屬性,其值:1)left 2)right 3)both

          clear屬性作用是清除浮動,其值為:1)left 2)right 3)both

          d2向右浮動 float:right

          因為div是塊級元素,如果都沒有脫離文檔流div就會按照從上到下的順序放置

          d2設置為右浮動其他兩個div位置的變化:

          1)d1沒有脫離文檔流會占據一行,所以d2只能浮動到d1下面的右面如上圖所示

          2)d2脫離文檔流,d3自動填充到d2的位置

          d1,d2全部設置為右浮動

          1)當d1,d2都設置為右浮動時:因為css中d1在d2上面先設置,因此d1在右側,如果d2在d1上面先設置樣式,則d2在右側,d1在左側,自己測試不再截圖

          2)當d1,d2都設置為右浮動時:d3就會跑到上圖中d2的位置

          3)如果3個div都設置左或右浮動,當3個width加一起<=100%就會在第一行顯示(d1,d2,d3)

           <style type="text/css">
                #d1 {
                margin: 0px;
                background-color: red;
                padding: 0px;
                width: 50%;
                height: 100px;
                float:right; 
              }
              #d2 {
                margin: 0px;
                background-color: yellow;
                padding: 0px;
                width: 50%;
                height: 100px;
                float:right; 
              }
              #d3 {
                margin: 0px;
                background-color: green;
                padding: 0px;
                width: 50%;
                height: 100px;
              }
            </style>

          d2清除左浮動,d3設置為右浮動

          當d2清除了左浮動,d3設置為右浮動,就會如上圖所示;如果d2清除的是右浮動,d2就會在d1上面,d3就會定位在d1下面的右面,自己測試不再截圖

          當d2清除了左浮動,如果想要d2緊挨著d1(與d1在一行上),可以通過position脫離文檔流設置其上下左右屬性使其定位在d1右側,自己測試

          <!DOCTYPE html
            PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
          <html xmlns="http://www.w3.org/1999/xhtml">
          <head>
            <title>div+CSS布局</title>
            <style type="text/css">
                #d1 {
                margin: 0px;
                background-color: red;
                padding: 0px;
                width: 30%;
                height: 100px;
                float:left; 
              }
              #d2 {
                margin: 0px;
                background-color: yellow;
                padding: 0px;
                width: 40%;
                height: 100px;
                clear: left;     
              }
              #d3 {
                margin: 0px;
                background-color: green;
                padding: 0px;
                width: 30%;
                height: 100px; 
                float: right; 
              }
            </style>
          </head>
          <body>
              <div id="d1"><span style="font-size: 50px;">d1</span></div>
              <div id="d2"><span style="font-size: 50px;">d2</span></div>
              <div id="d3"><span style="font-size: 50px;">d3</span></div>
            </body>
          </html>

          DIV+CSS布局綜合運用position+上下左右屬性與float屬性為網頁進行布局

          注意:瀏覽器的兼容性問題,特別是使用IE內核的瀏覽器對W3C的規范不怎么遵守

          SS是Web開發中不可或缺的一部分,隨著Web技術的不斷革新,CSS也變得更加強大。CSS的眾多屬性你知道了多少?具體開發中該使用什么屬性才最適合恰當?如今的一些CSS屬性可以讓我們節約更多的時間。比如在Web布局中,現代CSS特性就可以更好的幫助我們快速實現如等高布局,水平垂直居中,經典的圣杯布局、寬高比例、頁腳保持在底部等效果。淘系前端技術專家大漠將詳細介紹一些不同的CSS屬性來實現這些效果,希望對同學們有所幫助。


          一 水平垂直居中


          如何實現水平垂直居中可以說是CSS面試題中的經典面試題,在多年前這個面試題給很多同學都帶來了困惑,但Flexbxo布局模塊和CSS Grid布局模塊的到來,可以說實現水平垂直居中已是非常的容易。


          Flexbox中實現水平垂直居中


          在Flexbox布局模塊中,不管是單行還是多行,要讓它們在容器中水平垂直居中都是件易事,而且方法也有多種。最常見的是在Flex容器上設置對齊方式,在Flex項目上設置 margin:auto。


          先來看在Flex容器上設置對齊方式。


          Flex容器和Flex項目上設置對齊方式


          你可能已經知道在Flex容器上設置 justify-content、align-items 的值為 center 時,可以讓元素在Flex容器中達到水平垂直居中的效果。來看一個示例:

          
          <!-- HTML -->
          <div class="flex__container">
              <div class="flex__item"></div>
          </div>
          
          /* CSS */
          .flex__container {
              display: flex;
              justify-content: center;
              align-items: center;
          }
          

          效果如下:

          這種方式特別適應于讓Icon圖標在容器中水平垂直居中,不同的是在Icon圖標容器上顯示設置display: inline-flex。比如下面這個示例:

          
          <!-- HTML -->
          <div class="flex__container">
              <svg> </svg>
          </div>
          
          /* CSS */
          .flex__container {
              display: inline-flex;
              align-items: center;
              justify-content: center;
          }
          	

          效果如下:



          在這種模式之下,如果要讓多個元素實現水平垂直居中的效果,那還需要加上 flex-direction: column,比如:

          
          <!-- HTML -->
          <div class="flex__container">
              <div class="avatar">:)</div>
              <div class="media__heading"></div>
              <div class="media__content"></div>
              <div class="action"></div>
          </div>
          
          /* CSS */
          .flex__container  {
              display: flex;
              flex-direction: column;
              justify-content: center;
              align-items: center;
          }

          效果如下:

          在Flexbox布局中,還可以像下面這樣讓Flex項目在Flex容器中達到水平垂直居中的效果:

          
          <!-- HTML -->
          <div class="flex__container">
              <div class="flex__item"></div>
          </div>
          
          /* CSS */
          .flex__container {
              display: flex; // 或inline-flex
              justify-content: center;
          }
          
          .flex__item {
              align-self: center;
          }

          效果如下:



          如果在Flex容器中有多個Flex項目時,該方法同樣有效:

          
          .flex__container {
              display: flex; // 或inline-flex
              justify-content: center;
          }
          
          .flex__container > * {
              align-self: center;
          }

          比如下面這個效果:



          除此之外,還可以使用 place-content: center 讓Flex項目實現水平垂直居中:

          
          .flex__container {
              display: flex;
              place-content: center;
          }
          
          .flex__item {
              align-self: center;
          }

          效果如下:



          或者換:

          
          .flex__container {
              display: flex;
              place-content: center;
              place-items: center;
          }
          

          效果如下:



          這兩種方式同樣適用于Flex容器中有多個Flex項目的情景:

          
          .flex__container {
              display: flex;
              flex-direction: column;
              place-content: center;
          }
          
          .flex__container > * {
              align-self: center;
          }
          
          // 或
          
          .flex__container {
              display: flex;
              flex-direction: column;
              place-content: center;
              place-items: center;
          }

          效果如下:



          可能很多同學對于 place-content 和 place-items 會感到陌生。其實 place-content 是 align-content 和 justify-content 的簡寫屬性;而 place-items 是 align-items 和 justify-items 的簡寫屬性。即:

          
          .flex__container {
              place-content: center;
              place-items: center;
          }

          等效于:

          
          .flex__container {
              align-content: center;
              justify-content: center;
          
              align-items: center;
              justify-items: center;
          }
          

          雖然擴展出來有四個屬性,但最終等效于:

          
          .flex__container {
              display: flex;
              align-items: center;
              justify-content: center;
          }
          
          // 多行
          .flex__container {
              display: flex;
              flex-direction: column;
              align-items: center;
              justify-content: center;
          }
          

          在Flex項目上設置margin: auto


          如果在Flex容器中只有一個Flex項目,還可以顯式在Flex項目中顯式設置 margin 的值為auto,這樣也可以讓Flex項目在Flex容器中水平垂直居中。例如:

          
          .flex__container {
              display: flex; // 或 inline-flex
          }
          
          .flex__item {
              margin: auto;
          }
          

          效果如下:



          整個過程,你可以通過下面這個示例來體驗。嘗試著選中不同方向的 margin 值:


          Grid中實現水平垂直居中


          CSS Grid布局可以說是現代Web布局中的銀彈。它也是到目前為止布局系統中唯一一個二維布局系統。


          在CSS Grid布局中,只需要僅僅的幾行代碼也可以快速的幫助我們實現水平垂直居中的效果。比如下面這個示例:

          
          <!-- HTML -->
          <div class="grid__container">
              <div class="grid__item"></div>
          </div>
          
          /* CSS */
          .grid {
              display: grid; // 或 inline-grid
              place-items: center
          }

          效果如下:



          在CSS Grid布局模塊中,只要顯式設置了 display: grid(或 inline-grid)就會創建Grid容器和Grid項目,也會自動生成網格線,即行和列(默認為一行一列)。



          在沒有顯式地在Grid容器上設置 grid-template-columns 和 grid-template-rows,瀏覽器會將Grid容器默認設置為Grid內容大小:



          這種方法也適用于CSS Grid容器中有多個子元素(Grid項目),比如:

          
          <!-- HTML -->
          <div class="grid__container">
              <div class="avatar">:)</div>
              <div class="media__heading"></div>
              <div class="media__content"></div>
              <div class="action"></div>
          </div>

          這個時候你看到的效果如下:



          而且 palce-items 適用于每個單元格。這意味著它將居中單元格的內容。比如下面這個示例:

          
          <!-- HTML -->
          <div class="grid__container">
              <div class="grid__item">
                  <h3>Special title treatment</h3>
                  <p>With supporting text below as a natural lead-in to additional content.</p>
                  <div class="action">Go somewhere</div>
              </div>
          </div>
          
          /* CSS */
          .grid__container {
              display: grid;
              place-items: center;
              grid-template-columns: repeat(2, 1fr);
              gap: 2vh;
          }
          
          
          .grid__item {
              display: grid;
              place-items: center;
          }
          

          效果如下:



          二 等高布局


          等高布局也是Web中非常常見的一種布局方式,而且實現等高布局的方案也有很多種。這里我們主要來看Flexbox布局模塊和Grid布局模塊給我們帶來了什么樣的變化。


          在Flexbox和Grid布局模塊中,讓我們實現等高布局已經是非常的簡單了,比如:

          
          <!-- Flexbox -->
          <flex__container>
              <flex__item></flex__item>
              <flex__item></flex__item>
              <flex__item></flex__item>
          </flex__container>
          
          /* CSS */
          .flex__container {
              display: flex; // 或 inline-flex
          }

          簡單地說,在容器上顯式設置了 display 的值為 flex 或 inline-flex,該容器的所有子元素的高度都相等,因為容器的 align-items 的默認值為 stretch。


          這個時候你看到的效果如下:



          這種方式特別適用于卡片組件中:



          在Grid布局模塊中類似:

          
          <!-- HTML -->
          <grid__container>
              <grid__item></grid__item>
              <grid__item></grid__item>
              <grid__item></grid__item>
          </grid__container>
          
          /* CSS */
          .grid__container {
              display: grid;
              grid-template-columns: 20vw 1fr 20vw; /* 根據需求調整值*/
          }

          效果如下:



          同樣在一些卡片類布局中運用:



          如果需求有所調整,比如在Flex項目 或 Grid項目的子元素高度和容器高度相同。

          
          <!-- HTML -->
          <flex__container>
              <flex__item>
                  <content></content>
              </flex__item>
          </flex__container>
          
          /* CSS */
          .flex__container {
              display: flex;
          }
          
          .content {
              height: 100%
          }
          
          // 或
          .grid__container {
              display: grid;
              grid-auto-flow: column;
          }
          
          .content {
              height: 100%;
          }

          效果如下:



          三 Sticky Footer


          首先用下圖來描述什么是Sticky Footer布局效果:



          Sticky Footer實現方案和等高、垂直居中一樣,同樣有很多種方案可以實現。


          比如像下面這樣的結構:

          
          <!-- HTML -->
          <header></header>
          <main></main>
          <footer></footer>

          先來看Flexbox布局模塊中的實現方案:

          
          body {
              display: flex;
              flex-direction: column;
          }
          
          footer {
              margin-top: auto;
          }
          


          可以嘗試著在 main 區域右下角向下拖動,改變主內容區域的高度,你會發現“當內容不足一屏時,<footer> 會在頁面的最底部,當內容超出一屏時,<footer> 會自動往后延后”。


          在Flexbox布局中,還可以在 <main> 區域上設置下面的樣式,達到相等的效果:

          
          body {
              display: flex;
              flex-direction: column;
          }
          
          main {
              flex: 1 0 auto;
          }
          

          效果如下:



          <main> 中的 flex: 1 0 auto 相當于是:

          
          main {
              flex-grow: 1; /*容器有剩余空間時,main區域會擴展*/
              flex-shrink: 0; /*容器有不足空間時,main區域不會收縮*/
              flex-basis: auto; /*main區域高度的基準值為main內容自動高度*/
          }


          如果你想省事的話,可以在 main 上顯式設置 flex-grow:1,因為 flex-shrink 和 flex-basis 的默認值為 1 和 auto。


          在CSS Grid布局中我們可以借助 1fr 讓 <main> 區域根據Grid容器剩余空間來做計算。

          
          .grid__container {
              display: grid;
              grid-template-rows: auto 1fr auto;
          }

          效果如下:



          四 均分列


          在Web布局中,很多時候會對列做均分布局,最為常見的就是在移動端的底部Bar,比如下圖這樣的一個效果:



          在Flexbox和Grid還沒出現之前,如果希望真正的做到均分效果,可以用 100%(或 100vw)除以具體的列數。比如:

          
          <!-- HTML -->
          <container>
              <column></column>
              <column></column>
              <column></column>
          </container>
          
          /* CCSS */
          .container {
              inline-size: 50vw;
              min-inline-size: 320px;
              display: flex-row;
          }
          
          .column {
              float: left;
              width: calc(100% / 3);
          }

          效果如下:



          通過瀏覽器調試器中可以發現,現個列的寬度都是相等的:



          在Flexbox和Grid布局中,實現上面的效果會變得更容易地多。先來看Flexbox中的布局:

          
          <!-- HTML -->
          <flex__container>
              <flex__item></flex__item>
              <flex__item></flex__item>
              <flex__item></flex__item>
          </flex__container>
          
          /* CSS */
          .flex__container {
              inline-size: 50vw;
              display: flex;
          }
          
          .flex__item {
              flex: 1;
          }
          

          效果如下:



          在Flexbox布局模塊中,當flex取的值是一個單值(無單位的數),比如示例中的 flex:1,它會當作顯式的設置了 flex-grow: 1。瀏覽器計算出來的 flex:



          接下來看Grid中如何實現上例的效果:

          
          <!-- HTML -->
          <grid__container>
              <grid__item></grid__item>
              <grid__item></grid__item>
              <grid__item></grid__item>
          </grid__container>
          
          /* CSS */
          .grid__container {
              display: grid;
              grid-template-columns: repeat(3, 1fr); /*這里的3表示具體的列數*/
          }

          最終的效果是相同的:



          這樣的布局方式也適用于其他的布局中。但不管是Flexbox還是Grid布局中,都存在一定的缺陷,當容器沒有足夠的空間容納Flex項目(或Grid項目)時,Flex項目或Grid項目會溢出(或隱藏,如果Flex容器或Grid容器顯式設置了 overflow:hidden):



          修復這種現象最簡單的方式是在Flex容器或Grid容器顯式設置一個 min-width(或 min-inline-size):

          
          .flex__container {
              min-inline-size: 300px;
          }

          不過話又說回來,比如我們的Flex項目(或Grid項目)是一個卡片,每張卡片寬度是相等之外,更希望容器沒有足夠空間時,Flex項目(或Grid項目)會自動斷行排列。


          我們繼續通過示例向大家展示。先來看Flexbox實現方案:

          
          .flex__container {
              display: flex;
              flex-wrap: wrap;
          }
          
          .flex__item {
              flex: 0 1 calc((100vw - 18vh) / 4); /* calc(100vw -18vh) / 4 是flex-basis的基準值 */
          }
          



          你可以嘗試著調整瀏覽器的視窗寬度,當瀏覽器的視窗越來越小時,Flex容器寬度也就會越來越小,當Flex容器小到沒有足夠的空間容納四個Flex項目(就此例而言),那么Flex項目就會斷行排列:



          基于該例,如果把Flex項目的 flex 值改成:

          
          .flex__item {
              flex: 0 0 400px;
          }

          這個時候,當Flex容器沒有足夠空間時,Flex項目會按 flex-basis: 400px 計算其寬度,Flex容器沒有足夠空間時,Flex就會斷行:



          反過來,如果Flex項目的值 flex 改成:

          
          .flex__item {
              flex: 1 0 400px;
          }

          當Flex容器沒有足夠空間排列Flex項目時,Flex項目會按 flex-basis: 400px 計算其寬度,Flex會斷行,并且同一行出現剩余空間時,Flex項目會擴展,占滿整個Flex容器:



          在Grid中實現類似的效果要更復雜一點??梢允褂?repeat() 函數,1fr 以及 auto-fit 等特性:

          
          .grid__container {
              display: grid;
              grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
              gap: 2vh;
          }

          效果如下:



          如果你對這方面知識感興趣的話,還可以移步閱讀《Container Query Solutions with CSS Grid and Flexbox》一文。


          其實在Grid中與 auto-fit 對比的值還有一個叫 auto-fill。但兩者的差異是非常地大,用下圖來描述 auto-fit 和 auto-fill 的差異:


          另外這種方式也是到目前為止一種不需要借助CSS媒體查詢就可以實現響應式布局效果。


          五 圣杯布局


          圣杯布局(Holy Grail Layout))是Web中典型的布局模式??瓷先ハ裣聢D這樣:



          對于圣杯布局而言,HTML結構是有一定的要求,那就是內容為先:

          
          <!-- HTML -->
          <header></header>
          <main>
              <article></article> <!-- 主內容 -->
              <nav></nav>
              <aside></aside>
          </main>
          <footer></footer>

          在這里主要還是和大家一起探討,如何使用Flexbox和Grid布局模塊來實現圣杯布局。先來看Flexbox實現方案:

          
          body {
              width: 100vw;
              display: flex;
              flex-direction: column;
          }
          
          main {
              flex: 1;
              min-height: 0;
          
              display: flex;
              align-items: stretch;
              width: 100%;
          }
          
          footer {
              margin-top: auto;
          }
          
          nav {
              width: 220px;
              order: -1;
          }
          
          article {
              flex: 1;
          }
          
          aside {
              width: 220px;
          }


          效果如下:



          通過在 nav、aside 和 article 上顯式設置 order 的值,可以很好的控制這三個區域的布局順序。比如說,希望 <aside> 在 <article> 之前排列,只需要在上面的示例基礎上做一點點調整:

          
          nav {
              order: 0;
          }
          
          aside {
              order: -1;
          }

          效果如下:


          注意,order的默認值為0,值越大越排在后面!


          在上例的基礎上,借助CSS媒體對象的特性,可以很容易實現響應式的圣杯布局效果:

          
          @media screen and (max-width: 800px) {
              main {
                  flex-direction: column;
              }
          
              nav, aside {
                  width: 100%;
              }
          }

          效果如下:



          嘗試著拖動瀏覽器來改變視窗大小,你可以看到如下圖的效果:


          在Grid布局模塊中,實現圣杯布局要比Flexbox布局模塊中更容易,而且更靈活。在CSS Grid布局模塊中,HTML結構可以更簡潔:

          
          <!-- HTML -->
          <body>
              <header></header>
              <main></main>
              <nav></nav>
              <aside></aside>
              <footer></footer>
          </body>
          

          在CSS方面有很多種方案可以實現圣杯布局效果。我們先來看第一種:

          
          body {
              display: grid;
              grid-template: auto 1fr auto / 220px 1fr 220px;
          }
          
          header {
              grid-column: 1 / 4;
          }
          
          main {
              grid-column: 2 / 3;
              grid-row: 2 / 3;
          }
          
          nav {
              grid-column: 1 / 2;
              grid-row: 2 / 3;
          }
          
          aside {
              grid-column: 3 / 4;
              grid-row: 2 / 3;
          }
          footer {
              grid-column: 1 / 4;
          }

          效果如下:



          上面示例采用的是網格線來給每個區域進行定位的:



          和Flexbox布局類似,在媒體查詢中可以改變每個網格區域的位置:

          
          @media screen and (max-width: 800px) {
              body {
                  grid-template-rows: auto;
                  grid-template-columns: auto;
              }
          
              header,
              main,
              nav,
              aside,
              footer {
                  grid-column: 1 / 2;
                  min-height: auto;
              }
          
              main {
                  grid-row: 3 / 4;
                  margin: 0;
              }
          
              nav {
                  grid-row: 2 / 3;
              }
          
              aside {
                  grid-row: 4 / 5;
              }
          
              footer {
                  grid-row: 5 / 6;
              }
          }


          除了 grid-template(即 grid-template-columns 和 grid-template-rows)之外,在Grid布局中還可以使用 grid-area 和 grid-template-areas 屬性的結合,也能很方便的實現CSS圣杯布局?;谏厦娴氖纠?,只需要把你的CSS調整為:

          
          body {
              display: grid;
              grid-template-areas:
                  "header header header"
                  "nav main aside"
                  "footer footer footer";
          }
          
          header {
              grid-area: header;
          }
          
          main {
              grid-area: main;
          }
          
          nav {
              grid-area: nav;
          }
          
          aside {
              grid-area: aside;
          }
          
          footer {
              grid-area: footer;
          }
          
          @media screen and (max-width: 800px) {
              body {
                  grid-template-areas:
                      "header"
                      "nav"
                      "main"
                      "aside"
                      "footer";
              }
          }
          

          效果如下:



          你可能發現了它們之間的差異性:



          后面這個示例中,<nav>、<main> 和 <aside> 區域寬度相等。這是因為我們示例中通過 grid-template-areas 來聲明網格,在使用 grid-template-areas 創建網格時,其實也隱式的創建了網格線,只不過他和 grid-template 不同的是 grid-template 可以顯式的指定網格軌道大小,而grid-template-areas 在該示例中相當于網格軌道大小都是 1fr。



          如果我們希望 <main> 的區域變得更大,那么可以在 grid-template-areas 上做個調整:

          
          body {
              display: grid;
              grid-template-areas:
                  "header header header header header"
                  "nav main main main aside"
                  "footer footer footer footer footer";
          }

          效果如下:



          這個時候網格區域的劃分像下圖這樣:



          雖然在效果有所調整了,但還是均分狀態。更好的解決方案是,將 grid-template-areas 和 grid-template 結合起來使用:

          
          body {
              display: grid;
              grid-template-areas:
                  "header header header"
                  "nav main aside"
                  "footer footer footer";
              grid-template-columns: 220px 1fr 220px;
              grid-template-rows: auto 1fr auto;
          }
          
          header {
              grid-area: header;
          }
          
          main {
              grid-area: main;
          }
          
          nav {
              grid-area: nav;
          }
          
          aside {
              grid-area: aside;
          }
          
          footer {
              grid-area: footer;
          }
          
          @media screen and (max-width: 800px) {
              body {
                  grid-template-areas:
                      "header"
                      "nav"
                      "main"
                      "aside"
                      "footer";
                  grid-template-columns: 1fr;
                  grid-template-rows: auto auto 1fr auto auto;
              }
          
              main {
                  margin-left: 0;
                  margin-right: 0;
              }
          }
          

          效果如下:



          你可以發現,這個時候,網格線的區域的命名像下圖這樣:



          六 12列網格布局


          12列網格布局最早是由960.gs提出的網格布局系統:



          12列網格布局在設計系統和CSS Framework中經常使用,比如業內經典的Bootstrap就采用了12列網格布局系統:



          在社區中也有很多在線工具,幫助我們快速構建12列網格系統,比如 Free CSS Grid Tools & Resources For Developers 一文中羅列的工具。



          不過這里主要是想和大家一起看看在Flexbox和Grid布局模塊中是如何實現12列的網格布局系統。


          先來看Flexbox布局模塊。12列網格布局的HTMl結構一般類似于下面這樣:

          
          <!-- HTML -->
          <flex__grid>
              <flex__row>
                  <flex__item col4></flex__item col4>
                  <flex__item col4></flex__item col4>
                  <flex__item col4></flex__item col4>
              </flex__row>
          </flex__grid>


          注意,12列網格中,一般同一行的列數值和剛好等于12。比如上面的HTML結構,行中有三列,每列的寬度剛好四個網格寬度加兩個列間距。并且在計算的時候有一套成熟的計算公式:



          而且還設計上也會有所差異,比如說距離容器兩側有沒有間距等:



          這些的差異對于計算公式和樣式代碼的設計都略有差異。我們用其中一個為例:

          
          :root {
              --gutter: 10px;
              --columns: 12;
              --span: 1;
          }
          
          .flex__container {
              display: flex;
              flex-direction: column;
              padding-left: var(--gutter);
              padding-right: var(--gutter);
          }
          
          .flex__row {
              display: flex;
              margin-left: calc(var(--gutter) * -1);
              margin-right: calc(var(--gutter) * -1);
          }
          
          .flex__row + .flex__row {
              margin-top: 2vh;
          }
          
          .flex__item {
              flex: 1 1
                  calc((100% / var(--columns) - var(--gutter)) * var(--span));
              margin: 0 var(--gutter);
          }
          
          .flex__item1 {
              --span: 1;
          }
          
          .flex__item2 {
              --span: 2;
          }
          
          .flex__item3 {
              --span: 3;
          }
          
          .flex__item4 {
              --span: 4;
          }
          
          .flex__item5 {
              --span: 5;
          }
          
          .flex__item6 {
              --span: 6;
          }
          
          .flex__item7 {
              --span: 7;
          }
          
          .flex__item8 {
              --span: 8;
          }
          
          .flex__item9 {
              --span: 9;
          }
          
          .flex__item10 {
              --span: 10;
          }
          
          .flex__item11 {
              --span: 11;
          }
          
          .flex__item12 {
              --span: 12;
          }

          你會看到的效果如下:



          在該示例中采用了CSS自定義屬性相關的特性,讓整個計算變得更容易一些。


          對于使用CSS Grid布局模塊來實現12列網格布局,相對而言,不管是HTML結構還是CSS代碼都會更簡易一些。在使用CSS Grid布局模塊實現12列網格布局,將會運用到repeat()、minmax()、gap 和 fr 等特性。具體的來看一個示例吧。

          
          <!-- HTML -->
          <grid__container>
              <grid__item></grid__item>
          </grid__container>

          我們來看CSS代碼:


          • 使用 fr 將網格均分為相等的值,即每列寬度都是 1 個 fr;配合 repeat() 函數,即repeat(12, 1fr) 創建了12列網格。


          • 使用 gap 可以用來控制網格之間的間距。
          • 配合 minmax() 還可以設置網格最小值。


          具體的代碼如下:

          
          :root {
              --columns: 12;
              --gap: 10px;
              --span: 1;
          }
          
          .grid__container {
              display: grid;
              grid-template-columns: repeat(var(--columns), 1fr);
              grid-template-rows: 1fr;
              gap: var(--gap);
              padding-left: calc(var(--gap) / 2);
              padding-right: calc(var(--gap) / 2);
          }
          
          .grid__item {
              min-block-size: 10vh;
              grid-column: span var(--span);
          }
          
          .col1 {
              --span: 1;
          }
          
          .col2 {
              --span: 2;
          }
          
          .col3 {
              --span: 3;
          }
          
          .col4 {
              --span: 4;
          }
          
          .col5 {
              --span: 5;
          }
          
          .col6 {
              --span: 6;
          }
          
          .col7 {
              --span: 7;
          }
          
          .col8 {
              --span: 8;
          }
          
          .col9 {
              --span: 9;
          }
          
          .col10 {
              --span: 10;
          }
          
          .col11 {
              --span: 11;
          }
          
          .col12 {
              --span: 12;
          }
          

          你將看到的效果如下:



          就該示例而言,grid-template-columns: repeat(12, 1fr) 創建網格如下圖所示:



          除了上述這種粗暴的方式,還可以更靈活一些,將 auto-fit、minmax() 以及 grid-auto-flow: dense 等來創建:

          
          .grid__container {
              padding: 1em;
              display: grid;
              grid-template-columns: repeat(auto-fit, minmax(60px, 1fr));
              gap: 1em;
              grid-auto-flow: dense;
          }


          對于 .grid__item 可以通過 grid-column、grid-row 來控制網格項目的位置:



          加上 grid-auto-flow: dense 會根據Grid容器空間,Grid項目會自動流到合適的位置:



          這種布局對于雜志類的布局非常的適用。有關于這方面更詳細的介紹可以閱讀@Keir Watson的《Responsive Grid Magazine Layout in Just 20 Lines of CSS》一文。


          七 兩端對齊


          在Web布局中時常碰到兩端對齊的需求。在Flexbox布局中,時常在Flex容器中顯式設置 justify-content 的值:

          
          .flex__container {
              display: flex;
              flex-wrap: wrap;
              justify-content: space-between;
          
              width: 100%;
          }

          但在末尾行,如果和前面行的個數不相同(Flex項目)就會出現下圖這樣的效果:



          像上圖這樣的效果,并不是我們所需要的,因為我們希望在最后一行的Flex項目不足夠排列滿一行時,希望Flex項目一個緊挨一個的排列:



          在Flexbox要實現上圖這樣的效果,只需要在Flex容器中添加一個偽元素:

          
          .flex__container::after {
              content: "";
              display: flex;
              flex: 0 1 32vw;
          }

          注意,偽元素的 flex-basis 建議設置的和卡片的 flex-basis(或寬度)等同。這個時候你將看到像下面這樣的示例:



          不過這種方式也不是最佳的方式,當末尾行的個數不只少一個時,就會出現下圖這樣的效果:



          面對這樣的場景,我們需要給Flex容器添加額外的空標簽元素:


          占位符元素數量 = 每行最大的列數 - 2


          但是 gap屬性出現之后,要實現這樣的效果就不難了:

          
          body {
              padding: 1vh;
          }
          
          .flex__container {
              display: flex;
              flex-wrap: wrap;
              gap: 2vh;
          
              width: 100%;
          }
          
          .flex__item {
              flex: 0 1 calc((100vw - 8vh) / 4);
          }
          

          效果如下:



          注意,gap 運用在Flexbox中到目前為止,僅得到了Firefox瀏覽器的支持。上面的示例,使用Firefox瀏覽器,你看到的效果如下:



          在CSS Grid布局中,就可以直接使用 gap:

          
          body {
              padding: 1vh;
          }
          
          .grid__container {
              display: grid;
              grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
              gap: 1vh;
          }
          

          效果如下:



          八 選擇最佳的值


          很多時候,針對不同的場景,設計師會為我們提供不同的設計風格,比如元素大?。?/p>



          隨著 clam() 函數的到來,這一切都變得容易地多。


          clam() 函數接受三個參數,即 clam(MIN, VAL, MAX),其中 MIN 表示最小值,VAL 表示首選值,MAX 表示最大值。它們之間:


          • 如果 VAL 在 MIN 和 MAX 之間,則使用 VAL 作為函數的返回值。
          • 如果 VAL 大于 MAX,則使用 MAX 作為函數的返回值。
          • 如果 VAL 小于 MIN,則使用 MIN 作為函數的返回值。


          我們來看一個示例:

          
          .element {
              /**
              * MIN = 100px
              * VAL = 50vw ? 根據視窗的寬度計算
              * MAX = 500px
              **/
          
              width: clamp(100px, 50vw, 500px);
          }

          比如瀏覽器視窗現在所處的位置是1200px的寬度,那么 .element 渲染的結果如下:



          這個時候 .element 元素的 width 是 500px。此時,clamp(100px, 50vw, 500px) 相當于clamp(100px, 600px, 500px),對應的 VAL 值是 600px,大于 MAX 值,那么這個時候clamp() 函數返回的值是 MAX,即 500px,這個時候 .element 的 width 值就是 500px(即MAX 的值)。


          如果我們把瀏覽器視窗縮小至 760px:



          這個時候 .element 元素的 width 是 50vw。此時,clamp(100px, 50vw, 500px) 相當于clamp(100px, 380px, 500px),對應的 VAL 值是 380px,該值大于 MIN 值(100px),小于MAX 值(500px),那么這個時候 clamp() 函數返回的值是 VAL,即 50vw,這個時候.element 的 width 值就是 50vw(即 VAL 的值)。


          如果繼續將瀏覽器的視窗縮小至 170px:



          這個時候 .element 元素的 width 是 100px。此時,clamp(100px, 50vw, 500px) 相當于clamp(100px, 85px, 500px),對應的 VAL 值是 85px,該值小于 MIN 值(100px),那么這個時候 clamp() 函數返回的值是 MIN,即 100px,這個時候 .element 的 width 值就是100px(即 MIN 的值)。


          就該示例而言,clamp(100px, 50vw, 500px) 還可以這樣來理解:


          • 元素 .element 的寬度不會小于 100px(有點類似于元素設置了 min-width: 100px)。


          • 元素 .element 的寬度不會大于 500px(有點類似于元素設置了 max-width: 500px)。


          • 首選值 VAL 為 50vw,只有當視窗的寬度大于 200px 且小于 1000px 時才會有效,即元素.element 的寬度為 50vw(有點類似于元素設置了 width:50vw)。


          九 Logo圖標的對齊


          我想你在Web開發中可能碰到過類似下圖的這樣的場景:



          正像上圖所示,Logo圖像的有大有?。▽挾群透叨榷疾灰粯樱?。面對這樣的業務場景,很多時候都希望設計師能提供相同尺寸的圖像。但這樣勢必會影響Logo圖像的外觀。


          前段時間看到@Ahmad Shadeed專門寫了一篇博文《Aligning Logo Images in CSS》,就是介紹如何實現上圖這樣的布局效果。


          其實實現這樣的布局效果,主要運用到的就是CSS的 object-fit 屬性,而這個屬性早在多年前就得到了各大主流瀏覽器的支持。


          這里我們用一個簡單的示例,來看看具體實現過程。先來看HTML結構:

          
          <!-- HTML -->
          <ul class="brands">
              <li class="brands__item">
                  <a href="#">
                      <img src="img/logo.png" alt="">
                  </a>
              </li>
              <li> <!-- ... --> </li>
          </ul>

          居中對齊前面已經介紹過了,這里主要是看圖像大小方面的處理:

          
          .brands {
              display: grid;
              grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
              grid-gap: 1rem;
          }
          
          .brands__item {
              background: #eee;
          }
          
          .brands__item a {
              display: flex;
              justify-content: center;
              align-items: center;
              height: 100%;
          }
          
          .brands__item img {
              width: 130px;
              height: 75px;
              object-fit: contain;
          }
          

          這樣就能實現上圖的效果。你可能發現了,有些Logo圖像帶有背景顏色,如果讓效果更好一些,可以把CSS混合模式相關的特性運用進來:

          
          .brands__item img {
              width: 130px;
              height: 75px;
              object-fit: contain;
              mix-blend-mode: multiply;
          }
          

          這個時候,你看到的效果如下:



          object-fit 除了取值 contain 之外,還有其他幾個值:



          其實這個方案也適用于產品圖片,人物頭像等布局。


          小結


          文章中主要介紹了Web中一些布局的實現思路和具體方案。其實文章提到的效果,比如水平垂直居中、等高布局、平均分布列和Sticky Footer等,在CSS中一直有多種解決方案,只不過隨著CSS Flexbox布局模塊和CSS Grid布局模塊的到來,實現這些效果變得更為靈活和簡潔。


          當然,文章中提到的只是一些最為常見的一些效果,其實在Web布局中,特別是Flexbox布局和Grid布局中還存在著很多有意思的東西,只不過因為篇幅的原因沒有一一羅列。如果你感興趣可以再挖掘一些出來,如果你在這方面有更好的經驗或方案,歡迎在下面的評論中分享。最后希望這篇文章對你平時的工作有所幫助。


          主站蜘蛛池模板: 久久精品国产亚洲一区二区三区| 亚洲区精品久久一区二区三区| 高清国产AV一区二区三区| 视频在线观看一区二区| 久久久久国产一区二区| 91视频国产一区| 视频一区二区三区人妻系列 | 日韩高清国产一区在线| 一区二区三区91| 日本精品少妇一区二区三区| 秋霞无码一区二区| 亚洲无线码在线一区观看| 国产亚洲福利一区二区免费看| 国产一区在线mmai| 麻豆一区二区在我观看| 人妻体内射精一区二区三区| 国产福利视频一区二区| 亚洲综合无码精品一区二区三区| 四虎永久在线精品免费一区二区| 精品国产一区二区麻豆| 成人免费一区二区无码视频| 亚洲精品无码一区二区| 无码中文人妻在线一区二区三区| 精品欧洲AV无码一区二区男男| 精品三级AV无码一区| 国偷自产Av一区二区三区吞精| 黄桃AV无码免费一区二区三区 | 国产一区二区精品久久凹凸| 国产情侣一区二区三区| 色狠狠色噜噜Av天堂一区| 久久免费区一区二区三波多野| 日本不卡一区二区三区 | 亚洲乱色熟女一区二区三区蜜臀| 中文字幕一区视频| 日韩免费视频一区| 精品福利一区二区三| 成人免费视频一区| 国产在线一区二区| 波多野结衣一区二区三区| 无码人妻久久一区二区三区蜜桃| 中文字幕Av一区乱码|