圖片橫向排版最佳實踐 - CSS筆記

    本文主要說圖片的橫向排版

    將圖片排版引入到博客中是我自己的一個小需求。有時候想要分享一些平時的隨手拍,但是直接在網頁上一張張堆疊照片又顯得并不美觀,因此著手研究這個功能。

    第一次的嘗試實現是在 RAW 主題里,在這里可以看到效果。看似還行,但其實非常 naive,在許多情況下都會出現 bug 導致版式錯亂。

    目前我的最佳實現已經應用在了 VOID 主題中。另外,VOID 主題用戶中也有深度使用了這個功能的,例如這里,效果也足夠令人滿意,那么這篇文章就說說實現細節。

    常見的圖片排版方式

    在網頁上展示圖片集合一般有幾種方式:裁切為正方形、縱向瀑布流、橫向排版。當然除了這三者,還有諸如 slider、popover 等展示方式,這些展示方式不在本文討論之列。

    裁切為正方形的展示方式很常見,微博、朋友圈等都是這樣;Twitter 雖然有些許變化(不是所有的圖片都等大),但是也在裁切為正方形的陣營里。背后的原因有產品上的考慮,也有技術上的考慮,在此不多說。但是若從個人分享攝影作品的角度來說裁切為正方形算不上是好的方案,因為總有一部分像素會丟失,除非看客有意點擊展開,否則這部分內容就沒有機會被展示了。況且某些照片有著精妙的構圖,沒人希望自己的構圖被破壞。

    縱向瀑布流也是很常見的展示方式,主要應用在專職展示圖片的網站上,例如?PinterestUnsplash。這種展示方式的特點是列數一定,但是每列中的圖片高度不一,圖片能夠保持自己的寬高比。這是不錯的方案,特別是應用在無限滾動的網頁上,不過也有一個相當大的缺點:不適合圖文混排。圖片列數一定,每列高度不同,自然使得最底下一行參差不齊,不適合作為文章中插入圖片的方式。另外,這個方式有一個缺點:圖片順序不易保持,這是縱向瀑布流的通病,因此不論是內容塊還是圖片,縱向瀑布流都更適合順序不那么重要的場景。

    以上兩種方式各自有自己的應用場景,但不是本文要重點講的方式,因此其技術細節也就略過了(實際上也不難)。本文主要說圖片的橫向排版,效果如下(請在電腦端查看完整效果):

    圖片橫向排版最佳實踐 - CSS筆記

    特點顯而易見:圖片排版以行為單位,每行中可以有任意張任意寬高比的圖片,因此只需要處理一行中的圖片排版問題,那么無論再來多少行效果都令人滿意。應用這種排版方式的網站有?500px百度圖片等。

    實現細節

    HTML 與 CSS

    我們只關注一行圖片。為了使文章具有足夠的參考價值,我這里使用完整的 HTML 結構(這也是 VOID 使用的 HTML 結構):

    <div class="photos">
        <figure>
            <div><img src="..." /></div>
            <figcaption>...</figcaption>
        </figure>
        ...    <!--若干個類似的 figure 結構-->
    </div>

    使用 figure 標簽是為了使每張圖片都有完整的展示與圖題。照例,看 Demo:

    從 HTML 結構中可以看出,div.photos?是一行圖片的容器,每張圖標使用?figure?包裹,并且在?img?標簽外套上一層?div,這是為了模擬某些情況下的特殊需求(例如燈箱)。

    最外層的容器?div.photos?設定為 flex 布局,方向為橫向(flex-wrap: wrap 是為了在小屏幕下使用媒體查詢使圖片每張占一行,否則圖片就會小得看不清了……)。

    figure?標簽除了一個 margin 屬性用來控制間距和一個 position 屬性來指定定位方式之外沒有更多的內容。figure?下的?div?標簽顯式地指定了 height 為 0,并指定了 position 為 relative。這兩個標簽上的樣式并不多,但是圖片排版全看這兩個標簽的定位與尺寸,這部分放到后面。

    首先不妨假設?div?標簽與?figure?標簽都有了合適的大小,那么?img?很好處理,指定為絕對定位,并且使之長寬等于父元素的長寬即可。現在就來看看如何使?div?標簽與?figure?標簽合理布局。

    關鍵的部分

    核心知識點有兩個:padding-top?與?flex-grow

    padding-top 用來保持寬高比的 trick 想必很多人都知道。根據?MDN

    當內邊距(padding)是一個百分比的時候, 百分比是和包含塊(containing block)的寬度有關的...

    當 img 標簽的直接父元素(即 div)得到了合理的寬度,然后通過 padding-top 屬性來維持容器寬高比與圖片寬高比相同。這樣 div 本身 height 為 0,但是通過 padding-top 將它撐大,img 標簽相對它絕對定位,尺寸與之相同,就是合理的結果。

    最后只剩下一個關鍵的點:img 父元素即 div 的寬度如何確定。這個問題就是解決如何將一批長寬比不盡相同的圖片塞到一行里并且保證底部平齊。

    這里用到了 flex 布局的一個知識點:flex-grow。flex 布局中允許容器中的元素拉伸以填充整個容器的可用空間,其中每個子元素的拉伸比例即可通過 flex-grow 定義。例如:

    div:nth-of-type(1) {flex-grow: 1;}
    div:nth-of-type(2) {flex-grow: 3;}
    div:nth-of-type(3) {flex-grow: 1;}

    這段 CSS 使得第二個元素在拉伸時寬度總是別的元素的 3 倍。flex-grow 的值不重要,值之間的比值才重要。若能夠在拉伸時保持各元素的比例,那么事情就變得簡單了一些:只需要先把一行元素的高度都搞到相同,然后在橫向按比例拉伸,那么問題便解決了。

    圖片橫向排版最佳實踐 - CSS筆記

    先說實踐方案,首先定義一個“基準值”(上面的 Demo 中是 50),然后計算把每張圖片都縮到高度為基準值時圖片的寬度。設圖片原始寬度為?ww?與?hh,基準值?base=50base=50?,則圖片等比縮到 50px 時的寬度為:

    圖片橫向排版最佳實踐 - CSS筆記

    對每個容器如此處理,即可得到一行高度為 50px 且寬高比與圖片相同的容器,這時再指定 flex-grow 使容器填充一行內的可用空間。這一步很巧妙,每個容器的 flex-grow 只需要設置為:

    圖片橫向排版最佳實踐 - CSS筆記

    也就是 flex-grow 與?w'w′?恰好相同即可。這是由于前面所述的,“flex-grow 的值不重要,值之間的比值才重要”。此時就完成了整個排版,至于如何獲得圖片的原始尺寸等屬于細枝末節的問題,看 Demo 代碼即可。

    這篇文章也屬于 VOID 主題開發過程的技術筆記。寫主題好玩,寫完了繼續維護就不好玩了……希望到 2.0 版本的時候能夠到達比較穩定的狀態,然后就進入 LTS 階段吧。

    Normalize.css - 一種現代且支持HTML5的CSS重置替代品

    2020-5-15 14:16:42

    VUE模塊

    setTimeout定時執行一個函數 - Vue3

    2022-9-11 17:20:10

    ??
    Npcink上的部份代碼及教程來源于互聯網,僅供網友學習交流,若您喜歡本文可附上原文鏈接隨意轉載。
    無意侵害您的權益,請發送郵件至 1355471563#qq.com 或點擊右側 私信:Muze 反饋,我們將盡快處理。
    0 條回復 A文章作者 M管理員
      暫無討論,說說你的看法吧
    ?
    個人中心
    購物車
    優惠劵
    今日簽到
    有新私信 私信列表
    搜索
    主站蜘蛛池模板: 97av麻豆蜜桃一区二区| 国产AV一区二区精品凹凸| 国产av一区最新精品| 免费高清在线影片一区| 久久综合九九亚洲一区| 日本精品一区二区三区视频| 亚洲国产成人久久综合一区77 | 精品无码av一区二区三区| 亚洲乱码av中文一区二区| 一区二区三区四区免费视频| 国产波霸爆乳一区二区| 日韩精品一区二三区中文| 色综合视频一区二区三区44| 久久精品国产一区二区三| 国产精品无码一区二区三区在| 国产内射999视频一区| 成人区人妻精品一区二区不卡网站| 日韩毛片一区视频免费| 日韩一区二区视频| 精品国产AV无码一区二区三区| 亚洲av一综合av一区| 射精专区一区二区朝鲜| 国产精品小黄鸭一区二区三区 | 波多野结衣在线观看一区二区三区 | 一区二区三区精品视频| 欧洲无码一区二区三区在线观看| 亚洲一区二区三区久久久久| 狠狠综合久久AV一区二区三区| 色综合视频一区二区三区44| 性盈盈影院免费视频观看在线一区| 韩国女主播一区二区| 乱人伦一区二区三区| 精品国产一区AV天美传媒| 精品亚洲一区二区| 亚洲国产精品一区二区第一页| 国产vr一区二区在线观看| 久久久久女教师免费一区| 日本一区午夜爱爱| 免费av一区二区三区| 亚洲一区二区中文| 国产色欲AV一区二区三区|