响应式布局下关于gird栅格布局的一些构思

1、传列数,根据列数计算元素容器宽度

好处是子元素可以写百分比宽度,不用固定某一种宽度,反正知道列数通过计算间距就能得到外层容器的宽度。
举个简单的例子:

(ps:以下用例皆在html中去模拟,就不另外起react或者vue应用了,主打一个轻便。)

在瀑布流下面的栅格布局

  • 先尝试固定列数3,并且固定宽高100px
<!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>
    <style>
      .item {
        color: white;
        background-color: violet;
        width: 100px;
        height: 100px;
        margin: 2px;
        text-align: center;
      }
      .waterfall {
        display: flex;
        flex-wrap: wrap;
      }
    </style>
  </head>
  <body>
    <div class="grid waterfall"></div>
  </body>
  <script>
    const column = 3;
    const list = [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    ];
    const UIList = list.map((item) => {
      return `<div class="item">${item}</div>`;
    });
    const renderList = new Array(column);
    const finalList = UIList.forEach((item, childIndex) => {
      const realIndex = childIndex % column;
      if (!renderList[realIndex]) {
        renderList[realIndex] = [];
      }
      renderList[realIndex].push(item);
      console.log("renderList", renderList);
    });
    const html = renderList.map((item) => {
      return `<div class="waterfall-item">${item.join("")}</div>`;
    });
    document.querySelector(".grid").innerHTML = html.join("");
  </script>
</html>

得到的结果:
在这里插入图片描述
好,写法ok,让我们试试列数固定(通过api传入),子元素宽度根据公式计算呢。
理论计算公式:元素宽度 = (屏幕宽度 - 左右间距宽度 - 列之间的间距)/ 列数
注意3列的话,计算列的宽度就是 2个列宽,自己体会。
在这里插入图片描述
好!理论成立,实践开始~!

我们修改下css,让item元素的宽高不在固定。

   .item {
        color: white;
        background-color: violet;
        height: auto;
        margin: 2px;
        text-align: center;
      }

在这里插入图片描述
于是我们得到了上面一坨,因为宽度和高度根据内容自适应了,所以只包裹了填充的数字。

嗯,在意料之中。
在这里插入图片描述

那么关键的计算来了,且看下面的js:

    const column = 3;   // 列数
    const screenWith = window.innerWidth; // 屏宽
    const paddingLeft = 12; // 页面左间距
    const paddingRight = 12; // 页面右间距
    const columnWith = 8; // 列之间的间距

我们先设定页面左右间距为12(px),列间距为8(px).
然后我们就可以计算单个元素容器宽度了:

  // 四舍五入并且精确到2位小数,防止列数过多而误差过大
  const itemWidth =
      Math.round(
        ((screenWith - paddingLeft - paddingRight - columnWith * (column - 1)) /
          column) *
          100
      ) / 100;

然后将元素的间距设置成和js里写的一致(当然你也可以把他们开放成动态的api):
完整demo:

<!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>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      .item {
        color: white;
        background-color: violet;
        height: 50px;
        margin-bottom: 8px;
        text-align: center;
      }
      .item:last-child {
        margin-bottom: 0;
      }
      .waterfall {
        display: flex;
        flex-wrap: wrap;
        padding: 0 12px;
      }
      .waterfall-item {
        margin-left: 8px;
      }
      .waterfall-item:first-child {
        margin-left: 0;
      }
    </style>
  </head>
  <body>
    <div class="grid waterfall"></div>
  </body>
  <script>
    const column = 3;
    const list = [
      1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
    ];
    const screenWidth = window.innerWidth;
    const paddingLeft = 12;
    const paddingRight = 12;
    const columnWidth = 8;

    const itemWidth =
      Math.round(
        ((screenWidth - paddingLeft - paddingRight - columnWidth * (column - 1)) /
          column) *
          100
      ) / 100;
    console.log("itemWidth", itemWidth);
    const UIList = list.map((item) => {
      return `<div class="item" style="width: ${itemWidth}px;">${item}</div>`;
    });
    const renderList = new Array(column);
    const finalList = UIList.forEach((item, childIndex) => {
      const realIndex = childIndex % column;
      if (!renderList[realIndex]) {
        renderList[realIndex] = [];
      }
      renderList[realIndex].push(item);
    });
    const html = renderList.map((item) => {
      return `<div class="waterfall-item">${item.join("")}</div>`;
    });
    document.querySelector(".grid").innerHTML = html.join("");
  </script>
