使用flexbox的自適應照片布局


作者:Tim Vam Damme

讓我們來看看一種超輕量級的方法,它可以為一組任意大小的照片創建水平磚砌效果。將任何照片丟到上面,它們將邊對邊無縫對齊。

該解決方案不僅輕巧,而且非常簡單。我們將使用無序的圖片列表和僅僅17行CSS代碼,其中重點要領是flexbox和object-fit。

#為什么?

我有兩個業余愛好:用照片記錄生活,以及找出新舊CSS屬性有趣的組合方式。

幾周前,我參加了XOXO(注:XOXO是一個針對在線生活和工作的獨立藝術家的實驗性節日)並且拍攝了大量照片,然后我縮減為39張照片。為了擁有我自己的內容,我花了兩年的時間來組建一個簡單的照片博客,但始終無法實現我想要的布局:一個簡單的磚砌布局,其中的照片填充行的同時要尊重其寬高比例(在iOS、Google Photos、Flickr上可以考慮使用Photos.app)。

我進行了一些研究來查看是否有任何輕量級、非JavaScript的選項,但是不能找到適合我需要的任何內容。面對一些延誤的航班,我開始鼓搗一些代碼,限制自己盡可能簡化事情(因為這是我對樂趣的定義)。

#基本標記

由於我基本上是在創建圖片列表,因此我選擇了無序列表:

<ul>
  <li>
    <img>
  </li>
  <!-- ... -->
  <li>
    <img>
  </li>
</ul>

  

#所有像下冰雹一樣的彈性盒子

然后是一連串電燈泡時刻:

  • Flexbox非常適合通過根據單元格內容確定單元格的寬度來填充行。
  • 這意味着所有圖片(橫向或縱向)需要有統一高度。
  • 我可以使用object-fit:cover;確保圖像充滿了單元格。

從理論上講,這聽起來是一個靠譜的計划,這給了我90%滿意度的結果。

ul {
  display: flex;
  flex-wrap: wrap;
}

li {
  height: 40vh;
  flex-grow: 1;
}

img {
  max-height: 100%;
  min-width: 100%;
  object-fit: cover;
  vertical-align: bottom;
}

  

注意:40vh似乎是台式機瀏覽器的最佳初始方式,以合理的大小顯示兩整行照片,並在下方顯示更多內容。這還允許每行更多照片,從而大大提高了寬高比例。

#最后一行彈性縮放

我遇到的唯一問題是flexbox確實想要填滿所有行,並且它對最后一行照片的長寬比做了一些蠢事。這可能是這種布局中我最不喜歡的一部分,但是我必須在列表的末尾添加一個空的<li>元素。

<ul>
  <li>
    <img>
  </li>
  <!-- ... -->
  <li>
    <img>
  </li>
  <li></li>
</ul>

結合了這段CSS:

li:last-child {
  flex-grow: 10;
}

注意:此處使用“10”是沒有科學依據的。在我所有的測試匯總,這提供了最佳結果。(注:作者的意思是這是一個測試結果中較佳的數字,是一個根據結果不斷調整后的嘗試值。)

#Demo

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <meta name='viewport' content='width=device-width' />
    <title></title>
    <style>
        ul {
            display: flex;
            flex-wrap: wrap;
        }

        li {
            height: 40vh;
            flex-grow: 1;
            list-style: none;
        }

        li:last-child {

            flex-grow: 10;
        }

        img {
            max-height: 100%;
            min-width: 100%;
            object-fit: cover;
            vertical-align: bottom;
        }



        @media (max-aspect-ratio: 1/1) {
            li {
                height: 30vh;
            }
        }



        @media (max-height: 480px) {
            li {
                height: 80vh;
            }
        }



        @media (max-aspect-ratio: 1/1) and (max-width: 480px) {
            ul {
                flex-direction: row;
            }

            li {
                height: auto;
                width: 100%;
            }

            img {
                width: 100%;
                max-height: 75vh;
                min-width: 0;
            }
        }
    </style>
</head>

