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-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布局其内容。
- 每次用户选择布局(网格或列表)时,相应的按钮都会标记为活动状态并接收深绿色边框。 另外,我们禁用它。
- 仅当网格视图处于活动状态且最小宽度为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开始。我们这样做是有意的,因为这将有助于我们稍后轻松地将所需元素作为目标。
用户输入
接下来,每次用户在搜索输入中键入内容时,我们都会执行以下操作:
- 隐藏所有照片。
- 抓住搜索查询。
- 检查是否有数组元素(对象)的
text属性值中包含搜索查询。 - 显示满足以上要求的元素。
- 在屏幕上打印他们的号码。 如果没有任何元素,则打印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()));
结论
就是这样! 这确实是一段漫长的旅程,但是我希望您能学到一些新东西,并且您喜欢我们在此处构建的演示。 试一下,如果您有任何疑问,请告诉我。
一如既往,感谢您的阅读!
css flexbox模型
本文详细介绍如何使用CSS Grid和Flexbox结合JavaScript构建一个可过滤的缩略图布局,包括不同视图模式的切换、响应式设计及自定义搜索功能。
986

被折叠的 条评论
为什么被折叠?



