css flexbox模型_如何使用CSS网格,Flexbox和JavaScript构建可过滤的缩略图布局

本文详细介绍如何使用CSS Grid和Flexbox结合JavaScript构建一个可过滤的缩略图布局,包括不同视图模式的切换、响应式设计及自定义搜索功能。

css flexbox模型

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

这是我们将要创建的:

请务必在大屏幕 (> 900像素) 查看演示,因为这时魔术就发生了! 事不宜迟,拿起一杯咖啡,让我们开始吧!

1.从页面标记开始

我们将从一个.container开始,该.container包含.toolbar元素和一张照片列表:

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

工具栏布局如下所示:

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

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

这是所有相关的标记:

<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>

在图像列表内,我们将放置十二张Unsplash照片。 每张照片都带有其描述以及所有者名称。 这是一些基本样式的外观(稍后将介绍):

这是单张照片的标记:

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

<!-- 11 list items here -->

重要的是要注意,图像列表将始终包含image-list类。 此外,它还将接收grid-viewlist-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布局其内容。
  • 每次用户选择布局(网格或列表)时,相应的按钮都会标记为活动状态并接收深绿色边框。 另外,我们禁用它。
  • 仅当网格视图处于活动状态且最小宽度为901px的屏幕时,范围滑块才会出现。

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

/*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;
}

在网格视图中,列表项将分为重复的列/单元格,它们之间有装订线:

网格视图

每行显示的项目数取决于屏幕尺寸。 最初,每个项目的最小宽度为280px,最大宽度与其容器宽度相匹配。 但是,正如我们稍后将看到的,我们将添加一些交互性,并为用户提供修改最小宽度的选项。 因此,我们不会对其值进行硬编码,而是将其存储在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));
}

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

在其中,图片的固定宽度为150px,其说明将覆盖其余可用空间(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;
}

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变量的值匹配。 另外,最小值为180像素,最大值为380像素。

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

将完成技巧JavaScript代码将利用input事件:

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

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

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

5.建立搜索功能

当前,我们只有十二个图像,但是要一个场景,其中有几十个图像。 在这种情况下,如果用户能够搜索特定照片,那就太好了。

因此,让我们继续构建这样的自定义搜索组件:

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

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

  • 遍历所有照片。
  • 对于找到的每张照片,我们使用两个属性初始化对象文字。
  • 第一个属性是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的去抖动功能。

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

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

结论

就是这样! 这确实是一段漫长的旅程,但是我希望您能学到一些新东西,并且您喜欢我们在此处构建的演示。 试一下,如果您有任何疑问,请告诉我。

一如既往,感谢您的阅读!

翻译自: https://webdesign.tutsplus.com/tutorials/how-to-build-a-filterable-thumbnail-layout-with-css-grid-flexbox-and-javascript--cms-33242

css flexbox模型

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值