CSS Grid布局:从入门到放弃再到真香

news2025/4/14 12:56:04

Flexbox 与 Grid 布局:基础概念与特点

Flexbox

Flexbox(Flexible Box Layout),即弹性盒布局模型,主要用于创建一维布局,能够轻松实现元素在一行或一列中的排列、对齐与分布。通过display: flex属性启用 Flexbox 布局后,容器成为弹性容器,子元素成为弹性项。

其核心概念包括主轴(main axis)和交叉轴(cross axis)。

  • 开发者可以通过justify-content属性控制弹性项在主轴上的对齐方式,如flex-start(默认值,左对齐或上对齐)、flex-end(右对齐或下对齐)、center(居中对齐)、space-between(两端对齐,项目之间的间隔都相等)、space-around(每个项目两侧的间隔相等,所以项目之间的间隔比项目与边框的间隔大一倍)等;
  • 使用align-items属性控制弹性项在交叉轴上的对齐方式,取值如stretch(默认值,拉伸以填充容器)、flex-start、flex-end、center等。

比如创建一个简单的水平导航栏

.nav {
    display: flex;
    // justify-content: space-around;
    align-items: center;
    gap: 10px;
}

.nav-item {
/* 导航项样式 */
}

Grid

Grid 布局是一个基于网格的二维布局系统,专门用于创建复杂的网格结构,能够同时在行和列两个维度上精确控制元素的位置与大小。通过display: grid属性将容器定义为网格容器,容器内的子元素成为网格项。

Grid 布局引入网格轨道的概念,其指的是网格中的行或列;可以通过grid-template-rows和grid-template-columns属性来定义它们的大小。

超简单的一个例子:

.grid-container {
    display: grid;
    grid-template-columns: 1fr 2fr 1fr; /* 三列,第一列和第三列占一份空间,第二列占两份空间 */
    grid-template-rows: 100px auto 100px; /* 三行,第一行和第三行高度为100px,中间行自适应高 */
}
  • 这里的fr是一个特殊单位,表示网格容器中可用空间的等分数。除了fr,还可以使用像素(px)、百分比(%)等单位来定义轨道大小。

网格线(grid line)划分了网格轨道,每条网格线都有一个编号,从 1 开始。同时,也可以给网格线命名,方便在布局中引用。例如:

.grid-container {
    display: grid;
    grid-template-columns: [col1-start] 1fr [col2-start] 2fr [col2-end] 1fr [grid-end];
    grid-template-rows: [row1-start] 100px [row2-start] auto [row3-start] 100px [grid-end];
}
.item1 {
  grid-column: col1-start / col2-end;  /* 从第一列开始,到第二列结束 */
  grid-row: row1-start / row2-start;   /* 第一行 */
}

.item2 {
  grid-column: col2-start / grid-end;  /* 从第二列开始,到最后 */
  grid-row: row2-start / row3-start;   /* 第二行 */
}

网格区域(grid area)是由四条网格线围成的矩形区域,可以通过grid-template-areas属性来定义。结合grid-area属性,可将网格项放置到对应的网格区域中。例如:

<div class="grid-container">
  <div class="header">Header</div>
  <div class="header1">Header1</div>
  <div class="header2">Header2</div>
  <div class="main1">Main1</div>
  <div class="main2">Main2</div>
  <div class="sidebar">Sidebar</div>
  <div class="footer">Footer</div>
  <div class="footer1">Footer1</div>
  <div class="footer2">Footer2</div>
</div>


.grid-container {
  display: grid;
  grid-template-areas: 
    "header header1 header2"
    "main1 main2 sidebar"
    "footer footer1 footer2";
  grid-template-columns: 2fr 1fr 1fr;
  grid-template-rows: 100px auto 100px;
  gap: 10px;
}

