[Web Design] 10分鐘了解Pinterest圖片佈局製作

簡介

Pinterest是全球知名的圖片靈感收集網站,其網頁圖片佈局有以下幾點特徵:
  • 每張圖片寬度相等,圖片高度依據原始圖片的長寬比作調整
  • 每一行的圖片上下緊緊相靠
  • 游標經過圖片區塊會有顏色變化
  • 網頁放大、縮小(Ctrl+滑鼠滾輪),圖片行數會跟著變化
我是自學網頁設計的初學者,掌握網頁程式基礎之後,便開始嘗試製作像Pinterest這樣的網站佈局,在努力爬了國外的討論區和文章數日之後,終於研究有成,在這邊分享給大家。本篇文章主要就是介紹如何做到以上幾點的圖片排版以及效果,並且藉由程式碼一步一步的說明,建議讀者具備JS、CSS、HTML的基礎知識會比較容易理解。



內文

相信剛開始嘗試製作像Pinterest圖片佈局的開發者,應該都有試過用float來做排版,雖然float在網頁放大、縮小或不同螢幕大小瀏覽時會自動排版,但其實不管結果如何都並不是我們所要的。本篇技術文主要就是兩個核心:
  • CSS的-webkit-column-count: 自動將HTML元素視為一個Div並且每一列會依據Column數來擺放Div個數,其最大特徵就是每一列元素會上下緊緊相靠。
  • JS的setInterval: 運用它來達到動態變化(放大、縮小或不同的螢幕大小)的效果。
那麼,我們就先來做第一步,運用JS來做讀取圖片,其排版設計圖如下:



配置一個大Div,每個大Div都包含著圖片和圖片說明文字,我們先來做個大Div配置一張圖片吧!
<html>

    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <script type="text/javascript">
    function ImgField(){
        for(var load=1;load<8;load++){ //假設配置7個大Div,讀取7張圖片          

            //***讀取圖片和配置***
            var image = new Image();
            image.src="Image/Img"+load+".jpg";
            image.width="320"; //每張圖片寬度統一為320px,高度會自動依長寬比例調整
            image.style.margin ="10 10 5 10";

            var BidDiv = document.createElement('div');
            BidDiv.width="340" //大Div寬度比圖片多20px給margin用
            BidDiv.appendChild(image);
                    document.getElementById("ShowPanel").appendChild(BidDiv);
        }
    }
    </script>

    </head>

    <body>

    <div id="ShowPanel">

    <script type="text/javascript">
    ImgField()
    </script>

    </div>

    </body>

</html>
結果如下圖:



可以看到現在圖片全都靠左排成一行,接著我們再來加上圖片的說明,像是上傳日期作者下載次數,把這些Info一樣放到大Div裡頭,我們可以把ImgField函式改成如下:
<html>

    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <script type="text/javascript">
    function ImgField(){
        for(var load=1;load<8;load++){ //配置7個大Div,讀取圖片數量7張          

            //***讀取圖片和配置***
            var image = new Image();
            image.src="Image/Img"+load+".jpg";
            image.width="320"; //每張圖片寬度統一為320px,高度會自動依長寬比例調整
            image.style.margin ="10 10 5 10";

            var BidDiv = document.createElement('div');
            BidDiv.width="340" //大Div寬度比圖片多20px給margin用
            for(var col = 0; col < 4; col++){
                        switch(col){
                        case 0: 
                            BidDiv.appendChild(image);
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 1:
                            BidDiv.appendChild(document.createTextNode("上傳日期:2017/02/01"));
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 2:
                            BidDiv.appendChild(document.createTextNode("作者:Pixabay"));
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 3:
                            BidDiv.appendChild(document.createTextNode("下載次數:100,000"));
                            break;
                        }
                    }
            document.getElementById("ShowPanel").appendChild(BidDiv);
        }
    }
    </script>

    </head>

    <body>

    <div id="ShowPanel">

    <script type="text/javascript">
    ImgField()
    </script>

    </div>

    </body>

</html>
 
結果如下圖:



接著要來將我們的圖片排列好,並且每一行的圖片上下緊緊相靠,所用的方法是CSS的-webkit-column-count,這裡要特別注意,-webkit-column-count只支援Chrome和Safari,因此其他的瀏覽器需用另一個代碼來支援(程式碼會附上)。再來就是為了要達到動態排版(網頁縮小、放大或不同螢幕大小瀏覽),我們需用JS的setInterval設置一個排版變化週期,做法如下:
<html>

    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">

    <script type="text/javascript">
    function ImgField(){
        for(var load=1;load<8;load++){ //配置7個大Div,讀取圖片數量7張          

            //***讀取圖片和配置***
            var image = new Image();
            image.src="Image/Img"+load+".jpg";
            image.width="320"; //每張圖片寬度統一為320px,高度會自動依長寬比例調整
            image.style.margin ="10 10 5 10";

            var BidDiv = document.createElement('div');
            BidDiv.width="340" //大Div寬度比圖片多20px給margin用
            for(var col = 0; col < 4; col++){
                        switch(col){
                        case 0: 
                            BidDiv.appendChild(image);
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 1:
                            BidDiv.appendChild(document.createTextNode("上傳日期:2017/02/01"));
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 2:
                            BidDiv.appendChild(document.createTextNode("作者:Pixabay"));
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 3:
                            BidDiv.appendChild(document.createTextNode("下載次數:100,000"));
                            break;
                        }
                    }
            document.getElementById("ShowPanel").appendChild(BidDiv);
        }
    }

    //***網頁動態排版***
    var zoom = 0;
    setInterval(function() {
    var BigDivNumber = window.innerWidth / 340; //計算一列有幾個BigDivNumber
    var newZoom = (window.innerWidth-BigDivNumber*20) / 340; //扣掉每個BigDivNumber之間的間距(margin),以及最左右兩側的間隔。
    if (newZoom == zoom) return;
    zoom = newZoom;
    document.getElementById("ShowPanel").style.WebkitColumnCount = Math.floor(zoom); /* Code for old Chrome and Safari*/
    document.getElementById("ShowPanel").style.MozColumnCount = Math.floor(zoom); /* Code for Firefox*/
    document.getElementById("ShowPanel").style.columnCount = Math.floor(zoom);
    }, 200);

    </script>

    </head>

    <body>

    <div id="ShowPanel">

    <script type="text/javascript">
    ImgField()
    </script>

    </div>

    </body>

</html>
 
結果如下圖:



這時不管網頁視窗放大、縮小(Ctrl+滑鼠滾輪)或用不同螢幕大小瀏覽都能自動的排整齊,但是這裡有一個問題,如上圖紅色圈起的地方,圖片的說明會跑別人的圖片上方去了,也就是說BigDiv被切分了,這是以前在使用
CSS的-webkit-column-count時常常令人頭痛的缺點,但現在CSS為了解決這樣的問題,提供了以下的代碼給開發者:
-webkit-column-break-inside: avoid; /Code for Chrome and Safari/
page-break-inside: avoid; /Code for FireFox/
break-inside: avoid; /Code for IE/
只要新增一個CSS檔,將以上的代碼指定給ID為ShowPanel的超大Div(含有全部大Div的超大Div)就可以解決大Div被切分的問題了,另外我們也將大Div游標經過的顏色變化以及圖片說明文字置中一併完成吧!
<html>

    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <link rel="stylesheet" type="text/css" href="stylesheet.css">

    <script type="text/javascript">
    function ImgField(){
        for(var load=1;load<8;load++){ //配置7個大Div,讀取圖片數量7張          

            //***讀取圖片和配置***
            var image = new Image();
            image.src="Image/Img"+load+".jpg";
            image.width="320"; //每張圖片寬度統一為320px,高度會自動依長寬比例調整
            image.style.margin ="10 10 5 10";

            var BidDiv = document.createElement('div');
            BidDiv.width="340" //大Div寬度比圖片多20px給margin用
            BidDiv.onmouseover = function(){
                    this.style.backgroundColor = "rgb(153,255,255)";
                    };
            BidDiv.onmouseout = function(){
                        this.style.backgroundColor = "rgb(255,255,255)";
                    };
            for(var col = 0; col < 4; col++){
                        switch(col){
                        case 0: 
                            BidDiv.appendChild(image);
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 1:
                            BidDiv.appendChild(document.createTextNode("上傳日期:2017/02/01"));
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 2:
                            BidDiv.appendChild(document.createTextNode("作者:Pixabay"));
                            BidDiv.appendChild(document.createElement("br"));
                            break;
                        case 3:
                            BidDiv.appendChild(document.createTextNode("下載次數:100,000"));
                            break;
                        }
                    }
            document.getElementById("ShowPanel").appendChild(BidDiv);
        }
    }

    //***網頁動態排版***
    var zoom = 0;
    setInterval(function() {
    var BigDivNumber = window.innerWidth / 340; //計算一列有幾個BigDivNumber
    var newZoom = (window.innerWidth-BigDivNumber*20) / 340; //扣掉每個BigDivNumber之間的間距(margin),以及最左右兩側的間隔。
    if (newZoom == zoom) return;
    zoom = newZoom;
    document.getElementById("ShowPanel").style.WebkitColumnCount = Math.floor(zoom); /* Code for old Chrome and Safari*/
    document.getElementById("ShowPanel").style.MozColumnCount = Math.floor(zoom); /* Code for Firefox*/
    document.getElementById("ShowPanel").style.columnCount = Math.floor(zoom);
    }, 200);

    </script>

    </head>

    <body>

    <center>
    <div id="ShowPanel">

    <script type="text/javascript">
    ImgField()
    </script>

    </div>
    </center>

    </body>

</html>
 
結果如下圖:



以上是我模擬Pinterest圖片排版的程式碼,其他的美工調整的部分,還需各位自行配置,若有任何問題或討論可以在下方留言或寄信(Gmail)給我哦~感謝各位耐心收看!

參考

 

待補...

 

留言