</html>

效果:
在这里插入图片描述

测试高度不一样的栅格效果

增加修改以下代码,意思是给5的倍数的子元素高度设置到100px

   .more-height {
        height: 100px;
      }
    const UIList = list.map((item, index) => {
      return `<div class="item ${
        index % 5 === 0 ? "more-height" : ""
      }" style="width: ${itemWidth}px;">${item}</div>`;
    });

效果:
在这里插入图片描述
不错,符合预期~

如果我们连列数colum都不想传了咋办?能不能自适应屏幕尺寸设置列数

答案当然是肯定的,前提你要和设计师商量好什么尺寸下出多少列。

比如我们规定:
320px以下,展示2列
320~600px, 展示3列
600~920px,展示4列
920px以上,还是4列,但是容器宽度增加,这时候就需要子元素也做了响应式,否则会造成容器空旷很多。
使用以下方法,动态确定colum列数:

 let column = 2;
    function handleResize() {
      const screenWidth = window.innerWidth;
      if (screenWidth < 320) {
        column = 2;
      } else if (screenWidth >= 320 && screenWidth < 600) {
        column = 3;
      } else {
        column = 4;
      }
    }
    // 监听窗口大小变化
    window.addEventListener("resize", handleResize);
    // 页面加载时执行一次屏幕尺寸判断
    handleResize();

看看效果:
320以下展示2行:
在这里插入图片描述

320~600 展示3行:
在这里插入图片描述
600~920 展示4行:
在这里插入图片描述
920往上还是4行,但是单元格宽度增加:
在这里插入图片描述

上面的唯一缺点大概是因为是js控制,页面只要不刷新,即使尺寸变了也不会去动态的计算列数,在移动端影响不大~

2、根据子元素宽度,自动适应列数

如果是采用这种方案,那么子元素必须显示的定义了宽度,即只有子元素存在定义的宽度时才能正确计算。

这种方法则对子元素要求很高,需要子元素定宽并且适配了各种各样屏幕宽度下的尺寸。

我们的计算规则则变成了:
列数 = (屏幕宽度 - 页面左右间距- (列数-1) *列间距) / 子元素宽度(固定)
该公式解出来变成:
列数 = (屏宽 - 左右间距 + 列间距) / (子元素宽度+列间距)

假定我们各项数据值是:

    const screenWith = window.innerWidth;
    const paddingLeft = 12;  // 左间距
    const paddingRight = 12;  // 右间距
    const columnWidth = 8;  // 列宽
    const itemWidth = 120; // 子元素宽度

计算规则如下:

    // 列数必须向下取整,否则会放不下
    column = Math.floor(
      (screenWith - paddingLeft - paddingRight + columnWidth) /
        (itemWidth + columnWidth)
    );

在这里插入图片描述
像上面这种就是剩余宽度明显不够一列被向下取整给截断了。
那么有没有很好的解法呢,目前看来如果子元素定宽,不太好自适应的。

非要定宽可以考虑:
1、列间距自适应
2、整体布局居中

另外在设置子元素宽度时
计算失败的几种情况:
1、子元素定义了100%宽度,旨在根据容器宽度去定宽,但是容器也没有定宽。
2、子元素没有设置宽度导致计算失败,这时候会写一个兼容值,那么固定就会获取这个兼容值。

以上就是个人碎碎念~

希望有所收获!

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/789776.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零基础STM32单片机编程入门(十二) HC-SR04超声波模块测距实战含源码

文章目录 一.概要二.HC-SR04主要参数1.模块引脚定义2.模块电气参数3.模块通讯时序4.模块原理图 三.STM32单片机超声波模块测距实验四.CubeMX工程源代码下载五.小结 一.概要 HC-SR04超声波模块常用于机器人避障、物体测距、液位检测、公共安防、停车场检测等场所。HC-SR04超声波…

