Html手写一个各大商品网站的响应式瀑布流
首先我们先看一下各大电商网站的商品布局
淘宝的瀑布流里面会夹带着一个轮播图,和一些其他布局的东西。
京东的瀑布流也差不多,不过我们可以看到京东把图片的高度都设定成了固定大小,每个item的大小都一样,感觉少了一点什么。没有淘宝的那种交错的感觉。
拼多多的瀑布流与京东的比较相似,不过相对看起来更简单,它里面没有包含一些其他的内嵌内容。
简单实现一个瀑布流
我这里采用的是column-count ,该属性可以用来实现基于列的布局,将一个容器分成多列,每列的宽度相等。在制作瀑布流时,我们可以将商品容器设置为多列布局,让商品自动填充到每一列中,从而实现瀑布流的效果。
具体实现步骤如下:
- 将商品容器设置为多列布局,使用
column-count属性设置列数,例如:
.container {
column-count: 4;
}
- 设置商品容器的列间距,使用
column-gap属性设置列间距,例如:
.container {
column-gap: 20px;
}
- 设置商品容器的防止分割属性,使用
break-inside属性设置防止分割,例如:
.item {
break-inside: avoid;
}
这样,商品容器就会自动填充到每一列中,从而实现瀑布流的效果。需要注意的是,商品容器的高度应该是不固定的,否则可能会导致商品无法自动填充到每一列中。
实现响应式布局
利用这种方法实现的瀑布流实现响应式布局就非常简单了。
我们只需要改变 column-count的值就行了。
在768-900 为3列,在768一下为2列。
/* 媒体查询 */
@media screen and (max-width: 900px) {
.container {
column-count: 3; /* 列数为 3 */
}
}
@media screen and (max-width: 768px) {
.container {
column-count: 2; /* 列数为 2 */
}
}
自己实现一个这样的效果
先看一下我们的效果图吧! 可以看到外面这里第一个也是跟淘宝一样有一个轮播图的效果,并且每个商品的item的高度不是固定的。
先看看我的html代码吧!
惊不惊喜,意不意外,我的html里只有一个container容器,那么我的页面是怎么实现的呢?没错,为了节省代码,我采用了jsfor循环渲染挂载实现页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="container">
</div>
<script src="./demo.js"></script>
</body>
</html>
先把我的完整的css代码给你们一下
这个css没什么难点,难点和要点就是前面提到的瀑布流布局和响应式布局的实现。
/* 设置 body 的背景颜色 */
body {
background-color: #f00;
}
/* 商品瀑布流容器 */
.container {
background-color: transparent; /* 背景透明 */
margin: 30px; /* 外边距 */
column-count: 4; /* 列数 */
column-gap: 20px; /* 列间距 */
}
/* 商品样式 */
.item {
box-shadow: 0 2px 4px rgba(0, 0, 0, 1); /* 阴影效果 */
margin-bottom: 20px; /* 底部外边距 */
break-inside: avoid; /* 防止商品被分割 */
background-color: #fff; /* 背景颜色 */
border: 1px solid #ccc; /* 边框 */
box-sizing: border-box; /* 盒模型 */
padding: 10px; /* 内边距 */
}
/* 商品图片 */
.item img {
width: 100%; /* 宽度为 100% */
height: auto; /* 高度自适应 */
}
/* 商品标题 */
.item h3 {
margin-top: 10px; /* 顶部外边距 */
font-size: 18px; /* 字体大小 */
font-weight: bold; /* 字体加粗 */
}
/* 商品描述 */
.item p {
margin-top: 5px; /* 顶部外边距 */
font-size: 14px; /* 字体大小 */
color: #666; /* 字体颜色 */
}
/* 商品价格 */
.item span {
display: block; /* 块级元素 */
margin-top: 10px; /* 顶部外边距 */
font-size: 20px; /* 字体大小 */
font-weight: bold; /* 字体加粗 */
color: #f00; /* 字体颜色 */
}
/* 图片轮播组件 */
.slider {
position: relative; /* 相对定位 */
width: 100%; /* 宽度为 100% */
height: 200px; /* 高度为 200px */
overflow: hidden; /* 溢出隐藏 */
}
/* 图片 */
.slider img {
position: absolute; /* 绝对定位 */
top: 0; /* 顶部为 0 */
left: 0; /* 左侧为 0 */
width: 100%; /* 宽度为 100% */
height: 100%; /* 高度为 100% */
opacity: 0; /* 初始透明度为 0 */
transition: opacity 0.5s ease-in-out; /* 过渡效果 */
}
/* 第一张图片 */
.slider img:first-child {
opacity: 1; /* 初始透明度为 1 */
}
/* 前进和后退按钮 */
.slider .prev,
.slider .next {
position: absolute; /* 绝对定位 */
top: 50%; /* 上下居中 */
transform: translateY(-50%); /* 上下居中 */
width: 30px; /* 宽度为 30px */
height: 30px; /* 高度为 30px */
background-color: #fff; /* 背景颜色 */
border: 1px solid #ccc; /* 边框 */
border-radius: 50%; /* 圆角 */
text-align: center; /* 文字居中 */
line-height: 30px; /* 行高为 30px */
cursor: pointer; /* 鼠标指针为手型 */
}
/* 前进按钮 */
.slider .prev {
left: 10px; /* 左侧为 10px */
}
/* 后退按钮 */
.slider .next {
right: 10px; /* 右侧为 10px */
}
/* 媒体查询 */
@media screen and (max-width: 900px) {
.container {
column-count: 3; /* 列数为 3 */
}
}
@media screen and (max-width: 768px) {
.container {
column-count: 2; /* 列数为 2 */
}
}
要点,要点,要点,js部分
js部分可以分为三个部分,第一个部分我们要拿取一些数据。页面的数据,我利用fastmock写了一个接口替代伪数据,其实也就是在fastmock写了一个json数据,只不过仿造了请求数据的形式而已,大家也可以专门下载下来放到本地使用。然后第二部分,我主要实现的是页面渲染挂载到页面上。第三部分就是开头我们看到的轮播图的效果。 这段代码是一个使用 Fetch API 获取数据并渲染商品列表的 JavaScript 代码。具体实现步骤如下:
- 使用
fetch方法获取数据 我的数据接口
// 获取数据的函数
function fetchData() {
// 使用 fetch 方法获取数据
return fetch('https://www.fastmock.site/mock/8766179555b3d4e427d54b47a0f4b529/products/products')
.then(response => {
// 如果响应成功,则返回 JSON 格式的数据
if (response.ok) {
return response.json();
} else {
// 如果响应失败,则抛出错误
throw new Error('Network response was not ok.');
}
})
.catch(error => {
// 捕获错误并输出到控制台
console.error(error);
});
}
- 在获取数据成功后,使用
innerHTML属性将商品列表渲染到页面中。我采用的是渲染的时候把第一个元素单独拿出来渲染,渲染成轮播图,其他就是正常的商品元素。
// 获取商品容器元素
var container = document.querySelector('.container');
// 获取数据并渲染商品列表
fetchData().then(data => {
// 将数据存储到 items 变量中
let items = data;
// 遍历 items 数组,渲染每个商品
for (var i = 0; i < items.length; i++) {
var item = items[i];
// 如果不是第一个商品,则渲染普通商品
if (i !== 0) {
// 构造商品 HTML 代码
var html = '<div class="item">' +
'<img src="' + item.image + '" alt="Product Image">' +
'<h3>' + item.title + '</h3>' +
'<p>' + item.description.substring(0, 20) + '...</p>' +
'<span>' + item.price + '¥</span>' +
'</div>';
// 将商品 HTML 代码添加到商品容器中
container.innerHTML += html;
}
// 如果是第一个商品,则渲染轮播图商品
else {
// 构造轮播图商品 HTML 代码
var html = '<div class="item">' +
'<div class="slider">' +
'<img src="' + item.image + '" alt="Product Image">' +
'<img src="' + item.image1 + '" alt="Product Image">' +
'<img src="' + item.image2 + '" alt="Product Image">' +
'</div>' +
'<h3>' + item.title + '</h3>' +
'<p>' + item.description.substring(0, 20) + '...</p>' +
'<span>' + item.price + '¥</span>' +
'</div>';
// 将轮播图商品 HTML 代码添加到商品容器中
container.innerHTML += html;
}
}
- 对于商品列表中的轮播图,使用 JavaScript 实现轮播效果。
注意注意注意这一段代码应该也是放在fetchData().then(data => {})里,因为我们要特别注意,我们必须等需要的元素渲染完,才能拿到该元素,然后才能对它进行一些操作,添加轮播的效果。
// 获取所有轮播图元素
var sliders = document.querySelectorAll('.slider');
// 遍历轮播图元素,为每个轮播图添加轮播效果
for (var i = 0; i < sliders.length; i++) {
var slider = sliders[i];
// 获取轮播图中的所有图片元素
var images = slider.querySelectorAll('img');
// 创建轮播图的上一张和下一张按钮
var prev = document.createElement('div');
var next = document.createElement('div');
// 初始化轮播图的索引和定时器 ID
var index = 0;
var intervalId;
// 设置上一张和下一张按钮的样式和内容
prev.className = 'prev';
prev.innerHTML = '<';
next.className = 'next';
next.innerHTML = '>';
// 将上一张和下一张按钮添加到轮播图中
slider.appendChild(prev);
slider.appendChild(next);
// 显示当前轮播图的图片
function showImage() {
// 遍历所有图片元素,将它们的透明度设置为 0
for (var j = 0; j < images.length; j++) {
images[j].style.opacity = 0;
}
// 将当前图片元素的透明度设置为 1
images[index].style.opacity = 1;
}
// 显示下一张图片
function nextImage() {
// 计算下一张图片的索引
index = (index + 1) % images.length;
// 显示下一张图片
showImage();
}
// 显示上一张图片
function prevImage() {
// 计算上一张图片的索引
index = (index - 1 + images.length) % images.length;
// 显示上一张图片
showImage();
}
// 开始自动播放轮播图
function startAutoPlay() {
// 每隔 3 秒钟切换到下一张图片
intervalId = setInterval(nextImage, 3000);
}
// 停止自动播放轮播图
function stopAutoPlay() {
// 清除定时器
clearInterval(intervalId);
}
// 显示当前轮播图的第一张图片
showImage();
// 开始自动播放轮播图
startAutoPlay();
// 当点击上一张按钮时,停止自动播放,显示上一张图片,然后重新开始自动播放
prev.addEventListener('click', function () {
stopAutoPlay();
prevImage();
startAutoPlay();
});
// 当点击下一张按钮时,停止自动播放,显示下一张图片,然后重新开始自动播放
next.addEventListener('click', function () {
stopAutoPlay();
nextImage();
startAutoPlay();
});
// 当鼠标移动到轮播图上时,停止自动播放
slider.addEventListener('mouseover', function () {
stopAutoPlay();
});
// 当鼠标移出轮播图时,重新开始自动播放
slider.addEventListener('mouseout', function () {
startAutoPlay();
});
}
这样,就完成了使用 Fetch API 获取数据并渲染商品列表的 JavaScript 代码。
通过这次的商品响应式瀑布流,我们就可以结合之前的css实现电梯导航,和JS-实现电梯导航-标题高亮,再加上一些头部,和侧边栏,就可以手写一个电商平台的主页啦!