.header     { grid-area: header; background: #d0e; }
.header1    { grid-area: header1; background: #cce; }
.header2    { grid-area: header2; background: #ace; }
.main1      { grid-area: main1; background: #eda; }
.main2      { grid-area: main2; background: #ebf; }
.sidebar    { grid-area: sidebar; background: #bee; }
.footer     { grid-area: footer; background: #ffc; }
.footer1    { grid-area: footer1; background: #ffa; }
.footer2    { grid-area: footer2; background: #eef; }

在这里插入图片描述

Grid 布局案例解析

瀑布流布局

<div class="waterfall-grid">
  <div class="waterfall-item"><img src="https://picsum.photos/200/300?random=1" alt="Image 1"></div>
  <div class="waterfall-item"><img src="https://placehold.co/200x300?text=2" alt="Image 2"></div>
  <div class="waterfall-item"><img src="https://loremflickr.com/320/240?lock=3" alt="Image 3"></div>
  <div class="waterfall-item"><img src="https://picsum.photos/300/300?random=4" alt="Image 4"></div>
  <div class="waterfall-item"><img src="https://placehold.co/200x300?text=5" alt="Image 5"></div>
  <div class="waterfall-item"><img src="https://loremflickr.com/320/240?lock=6" alt="Image 6"></div>
  <div class="waterfall-item"><img src="https://picsum.photos/200/300?random=7" alt="Image 7"></div>
  <div class="waterfall-item"><img src="https://placehold.co/200x300?text=8" alt="Image 8"></div>
  <div class="waterfall-item"><img src="https://loremflickr.com/320/240?lock=9" alt="Image 9"></div>
  <div class="waterfall-item"><img src="https://picsum.photos/200/300?random=12" alt="Image 10"></div>
</div>
.waterfall-grid{
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    grid-gap: 10px;
    grid-template-rows: masonry;
}
.waterfall-item{
    width: 100%;
    display: block;
}
  • 仅适用于firefox浏览器!!

js+css方式实现瀑布流

在这里插入图片描述

<div class="waterfall-container" id="waterfall"></div>
.waterfall-container {
  position: relative;
  width: 100%;
}

.waterfall-item {
  position: absolute;
  width: 200px;
  transition: all 0.3s ease;
  box-shadow: 0 2px 10px rgba(0,0,0,0.1);
  border-radius: 8px;
  overflow: hidden;
}
.waterfall-item img {
  width: 100%;
  display: block;
}

  const container = document.getElementById('waterfall')
  const itemWidth = 200
  const gap = 5
  const itemCount = 50

  function createImage(index) {
    const div = document.createElement('div')
    div.className = 'waterfall-item'
    const height = 150 + Math.floor(Math.random() * 150) // 随机高度
    div.innerHTML = `<img src="https://picsum.photos/200/${height}?random=${index}" alt="img">`
    return div
  }

  function layoutWaterfall() {
    const containerWidth = container.clientWidth
    console.log(containerWidth, container,'containerWidth')
    const columns = Math.floor(containerWidth / (itemWidth + gap))
    const columnHeights = Array(columns).fill(0)

    const items = Array.from(container.children)

    items.forEach((item, index) => {
      const minCol = columnHeights.indexOf(Math.min(...columnHeights))
      const x = minCol * (itemWidth + gap)
      const y = columnHeights[minCol]

      item.style.left = x + 'px'
      item.style.top = y + 'px'

      columnHeights[minCol] += item.offsetHeight + gap
    })

    container.style.height = Math.max(...columnHeights) + 'px'
  }

  // 初始化渲染
  for (let i = 0; i < itemCount; i++) {
    const item = createImage(i)
    container.appendChild(item)
  }

  // 等图片加载后再布局
  window.addEventListener('load', layoutWaterfall)
  window.addEventListener('resize', () => {
    setTimeout(layoutWaterfall, 200)
  })
  • 主要逻辑就是每次找到最短的一列,将新加入的图片放入该列

Dashboard布局

草图
+--------------------------+
|        Header            |
+--------+-----------------+
| Sidebar|     Main        |
|        |  (cards, chart) |
+--------+-----------------+

在这里插入图片描述

<div class="dashboard-grid">
  <header class="header">Header</header>
  <aside class="sidebar">Sidebar</aside>
  <main class="main">
    <div class="card">Card 1</div>
    <div class="card">Card 2</div>
    <div class="card">Card 3</div>
    <div class="card">Card 4</div>
  </main>
</div>
.dashboard-grid {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar main";
  grid-template-columns: 250px 1fr;
  grid-template-rows: 60px 1fr;
  height: 100vh;
}

.header {
  grid-area: header;
  background: #2d3e50;
  color: white;
  padding: 1rem;
}

.sidebar {
  grid-area: sidebar;
  background: #34495e;
  color: white;
  padding: 1rem;
}

.main {
  grid-area: main;
  padding: 1rem;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
  gap: 16px;
}

.card {
  background: white;
  padding: 1rem;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}
  • 可以随意的扩充图表,加入<div class="chart"> 区块

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Springboot把外部jar包打包进最终的jar包,并实现上传服务器

1、创建lib目录&#xff0c;把jar包放进这个目录下&#xff0c;然后标记lib目录为“资源根路径”&#xff08;鼠标右键lib目录->将目录标记为->资源根路径。之后lib文件夹会有如下的图标变化&#xff09; 文件结构如下&#xff1a; 2、pom文件添加依赖 <dependency…

仿照管理系统布局配置

1.vue仿照snowy 配置&#xff0c;如下图&#xff1a; 2.代码实现 <template><div class"theme-settings"><!-- 导航栏 --><div class"nav-bar"><el-breadcrumb separator"/"><el-breadcrumb-item>导航设置…

GPT - 因果掩码(Causal Mask)

本节代码定义了一个函数 causal_mask&#xff0c;用于生成因果掩码&#xff08;Causal Mask&#xff09;。因果掩码通常用于自注意力机制中&#xff0c;以确保模型在解码时只能看到当前及之前的位置&#xff0c;而不能看到未来的信息。这种掩码在自然语言处理任务&#xff08;如…

适合工程建筑行业的OA系统有什么推荐?

工程行业具有项目周期长、协作链条复杂等特性&#xff0c;传统管理模式下的 “人治”“纸质化” 弊端日益凸显。OA 系统作为数字化管理的核心载体&#xff0c;通过流程标准化、数据可视化&#xff0c;精准解决工程行业项目管理核心痛点。 泛微 e-office 深度聚焦工程场景&#…

深入解析栈回溯技术:如何通过异常处理精准定位程序崩溃点

一、栈回溯 1.1 栈回溯的原理 调试程序时&#xff0c;经常发生这类错误&#xff1a; 1.读写某个地址&#xff0c;导致程序崩溃 2.调用某个空函数&#xff0c;导致程序崩溃在异常处理函数中&#xff0c;可以打印出”发生错误瞬间”的所有寄存器。 我们调试时&#xff0c;可以…

重构居家养老安全网:从 “被动响应” 到 “主动守护”

随着全球老龄化加剧&#xff0c;居家养老安全成为社会关注的核心议题。 传统养老模式依赖人工巡检或单一传感器&#xff0c;存在响应滞后、隐私泄露、场景覆盖不足等问题。 由此智绅科技应运而生&#xff0c;七彩喜智慧养老系统构筑居家养老安全网。 而物联网&#xff08;Io…

Unity6下架中国区,团结引擎接棒:这是分裂,还是本地化的开始?

就在近日&#xff0c;一则消息在国内游戏开发圈内迅速传播开来&#xff1a;Unity 6 及其后续版本已在中国大陆及港澳地区下架。这意味着&#xff0c;未来中国用户将无法直接使用 Unity 最新的主线版本。而取而代之的&#xff0c;是由 Unity 中国主导推出的本地化产品 —— 团结…

ESP8266水位监测以及温湿度数据采集

上面就是ESP8266的引脚图&#xff0c;水温检测使用的是水位监测传感器&#xff0c;温湿度测量使用的是DHT11&#xff0c;DHT11的反应时间是2秒&#xff0c;这里要注意。开发采用Arduino程序 1. 传感器初始化 功能&#xff1a;初始化DHT11温湿度传感器和串口通信。 代码实现&…

国产信创数据库:PolarDB 分布式版 V2.0,支持集中分布式一体化

阿里云PolarDB数据库管理软件&#xff08;分布式版&#xff09;V2.0 &#xff0c;安全可靠的集中分布式一体化数据库管理软件。点此查看详情https://www.aliyun.com/activity/database/polardbx-v2?spma2c6h.13046898.publish-article.8.44146ffaE0lEWT 立即咨询专家&#xf…

Axure PR 9 中继器 09 删除行

大家好&#xff0c;我是大明同学。 接着上期的内容&#xff0c;这期内容&#xff0c;我们来了解一下Axure中继器数据表删除行交互设计。 预览地址&#xff1a;https://vvlmqu.axshare.com 删除行 1.打开上期RP 文件&#xff0c;设计一个删除弹窗元件&#xff0c; 创建为动态面…

HDCP(五)

HDCP 2.2 测试用例设计详解 基于HDCP 2.2 CTS v1.1规范及协议核心机制&#xff0c;以下从正常流程与异常场景两大方向拆解测试用例设计要点&#xff0c;覆盖认证、密钥管理、拓扑验证等关键环节&#xff1a; 1. 正常流程测试 1.1 单设备认证 • 测试目标&#xff1a;验证源设…

商城APP打包教程

下载 HBuilderX 工具 HBuilderX支持插件拓展功能。App开发版已集成相关插件、开箱即用 根据自身电脑系统选择对应软件下载&#xff0c;建议选择APP开发版 2. 下载好软件安装后打开 建议直接在uniapp插件页面一键导入&#xff0c;正常情况下uniapp插件都是最新的&#xff0c;大家…

Spring 框架的核心基础:IoC 和 AOP

一、IoC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09; 定义&#xff1a; IoC&#xff08;Inversion of Control&#xff0c;控制反转&#xff09;&#xff0c;就是把对象创建和依赖关系的管理交给 Spring 容器&#xff0c;而不是由程序员手动去创建对象…

SpringBoot 基础知识,HTTP 概述

1. 概述 1.1 Spring Spring 提供若干个子项目&#xff0c;每个项目用于完成特定功能 Spring 的若干个子项目都基于一个基础的框架&#xff1a;Spring Framework 框架类似于 房屋的地基 但 Spring Framework 配置繁琐&#xff0c;入门难度大 1.2 Spring Boot 于是&#xf…

《网络管理》实践环节04:SNMP监控数据采集流程及SNMP协议详细分析

兰生幽谷&#xff0c;不为莫服而不芳&#xff1b; 君子行义&#xff0c;不为莫知而止休。 1 实验目标 1. 理解SNMP网络管理原理 2. 掌握SNMP服务器采集SNMP Agent数据的方法 3. 掌握SNMP报文发送和应答流程 4. 掌握典型GetResponsePDU数据结构分析的方法 4. 具备SNMP通信…

《Uniapp-Vue 3-TS 实战开发》构建HTTP请求拦截器

引言 在 UniApp 结合 TypeScript 和 Vue3 的项目开发中&#xff0c;请求拦截器起着至关重要的作用。它能够在请求发送前和响应接收后对数据进行统一处理&#xff0c;极大地提高了代码的可维护性和功能性。本文将详细解析上述代码中请求拦截器的实现及其在 UniApp-Ts-Vue3 项目中…

从PDF中提取表格:以GB/T2260—2007为例

文章目录 先说结论前因后果思路1、PDF2CSV2、PDF2MD → MD2CSV3、针对不同表格的两种思路1&#xff09; 竖形三线表2&#xff09;五元素为一组 还没结束批量处理1、分割markdown文档2、跳过另一种格式的文档 总结一下 先说结论 结论就是&#xff0c;博主用了一天的时间去研究如…

初识MySQL · 复合查询(内外连接)

目录 前言&#xff1a; 基本查询回顾 笛卡尔积和子查询 笛卡尔积 内外连接 子查询 单行子查询 多行子查询 多列子查询 from中使用子查询 合并查询 前言&#xff1a; 在前文我们学习了MySQL的基本查询&#xff0c;就是简单的套用了select语句&#xff0c;最多不过是…

辛格迪客户案例 | 北京舒曼德医药实施电子合约系统(eSign)

01 北京舒曼德医药科技开发有限公司&#xff1a;医药科技的数字化先锋 北京舒曼德医药科技开发有限公司&#xff08;以下简称“舒曼德医药”&#xff09;作为国内医药科技领域的领军企业&#xff0c;致力于创新药物的研发、临床试验和市场推广。公司以“科技兴药、质量为先、服…

Python面向对象-开闭原则(OCP)

1. 什么是开闭原则&#xff1f; 开闭原则(Open-Closed Principle, OCP) 是面向对象设计的五大SOLID原则之一&#xff0c;由Bertrand Meyer提出。其核心定义是&#xff1a; “软件实体(类、模块、函数等)应该对扩展开放&#xff0c;对修改关闭。” 对扩展开放&#xff1a;当需求…