宏碁F5-572G-59K3笔记本笔记本电脑拆机清灰教程(详解)

1. 前言 我的笔记本开机比较慢&#xff0c;没有固态&#xff0c;听说最近固态比较便宜&#xff0c;就想入手一个&#xff0c;于是拆笔记本看一下有没有可以安的装位置。&#xff08;友情提示&#xff0c;在拆机之前记得洗手并擦干&#xff0c;以防静电损坏电源器件&#xff09…

视频号的视频,一键就下载了,方法全在这儿了!

居然还有人不知道&#xff1a;视频号里面的视频是没有地址的&#xff0c;只能有微信自带的浏览器中打开。 所以很多人在视频号找到想要的素材&#xff0c;却无法下载&#xff0c;表示很苦恼。 几天每天都有人群里求助&#xff1a;“求好心人帮我下载一下这个视频&#xff01;…

昇思学习打卡-14-ResNet50迁移学习

文章目录 数据集可视化预训练模型的使用部分实现 推理 迁移学习&#xff1a;在一个很大的数据集上训练得到一个预训练模型&#xff0c;然后使用该模型来初始化网络的权重参数或作为固定特征提取器应用于特定的任务中。本章学习使用的是前面学过的ResNet50&#xff0c;使用迁移学…

STM32 GPIO的工作原理

STM32的GPIO管脚有下面8种可能的配置:&#xff08;4输入 2 输出 2 复用输出) &#xff08;1&#xff09;浮空输入_IN_FLOATING 在上图上&#xff0c;阴影的部分处于不工作状态&#xff0c;尤其是下半部分的输出电路&#xff0c;实际上是与端口处于隔离状态。黄色的高亮部分显示…

在攻防演练中遇到的一个“有马蜂的蜜罐”

在攻防演练中遇到的一个“有马蜂的蜜罐” 有趣的结论&#xff0c;请一路看到文章结尾 在前几天的攻防演练中&#xff0c;我跟队友的气氛氛围都很好&#xff0c;有说有笑&#xff0c;恐怕也是全场话最多、笑最多的队伍了。 也是因为我们遇到了许多相当有趣的事情&#xff0c;其…

Mac窗口辅助管理工具:Magnet for mac激活版

magnet mac版是一款运行在苹果电脑上的一款优秀的窗口大小控制工具&#xff0c;拖拽窗口到屏幕边缘可以自动半屏&#xff0c;全屏或者四分之一屏幕&#xff0c;还可以设定快捷键完成分屏。这款专业的窗口管理工具当您每次将内容从一个应用移动到另一应用时&#xff0c;当您需要…

python学习-容器类型

列表 列表&#xff08;list&#xff09;是一种有序容器&#xff0c;可以向其中添加或删除任意元素. 列表数据类型是一种容器类型&#xff0c;列表中可以存放不同数据类型的值,代码示例如下&#xff1a; 列表中可以实现元素的增、删、改、查。 示例代码如下&#xff1a; 增 …

医疗器械网络安全 | 漏洞扫描、渗透测试没有发现问题,是否说明我的设备是安全的?

尽管漏洞扫描、模糊测试和渗透测试在评估系统安全性方面是非常重要和有效的工具&#xff0c;但即使这些测试没有发现任何问题&#xff0c;也不能完全保证您的医疗器械是绝对安全的。这是因为安全性的评估是一个多维度、复杂且持续的过程&#xff0c;涉及多个方面和因素。以下是…

AI提示词:打造爆款标题生成器

打开GPT输入以下内容&#xff1a; # Role 爆款标题生成器## Profile - author: 姜小尘 - version: 02 - LLM: Kimi - language: 中文 - description: 利用心理学和市场趋势&#xff0c;生成吸引眼球的自媒体文章标题。## Background 一个吸引人的标题是提升文章点击率和传播力…

优化爬虫体验:揭秘IP重复率过高问题解决方案

