• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局

在本教程中,我们将拍摄一堆照片并将它们转换为可过滤的缩略图布局。我们将结合所有最新的 css 好东西(CSS Grid、flexbox 和 CSS 变量)以及一些自定义 javascript 来构建一个惊人的演示!

这是我们将要创建的内容:

一定要在大屏幕(>900px) 上查看演示,因为那时魔法就会发生!事不宜迟,来杯咖啡,让我们开始吧!

1.从页面标记开始

我们将从.container包含.toolbar 元素和照片列表的 a 开始:

<div class="container">
  <div class="toolbar">...</div>
  <ol class="image-list grid-view">...</ol>
</div>


工具栏布局将如下所示:

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第1张

在其中我们将放置两个元素:

  • 允许我们搜索特定照片的搜索框

  • 包含确定缩略图布局的三个选项的列表。默认情况下,照片显示在网格视图中,但我们可以通过单击右上角的图标切换到列表视图。此外,每次我们在网格视图中时,我们都可以选择更改每行显示的照片数量。为此,我们将使用范围滑块。 

这是所有这些的相关标记:

<div class="search-wrapper">
  <input type="search" placeholder="Search for photos">  
  <div class="counter">
    Total photos: <span>12</span>
  </div>
</div>
<ul class="view-options">
  <li class="zoom">
    <input type="range" min="180" max="380" value="280">
  </li>
  <li class="show-grid active">
    <button disabled>
      <img src="IMG_SRC" alt="grid view">  
    </button>
  </li>
  <li class="show-list">
    <button>
      <img src="IMG_SRC" alt="list view">  
    </button>
  </li>
</ul>

在图像列表中,我们将放置 12张Unsplash照片。每张照片都附有其描述以及所有者的姓名。以下是一些基本样式的外观(我们很快就会谈到):

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第2张

这是单张照片的标记:

<li>
  <figure>
    <img src="IMG_SRC" alt="">
    <figcaption>
      <p>...</p>
      <p>...</p>
    </figcaption>
  </figure>
</li>  

<!-- 11 list items here -->


请务必注意,图像列表将始终包含image-list该类。此外,它还将接收grid-view或 list-view类,如下所示: <ol class="image-list grid-view">...</ol>

它的第二类将取决于用户选择的布局视图。在接下来的部分中会对此进行更多介绍。 

2. 定义一些基本样式

我们首先设置了一些 CSS 变量和一些重置样式:

:root {
  --black: #1a1a1a;
  --white: #fff;
  --gray: #ccc;
  --darkgreen: #18846C;
  --lightbrown: antiquewhite;
  --darkblack: rgba(0,0,0,0.8);
  --minRangeValue: 280px;
}

* {
  margin: 0;
  padding: 0;
  outline: none;
  border: none;
}

button {
  cursor: pointer;
  background: none;
}

img {
  display: block;
  max-width: 100%;
  height: auto;
}

ol,
ul {
  list-style: none;
}

a {
  color: inherit;
}

最重要的是,注意minRangeValue变量的值。它的值 (280px) 与范围滑块的默认值相匹配。 

记住我们滑块的标记:  <input type="range" min="180" max="380" value="280">稍后我们将使用该值来设置照片的最小宽度。

注意:为简单起见,我不会  在教程中介绍所有CSS 规则。您可以通过单击  演示项目的CSS选项卡来检查其余部分。

样式化工具栏

下一步,我们将为工具栏设置样式。以下是有关此元素的要点:

  • 我们使用 flexbox 来布局它的内容。

  • 每次用户选择布局(网格或列表)时,相应的按钮都会标记为活动并接收深绿色边框。此外,我们禁用它。

  • 范围滑块仅在网格视图处于活动状态以及最小宽度为 901 像素的屏幕上出现。

对应样式的重要部分如下图所示:

/*CUSTOM VARIABLES HERE*/