<body>

    <ul>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05466_kwlv0n.jpg"
                alt="A Toyota Previa covered in graffiti" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05621_zgtcco.jpg"
                alt="Interesting living room light through a window" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05513_gfbiwi.jpg"
                alt="Sara on a red bike" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05588_nb0dma.jpg"
                alt="XOXO venue in between talks" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05459_ziuomy.jpg"
                alt="Trees lit by green light during dusk" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05586_oj8jfo.jpg"
                alt="Portrait of Justin Pervorse" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05465_dtkwef.jpg"
                alt="Empty bike racks outside a hotel" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05626_ytsf3j.jpg"
                alt="Heavy rain on an intersection" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05449_l9kukz.jpg"
                alt="Payam Rajabi eating peanut chicken" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05544_aczrb9.jpg"
                alt="Portland skyline sunset" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814785/photostream-photos/DSC05447_mvffor.jpg"
                alt="Interior at Nong's" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814784/photostream-photos/DSC05501_yirmq8.jpg"
                alt="A kimchi hotdog on a plate" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814784/photostream-photos/DSC05624_f5b2ud.jpg"
                alt="Restaurant window with graffiti saying 'water'" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814784/photostream-photos/DSC05623_dcpfva.jpg"
                alt="Portrait of Jeremy Tanner" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814784/photostream-photos/DSC05515_d2gzut.jpg"
                alt="Jordan, Sarah and Sara on red bikes, waiting" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814784/photostream-photos/DSC05581_ceocwv.jpg"
                alt="Barista wearing a hoodie saying 'Coffee Should Be Dope.'" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814784/photostream-photos/DSC05517_ni2k0p.jpg"
                alt="Payam crossing the street on a bike" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814783/photostream-photos/DSC05620_qfwycq.jpg"
                alt="Lit trees reflected in a puddle" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814783/photostream-photos/DSC05462_b33uvp.jpg"
                alt="Moody chair in my hotel room" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814783/photostream-photos/DSC05489_mqzktl.jpg"
                alt="Tom and Jenn wearing sunglasses" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814783/photostream-photos/DSC05476_dlkjza.jpg"
                alt="Jordan and Sarah in front of a restaurant window" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814783/photostream-photos/DSC05497_abbd3c.jpg"
                alt="Sarah reading the Double Dragon drink menu" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05487_fcdv7t.jpg"
                alt="Beer brewing equipment" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05493_q6njbk.jpg"
                alt="2 cocktails in the making" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05446_xj60ff.jpg"
                alt="Beverage fridge at Nong's" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05559_hu49zx.jpg"
                alt="Wood structure reflections" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05482_dtrj02.jpg"
                alt="Colorful garden equipment in a shop window" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05565_dx5rp6.jpg"
                alt="Sarah in front of a wooden wall" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05613_o9af2z.jpg"
                alt="A neon banana" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05469_fdxdzx.jpg"
                alt="Matt Sacks smiling while we're waiting for food" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814782/photostream-photos/DSC05558_yq2tnz.jpg"
                alt="A fixed-gear bike under some bright lights" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05483_dyiuya.jpg"
                alt="Panic's PlayDate being held by a tester" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05468_xzbtcd.jpg"
                alt="Window reflection of me and Payam" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05457_nloycw.jpg"
                alt="Upside down shopping carts" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05522_mekpec.jpg"
                alt="Payam riding a bike with no hands" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05611_lbwtmk.jpg"
                alt="A kid's pillow left on the bench of a bus stop" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05572_xfvij7.jpg"
                alt="My reflection in the mirror" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05481_gnljae.jpg"
                alt="Jordan holding an iced coffee against his head to cool down" loading="lazy">
        </li>
        <li>
            <img src="https://res.cloudinary.com/css-tricks/image/upload/f_auto,q_auto/v1568814781/photostream-photos/DSC05480_zkw8sm.jpg"
                alt="Jordan and Sarah looking at the menu in a coffee shop" loading="lazy">
        </li>
        <!--  Adding an empty <li> here so the final photo doesn't stretch like crazy. Try removing it and see what happens!  -->
        <li></li>
    </ul>

</body>

</html>

  

#視口優化

在不同視口方向上進行操作時,需要牢記一些注意事項。

縱向排列

如果視口的高度大於寬度,則此方法會限制每行的照片數量,從而弄亂了它們的長寬比。 為了解決這個問題,您可以使用以下簡單的媒體查詢來降低照片行的高度:

@media (max-aspect-ratio: 1/1) {
  li {
    height: 30vh;
  }
}

  

短屏

為了幫助小型設備橫向排版美觀,需要增加照片的高度有助於使它們看起來盡可能大:

@media (max-height: 480px) {
  li {
    height: 80vh;
  }
}

  

較小屏幕+縱向排列

大多數手機的寬度不足以允許flexbox在不縮小照片尺寸的情況下正常工作,因此在這里我選擇不嘗試每行容納多張照片。 盡管如此,還是值得在此處設置最大高度,因此您至少可以提示列表中的下一張照片。

@media (max-aspect-ratio: 1/1) and (max-width: 480px) {
  ul {
    flex-direction: row;
  }

  li {
    height: auto;
    width: 100%;
  }

  img {
    width: 100%;
    max-height: 75vh;
    min-width: 0;
  }
}

  

#其它靈活調整方法!

這種方法並未完全尊重照片的長寬比(但很接近),偶爾會導致一些奇怪的結果,但是我絕對喜歡這一切的簡單性和靈活性。 想讓您的畫廊水平滾動而不是垂直滾動嗎? 進行一些調整可以使您做到這一點。 畫廊中有1000張照片還是只有一張? 一切看起來都不錯。 不清楚縱橫比嗎? Flexbox是您最好的朋友。 如果還沒有演示,請再看一下演示,讓我知道您的想法!

#意外收獲

根據這些照片的大小,這樣的頁面可能很快就會增長到幾兆字節。 在我正在處理的博客上,我添加了loading =“ lazy”來幫助解決此問題。 在圖像上具有該屬性的情況下,它僅在滾動時靠近照片時才加載照片。 目前,Chrome僅支持該功能,但您可以采用自己更受支持的技術。

 

原文鏈接:

https://css-tricks.com/adaptive-photo-layout-with-flexbox/

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM