Html手写一个各大商品网站的响应式瀑布流

1,124 阅读8分钟

Html手写一个各大商品网站的响应式瀑布流

首先我们先看一下各大电商网站的商品布局

淘宝的瀑布流里面会夹带着一个轮播图,和一些其他布局的东西。 1AF392351AE7C0723FDBF60C56549A7A.jpg 京东的瀑布流也差不多,不过我们可以看到京东把图片的高度都设定成了固定大小,每个item的大小都一样,感觉少了一点什么。没有淘宝的那种交错的感觉。 image.png 拼多多的瀑布流与京东的比较相似,不过相对看起来更简单,它里面没有包含一些其他的内嵌内容。 image.png

简单实现一个瀑布流

我这里采用的是column-count ,该属性可以用来实现基于列的布局,将一个容器分成多列,每列的宽度相等。在制作瀑布流时,我们可以将商品容器设置为多列布局,让商品自动填充到每一列中,从而实现瀑布流的效果。

具体实现步骤如下:

  1. 将商品容器设置为多列布局,使用 column-count 属性设置列数,例如:
.container {
  column-count: 4;
}
  1. 设置商品容器的列间距,使用 column-gap 属性设置列间距,例如:
.container {
  column-gap: 20px;
}
  1. 设置商品容器的防止分割属性,使用 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循环渲染挂载实现页面。 image.png

<!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 代码。具体实现步骤如下:

  1. 使用 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);
        });
}
  1. 在获取数据成功后,使用 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;
        }
    }
  1. 对于商品列表中的轮播图,使用 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 = '&lt;';
        next.className = 'next';
        next.innerHTML = '&gt;';
        // 将上一张和下一张按钮添加到轮播图中
        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-实现电梯导航-标题高亮,再加上一些头部,和侧边栏,就可以手写一个电商平台的主页啦!

写文章不易,麻烦大家点点赞,给给鼓励,后面继续更。

源码-掘金/瀑布流布局