.toolbar {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.view-options {
  display: flex;
  align-items: center;
}

.view-options li:not(:last-child) {
  margin-right: 1.2rem;
}

.view-options button {
  padding: 2px;
  border: 3px solid transparent;
}

.view-options .active button {
  border-color: var(--darkgreen);
}

@media screen and (max-width: 900px) {
  .toolbar input[type="range"] {
    display: none;
  }
}


样式化图像列表

如前所述,图像列表布局将取决于用户选择的布局。无论如何,我们将利用 CSS Grid 来构建这个布局。

在此之前,让我们将一些通用样式应用于图像列表:

/*CUSTOM VARIABLES HERE*/

.image-list {
  margin: 3rem 0;
}

.image-list li {
  background: var(--lightbrown);
  background: var(--darkblack);
}

.image-list img {
  background: #e6e6e6;
}

.image-list p:first-child {
  font-weight: bold;
  font-size: 1.15rem;
}

.image-list p:last-child {
  margin-top: 0.5rem;
}

在网格视图中,列表项将被分成重复的列/单元格,它们之间有排水沟:

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第3张

每行显示的项目数取决于屏幕大小。最初,每个项目的最小宽度为 280 像素,最大宽度与其容器宽度相匹配。但正如我们稍后会看到的,我们将添加一点交互性,并让用户可以选择修改最小宽度。出于这个原因,我们不会对其值进行硬编码,而是将其存储在minRangeValue变量中。

minmax() 通过将CSS 函数与 CSS Grid相结合,我们能够生成这种真正响应式的布局 。以下是上述要求在样式方面的翻译方式:

:root {
 --minRangeValue: 280px;
}

.grid-view {
 display: grid;
 grid-gap: 2rem;
 grid-template-columns: repeat(auto-fit, minmax(var(--minRangeValue), 1fr));
}


在列表视图中,列表项将具有默认的块级行为:

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第4张

在它们内部,图像将具有 150 像素的固定宽度,并且其描述将覆盖剩余的可用空间 (1fr)。另外,这两个元素将垂直居中,它们之间有一个排水沟。

相关样式:

.list-view li + li {
  margin-top: 1.5rem;
}

.list-view figure {
  display: grid;
  grid-gap: 1.5rem;
  grid-template-columns: 150px 1fr;
  align-items: center;
}

要了解有关如何minmax()使用 CSS 网格布局的更多信息,这里有一个初学者教程:

  • 如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第5张如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第5张


3. 在列表视图和网格视图之间切换

每次用户单击所需的内容呈现模式时,我们会做两件事:

  • 为活动按钮添加深绿色边框。

  • 检查用户选择了哪种类型的视图。

如果用户选择网格视图,我们会显示范围滑块并确保图像列表包含grid-view类而不是list-view类。

另一方面,如果用户选择列表视图,我们隐藏范围滑块并确保图像列表包含list-view类而不是grid-view类。

所需的 JavaScript 代码:

const imageList = document.queryselector(".image-list");
const btns = document.querySelectorAll(".view-options button");
const imageListItems = document.querySelectorAll(".image-list li");
const active = "active";
const listView = "list-view";
const gridView = "grid-view";
const dNone = "d-none";

for (const btn of btns) {
  btn.addeventListener("click", function() {
    const parent = this.parentElement;
    document.querySelector(".view-options .active").classList.remove(active);
    parent.classList.add(active);
    this.disabled = true;
    document.querySelector('.view-options [class^="show-"]:not(.active) button').disabled = false;

    if (parent.classList.contains("show-list")) {
      parent.previousElementSibling.previousElementSibling.classList.add(dNone);
      imageList.classList.remove(gridView);
      imageList.classList.add(listView);
    } else {
      parent.previousElementSibling.classList.remove(dNone);
      imageList.classList.remove(listView);
      imageList.classList.add(gridView);
    }
  });
}


4. 通过 javaScript 更新 CSS 变量 

我们已经讨论过范围滑块的初始值为 280px 并且与 minRangeValue变量的值相匹配。另外,它的最小值是 180px,而最大值是 380px。

我们需要跟踪滑块值的变化并minRangeValue相应地更新变量。这将使我们的网格视图布局灵活,因为每行不包含固定数量的列。

实现这一目的的 JavaScript 代码利用了该input事件:

const rangeInput = document.querySelector('input[type = "range"]');

rangeInput.addEventListener("input", function() {
  document.documentElement.style.setProperty("--minRangeValue", `${this.value}px`);
});


要了解此代码,请打开浏览器工具并更新滑块值。你会注意到html元素接收到一个内联样式,它覆盖了通过 CSS 设置的属性值:


如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第7张   

5. 构建搜索功能

目前我们只有 12 张图像,但是想象一个我们有几十张图像的场景。在这种情况下,如果用户能够搜索特定的照片,那就太好了。

所以,让我们继续构建一个自定义搜索组件,如下所示:

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第8张   

请注意,它仅适用于图像描述:

如何使用CSS Grid、Flexbox和JavaScript构建可过滤的缩略图布局  第9张    

作为第一步,我们执行以下操作:

  • 遍历所有照片。 

  • 对于我们找到的每张照片,我们用两个属性初始化一个对象字面量。 

  • 第一个属性是id具有每个对象唯一的增量编号。第二个属性是text 存储目标照片描述的属性。 

  • 将所有对象存储在一个数组中。

实现此功能的 JavaScript 代码:

const captions = document.querySelectorAll(".image-list figcaption p:first-child");
const myArray = [];
let counter = 1;

for (const caption of captions) {
  myArray.push({
    id: counter++,
    text: caption.textContent
  });
}

需要注意的一点是,我们的计数器从 1 开始,而不是从 0 开始。我们这样做是故意的,因为这将有助于我们稍后轻松定位所需的元素。

用户输入

接下来,每次用户在搜索输入中键入内容时,我们都会执行以下操作:

  1. 隐藏所有照片。

  2. 抓住搜索查询。

  3. 检查是否存在在其 text属性值中包含搜索查询的数组元素(对象)。

  4. 显示满足上述要求的元素。

  5. 在屏幕上打印他们的号码。如果没有任何元素打印 0。

所需的 JavaScript 代码:

const searchInput = document.querySelector('input[type="search"]');
const imageListItems = document.querySelectorAll(".image-list li");
const photosCounter = document.querySelector(".toolbar .counter span");
const dNone = "d-none";

searchInput.addEventListener("keyup", keyupHandler);

function keyupHandler() {
  // 1
  for (const item of imageListItems) {
    item.classList.add(dNone);
  } 
  // 2
  const text = this.value;
  // 3
  const filteredArray = myArray.filter(el => el.text.includes(text));
  // 4
  if (filteredArray.length > 0) {
    for (const el of filteredArray) {
      document.querySelector(`.image-list li:nth-child(${el.id})`).classList.remove(dNone);
    }
  } 
  // 5
  photosCounter.textContent = filteredArray.length;
}

这里使用的 CSS 类:

.d-none {
  display: none;
}


注意: 我们可以使用不同的方法来阻止回调函数在用户每次释放键(keyup事件)时运行。虽然超出了本教程的范围,但一个有效的解决方案可能是使用 Lodash 的 debounce 函数

提示:如果要进行不区分大小写的搜索,一种简单的解决方案是将 filteredArray上述步骤 ( ) 中的常量替换为// 3

const filteredArray = myArray.filter(el => el.text.toLowerCase().includes(text.toLowerCase()));

结论

就是这样的人!这确实是一个漫长的旅程,但我希望你学到了一些新东西,并且你喜欢我们在这里构建的演示。玩弄它,如果您有任何问题,请告诉我。

文章目录
  • 1.从页面标记开始
  • 2. 定义一些基本样式
    • 样式化工具栏
    • 样式化图像列表
  • 3. 在列表视图和网格视图之间切换
  • 4. 通过 javaScript 更新 CSS 变量
  • 5. 构建搜索功能
    • 用户输入
  • 结论