CSS 例項系列 - 05 - Photo Album 瀑布流相簿

jsliang發表於2023-03-13

Hello 小夥伴們早上、中午、下午、晚上和深夜好,這裡是 jsliang~

今兒要實現的是:Photo Album 瀑布流相簿

05-01.gif

本期將和小夥伴們探討:

  • √ 透過簡單幾步,帶大家用 HTML + CSS + JavaScript 速通瀑布流畫冊

本例項的程式碼地址:

本例項系列整體效果可見:https://liangjunrong.github.io/

當然,jsliang 還貼心準備了影片教程,手把手帶你逐步完成:

一 前言

本 CSS 系列文章:

  1. 主推學以致用。結合面試題和工作例項,讓小夥伴們深入體驗 61 個工作常見的 CSS 屬性和各種 CSS 知識。
  2. 主推純 CSS。儘可能使用 HTML + CSS 完成學習目的,但仍然有 “一小部分” 功能需要用到 JavaScript 知識,適合新人學習 + 大佬複習

如果文章在一些細節上沒寫清楚或者誤導讀者,歡迎評論/吐槽/批判,你的關注和點贊是我持續更新的動力,謝謝大家 ❤

05-02.png

二 本期知識點

2.1 @media

關於 @media,小夥伴們在 MDN 上可以看到介紹:

  • @media 規則可用於基於一個或多個媒體查詢的結果來應用樣式表的一部分。

什麼意思呢?大概就是對於一個元素,你可以指定它在不同裝置下的展示。

例如:

<h1>jsliang 的例項系列</h1>
h1 {
  font-size: 36px;
  color: deepskyblue;
}

@media screen and (max-width: 1000px) {
  h1 {
    font-size: 24px;
  }
}

05-03.png

這 2 段程式碼,即表示對於 <h1> 元素,在 1000+ px 上,表現為 36px 的字型大小,而在 1000 px 下,則為 24px 大小。

透過這樣 @media,小夥伴們也可以聯想下,本次需要實現的功能,在不同解析度下如何嘗試實踐出來。

2.2 filter

關於 filter,小夥伴們在 MDN 上可以看到介紹:

  • CSS 屬性 filter 將模糊或顏色偏移等圖形效果應用於元素。濾鏡通常用於調整影像、背景和邊框的渲染。

我們很容易就聯想到一些特殊日子,很多網站的置灰效果,有些正是用上了 filter 屬性。

.gray {
  filter: grayscale(100%);
  filter: gray;
}

05-04.png

當然,本文也會透過 filter 來完成圖片遮罩效果。

三 實現步驟

OK,話不多說,我們開始完成本例項,讓我們開始吧!

3.1 實現一個畫框

05-05.png

對於上面這種效果,在小夥伴們看來,想必是已經熟能生巧:

index.html
<div class="photo-container">
  <div class="show">正常顯示</div>
</div>

在這裡,.photo-container 是紅色的,而 .show 是內部的藍色框。

index.css
/* 重置樣式 Start */
body, html { margin: 0; padding: 0; }
body {
  display: flex;
  justify-content: center;
  color: #fff;
  font-size: 24px;
}
/* 重置樣式 End */

.photo-container {
  width: 400px;
  height: 400px;
  background: red;
  padding: 10px;
  position: relative;
}
.show {
  width: 100%;
  height: 100%;
  background: deepskyblue;
}

3.2 實現畫框 hover 出彈窗

05-06.png

在滑鼠 hover 的時候,能出來一個彈窗,遮擋住 .show 這個元素,並且左下角有一個 jsliang 的小文字,想必也很簡單:

index.html
<div class="photo-container">
  <div class="show">正常顯示</div>
+  <div class="hover-show">
+    hover 顯示
+    <div class="author">
+      <span>jsliang</span>
+    </div>
+  </div>
</div>

CSS 稍微補充一下:

index.css
/* 大框 hover 後顯示效果 */
.photo-container:hover .hover-show {
  display: block;
}
.hover-show {
  display: none;
  width: calc(100% - 20px);
  height: calc(100% - 20px);
  background: orange;
  position: absolute;
  top: 10px;
  left: 10px;
}
/* 左下角作者 */
.author {
  position: absolute;
  left: 0;
  bottom: 0;
  color: deepskyblue;
  font-size: 18px;
  background: papayawhip;
  padding: 10px;
  cursor: pointer;
}

3.3 實現畫框 hover 的彈窗再 hover 出作者詳情

05-07.png

再下來就是在滑鼠 hover 到作者的時候,能展開上邊的「作者 hover 顯示」彈窗,這也不難:

index.html
<div class="photo-container">
 <div class="show">正常顯示</div>
 <div class="hover-show">
   hover 顯示
   <div class="author">
     <span>jsliang</span>
+     <div class="author-hover-show">
+       作者 hover 顯示
+     </div>
   </div>
 </div>
</div>

同樣也是補充一點 CSS:

index.css
/* 作者 hover 出作者詳情 */
.author:hover .author-hover-show {
  display: block;
}
.author-hover-show {
  display: none;

  position: absolute;
  width: 200px;
  height: 100px;
  background: blue;
  bottom: 40px;
  left: 0px;
}

3.4 Copy 彈窗,透過 JS 實現瀑布流

下面壓力來到 JS 這邊,我們如何「批次」製造響應式瀑布流呢?

05-08.gif

這裡我們們挑了「瀑布流的 N 種實現方式」之一來完成:

index.html
<body>
- <!-- 刪除了很多內容 -->
+  <div class="photo-album"></div>

+  <script src="./index.js"></script>
</body>
index.js
window.onload = () => {
  // 假裝後臺請求介面給到的圖片資料
  const imgList = Array.from(Array(100), (item, index) => index + 1);
  const renderDOM = document.querySelector('.photo-album');
  let prevMode = 1;

  // func: 滾動查詢元素並將 String 累計起來,最終渲染到 renderDOM 節點上
  const reduceDOM = (limit) => {
    // 生成 limit 條字串
    const htmlString = Array.from(Array(limit), () => '<div class="photo-list">');
    // 遍歷並將 <img/> 新增到每一列上
    imgList.forEach((item, index) => {
      const surplus = index % limit;
      if (surplus < limit) {
        htmlString[surplus] += `
<div class="photo-container">
  <div class="show">正常顯示 ${item}</div>
  <div class="hover-show">
    hover 顯示
    <div class="author">
      <span>jsliang</span>
      <div class="author-hover-show">
        作者 hover 顯示
      </div>
    </div>
  </div>
</div>
`;
      }
    });
    // 結尾設定 String
    for (let i = 0; i < limit; i++) {
      htmlString[i] += '</div>';
    }
    // 渲染到 HTML 上。記得處理下陣列,要不然會產生逗號
    renderDOM.innerHTML = htmlString.join('');
  };

  // func: 重排節點
  const resize = () => {
    const width = window.innerWidth;
    // 超過 1000px 顯示 3 列,否則顯示 2 列
    if (width >= 1000 && prevMode !== 3) {
      prevMode = 3;
      reduceDOM(prevMode);
    } else if (width < 1000 && prevMode !== 2) {
      prevMode = 2;
      reduceDOM(prevMode);
    }
  };
  
  // 1、每次進來先執行一遍
  resize();

  // 2、每次拖拽,判斷是否需要重新渲染
  window.onresize = () => {
    resize();
  };
};

接著我們稍微補充一點 CSS 即可:

index.css
/* 相簿主容器 */
.photo-album {
  display: flex;
  width: 100%;
}
/* 相簿列表 */
.photo-list {
  /* 防擠壓 */
  flex-shrink: 0;
  width: calc(33% - 20px);
  margin-left: 20px;
}
/* 自適應 */
@media screen and (max-width: 1000px) {
  .photo-list {
    width: calc(50% - 30px);
  }
}

這樣,我們就完成了瀑布流相簿的雛形。

3.5 補充「億」點點細節

jsliang 我想學真正的技術,別拿小框框敷衍我!

好的好的,麻瓜讓道,魔法來了~

05-01.gif

其實就是照著「Pexels」補充 CSS 細節:

05-09.png

OK,這樣我們本次的 CSS 之旅就完成啦!

本例項的程式碼地址:

本例項系列整體效果可見:https://liangjunrong.github.io/

當然,jsliang 還貼心準備了影片教程,手把手帶你逐步完成:

四 參考文獻


不折騰的前端,和鹹魚有什麼區別!

覺得文章不錯的小夥伴歡迎點贊/點 Star。

如果小夥伴需要聯絡 jsliang

個人聯絡方式存放在 Github 首頁,歡迎一起折騰~

爭取打造自己成為一個充滿探索欲,喜歡折騰,樂於擴充套件自己知識面的終身學習斜槓程式設計師。

jsliang 的文件庫由 梁峻榮 採用 知識共享 署名-非商業性使用-相同方式共享 4.0 國際 許可協議 進行許可。<br/>基於 https://github.com/LiangJunrong/document-library 上的作品創作。<br/>本許可協議授權之外的使用許可權可以從 https://creativecommons.org/licenses/by-nc-sa/2.5/cn/ 處獲得。

相關文章