在当今信息爆炸的时代&#xff0c;网络中蕴藏着大量宝贵的数据&#xff0c;而爬虫技术成为我们提取这些数据的重要工具。然而&#xff0c;随着爬虫的广泛使用&#xff0c;IP重复率高的问题也随之而来。本篇博文将揭秘解决这一问题的关键方法——使用IP代理。 一、 IP高重复问题…

手慢无,速看︱PMO大会内部学习资料

全国PMO专业人士年度盛会 每届PMO大会&#xff0c;组委会都把所有演讲嘉宾的PPT印刷在了会刊里面&#xff0c;供大家会后回顾与深入学习。 第十三届中国PMO大会-会刊 《2024第十三届中国PMO大会-会刊》 &#xff08;内含演讲PPT&#xff09; 会刊&#xff1a;750个页码&…

TK 检查输入框是否为空

在Python的Tkinter库中&#xff0c;你可以使用事件绑定或者在按钮点击事件中检查输入框的值是否为空来实现这个功能。以下是一个简单的例子&#xff1a; import tkinter as tk from tkinter import messageboxdef check_input():entry input_box.get()if not entry:messagebo…

《梦醒蝶飞:释放Excel函数与公式的力量》10.4 IMREAL函数

第四节 10.4 IMREAL函数 10.4.1 函数简介 IMREAL函数是Excel中的一个工程函数&#xff0c;用于提取复数的实部。在复数运算中&#xff0c;实部是复数的一部分&#xff0c;表示没有虚部参与的部分。IMREAL函数提供了一个简单的方法来获取复数的实部&#xff0c;便于进一步计算…

Java 8革新:现代编程的全新标准与挑战

文章目录 一、方法引用二、接口默认方法三、接口静态方法四、集合遍历forEach()方法 一、方法引用 方法引用是Java 8中一种简化Lambda表达式的方式&#xff0c;通过直接引用现有方法来代替Lambda表达式。 方法引用使得代码更加简洁和易读&#xff0c;特别是在处理函数式接口时&…

ns3学习笔记(四):路由概述

基于官网文档的 Routing Overview 部分详细研究一下ns3中路由是怎么工作的 文档链接16.4. Routing overview — Model Library 一、概述 NS3整体的工作架构如下&#xff1a; 路由部分的工作架构如下&#xff1a; 路由部分目前大多数用到的算法都包含在Ipv4RoutingProtocol部分…

常用网络概念

&#x1f4d1;打牌 &#xff1a; da pai ge的个人主页 &#x1f324;️个人专栏 &#xff1a; da pai ge的博客专栏 ☁️宝剑锋从磨砺出&#xff0c;梅花香自苦寒来 ​​ 目录 了解组织 局域网技术 …

【Ty CLI】一个开箱即用的前端脚手架

目录 资源链接基础命令模板创建命令帮助选择模板开始创建开发模板 开发背景npm 发布流程问题记录模板创建超时 更新日志 资源链接 文档&#xff1a;https://ty.cli.vrteam.top/ 源码&#xff1a;https://github.com/bosombaby/ty-cli 基础命令 1. npm 全局安装 npm i ty-cli…

开发个人Go-ChatGPT--6 OpenUI

开发个人Go-ChatGPT–6 OpenUI Open-webui Open WebUI 是一种可扩展、功能丰富且用户友好的自托管 WebUI&#xff0c;旨在完全离线运行。它支持各种 LLM 运行器&#xff0c;包括 Ollama 和 OpenAI 兼容的 API。 功能 由于总所周知的原由&#xff0c;OpenAI 的接口需要密钥才…

NAS免费用,鲁大师 AiNAS正式发布,「专业版」年卡仅需264元

7月10日&#xff0c;鲁大师召开新品发布会&#xff0c;正式发布旗下以“提供本地Ai部署和使用能力以及在线NAS功能”并行的复合软件产品&#xff1a;鲁大师 AiNAS。 全新的鲁大师 AiNAS将持续满足现如今大众对于数字化生活的全新需求&#xff0c;将“云存储”的便捷与NAS的大容…