TinyVue Layout 组件完全指南:别再手写 float 和 flex 了,栅格早该这样用

TinyVue Layout 组件完全指南:别再手写 float 和 flex 了,栅格早该这样用

开篇:前端布局的血泪史

如果你入行超过三年,一定经历过以下阶段:

远古时代<table> 布局。一个页面嵌套七八层 <table>,改一个单元格宽度整个页面崩盘,调试时你恨不得把显示器砸了。

中世纪float 布局。float: leftclear: both,浮动元素像一群放学的孩子------往左跑的往左跑,该清浮动的没清,父元素高度直接塌成零。

启蒙时代 :Flexbox。终于不用 float 了,但 justify-content: space-betweenalign-items: center 写了一万遍,手写重复度令人发指。

然后你遇到了栅格布局。

栅格系统的本质是什么?把页面横向切成 N 等份,每列占其中几份。12 栅格意味着一个「三栏布局」就是 3+6+3,一个「左右两栏」就是 8+4。不用算像素、不用写 calc、不用琢磨百分比。

TinyVue 的 Layout 组件就是这套哲学的完美实现。它由三个子组件构成------Layout(容器)、Row(行)、Col(列),三者配合,把"写布局"这件事简化成"填数字"。


1. 三剑客:Layout、Row、Col

Layout 组件的核心是三层嵌套结构

vue 复制代码
<template>
  <tiny-layout>
    <tiny-row>
      <tiny-col :span="6"><div class="col">左栏</div></tiny-col>
      <tiny-col :span="6"><div class="col">右栏</div></tiny-col>
    </tiny-row>
  </tiny-layout>
</template>

<script setup>
import { TinyLayout, TinyRow, TinyCol } from '@opentiny/vue'
</script>
组件 角色 比喻
TinyLayout 栅格容器 棋盘
TinyRow 棋盘上的一行
TinyCol 一行中的某个格子

布局 = Layout 包 Row,Row 包 Col。 记住这个嵌套顺序,剩下的就是往 Col 上填 span 数字。


2. 12 栅格 vs 24 栅格:粗粒度还是细粒度?

TinyVue 的 Layout 组件有个 cols 属性,决定总栅格数:

vue 复制代码
<!-- 默认 12 栅格 -->
<tiny-layout>
  <tiny-row>
    <tiny-col :span="6"><div class="col">占半行</div></tiny-col>
    <tiny-col :span="6"><div class="col">占半行</div></tiny-col>
  </tiny-row>
</tiny-layout>

<!-- 24 栅格,更细粒度 -->
<tiny-layout :cols="24">
  <tiny-row>
    <tiny-col :span="8"><div class="col">8/24</div></tiny-col>
    <tiny-col :span="16"><div class="col">16/24</div></tiny-col>
  </tiny-row>
</tiny-layout>
cols 适用场景
12(默认) 常规页面布局,2/3/4 等分都很方便
24 需要更细粒度的控制,比如五等分、七等分

自动换行 :当一行内所有 Colspan 之和超过总栅格数时,多出来的列会自动换到下一行。不需要手动 v-for 里套 v-if 判断分行逻辑------

vue 复制代码
<tiny-layout>
  <tiny-row>
    <tiny-col :span="8"><div class="col">1</div></tiny-col>
    <tiny-col :span="8"><div class="col">2(span=8+8+8=24>12,自动换行)</div></tiny-col>
    <tiny-col :span="8"><div class="col">3(到了新行)</div></tiny-col>
  </tiny-row>
</tiny-layout>

3. Span:栅格的灵魂

spanCol 组件最核心的属性,表示当前列占几个栅格。

vue 复制代码
<tiny-layout>
  <!-- 经典三栏:左导航 3 + 主内容 6 + 右面板 3 = 12 -->
  <tiny-row>
    <tiny-col :span="3"><div class="col">导航菜单</div></tiny-col>
    <tiny-col :span="6"><div class="col">核心内容区</div></tiny-col>
    <tiny-col :span="3"><div class="col">侧边面板</div></tiny-col>
  </tiny-row>

  <!-- 非对称:主区 8 + 侧栏 4 -->
  <tiny-row>
    <tiny-col :span="8"><div class="col">文章详情</div></tiny-col>
    <tiny-col :span="4"><div class="col">相关推荐</div></tiny-col>
  </tiny-row>
</tiny-layout>

常见的 span 组合速查:

布局模式 span 组合 视觉效果
两栏等分 6 + 6 □□
三栏等分 4 + 4 + 4 □□□
左窄右宽 3 + 9 ▯□
左宽右窄 8 + 4 □▯
四等分 3 + 3 + 3 + 3 □□□□

不用 width: 25%,不用 flex: 1,填个数字就行了。


4. 响应式布局:一套代码适配手机到超大屏

这是 Layout 组件的王牌功能。Col 组件预设了五个响应式断点,一个属性搞定多端适配:

属性 断点 触发条件
xs < 768px 手机竖屏
sm < 992px 手机横屏 / 小平板
md < 1200px 平板 / 小笔记本
lg < 1920px 标准桌面
xl >= 1920px 大屏 / 超宽显示器
vue 复制代码
<tiny-layout>
  <tiny-row :gutter="10">
    <!-- 手机上一行4个,平板上3个,桌面上2个 -->
    <tiny-col :xs="3" :sm="4" :md="6" :lg="6" :xl="3">
      <div class="col">卡片1</div>
    </tiny-col>
    <tiny-col :xs="3" :sm="4" :md="6" :lg="6" :xl="3">
      <div class="col">卡片2</div>
    </tiny-col>
    <tiny-col :xs="3" :sm="4" :md="6" :lg="6" :xl="3">
      <div class="col">卡片3</div>
    </tiny-col>
    <tiny-col :xs="3" :sm="4" :md="6" :lg="6" :xl="3">
      <div class="col">卡片4</div>
    </tiny-col>
  </tiny-row>
</tiny-layout>

解读这个配置:在总栅格 12 的前提下:

  • 手机 (xs=3):每列占 3 格 → 一行 4 个 3 × 4 = 12
  • 平板(sm=4):每列占 4 格 → 一行 3 个
  • 桌面(md=6):每列占 6 格 → 一行 2 个

一套模板,五种尺寸自动适配,不需要写一行 media query。

注意 :断点是固定的 (768 / 992 / 1200 / 1920),你不需要也无法修改它们。但老实说,这几个断点覆盖了从 iPhone SE 到 4K 显示器的全部场景,够用了。


5. Flex 对齐:比 CSS 的 justify-content 还好记

Row 上设置 :flex="true" 后,就可以用 justifyalign 控制子项的对齐:

5.1 主轴对齐(justify)

vue 复制代码
<tiny-layout>
  <!-- 左对齐(默认) -->
  <tiny-row :flex="true">
    <tiny-col :span="3"><div class="col">左</div></tiny-col>
    <tiny-col :span="3"><div class="col">左</div></tiny-col>
  </tiny-row>

  <!-- 居中 -->
  <tiny-row :flex="true" justify="center">
    <tiny-col :span="3"><div class="col">中</div></tiny-col>
    <tiny-col :span="3"><div class="col">中</div></tiny-col>
  </tiny-row>

  <!-- 两端对齐 -->
  <tiny-row :flex="true" justify="space-between">
    <tiny-col :span="3"><div class="col">最左</div></tiny-col>
    <tiny-col :span="3"><div class="col">最右</div></tiny-col>
  </tiny-row>
</tiny-layout>

justify 可取值:

效果
start(默认) 左对齐
center 居中
end 右对齐
space-between 两端对齐,中间平均分布
space-around 每个子项两侧间距相等

5.2 副轴对齐(align)

配合不同高度的子项:

vue 复制代码
<tiny-row :flex="true" align="top">
  <tiny-col :span="4"><div style="height: 80px">高个子</div></tiny-col>
  <tiny-col :span="4"><div style="height: 40px">矮个子</div></tiny-col>
</tiny-row>
效果
top(默认) 顶部对齐
middle 垂直居中
bottom 底部对齐

6. Gutter 间距与 NoSpace:告别负 margin 黑魔法

栅格系统里最烦人的就是"列间距"。你给每列加 padding,第一列左边和最后一列右边也会多出空白------于是你写负 margin 抵消,然后发现容器溢出,再写 overflow: hidden......

TinyVue 的 gutter 属性直接终结这个循环:

vue 复制代码
<tiny-layout>
  <!-- gutter=0:无间距,列紧挨着 -->
  <tiny-row :gutter="0">
    <tiny-col :span="4"><div class="col">0</div></tiny-col>
    <tiny-col :span="4"><div class="col">0</div></tiny-col>
    <tiny-col :span="4"><div class="col">0</div></tiny-col>
  </tiny-row>

  <!-- gutter=20:每列左右各 10px 间距,总共 20px 间隙 -->
  <tiny-row :gutter="20">
    <tiny-col :span="4"><div class="col">20px 间隔</div></tiny-col>
    <tiny-col :span="4"><div class="col">20px 间隔</div></tiny-col>
    <tiny-col :span="4"><div class="col">20px 间隔</div></tiny-col>
  </tiny-row>
</tiny-layout>

gutter 的值代表相邻两列之间的间距 (px),组件自动给每列加 padding-leftpadding-right 各一半。首尾列的左右边缘不会有额外的 padding 溢出------Row 内部用负 margin 自动处理了。

NoSpace:一切归零

当你想彻底干掉所有间距时(比如平铺的图片墙),noSpacegutter="0" 更直接:

vue 复制代码
<tiny-row :gutter="0" noSpace>
  <tiny-col :span="4"><div class="col">无任何间距</div></tiny-col>
  <tiny-col :span="4"><div class="col">紧贴在一起</div></tiny-col>
</tiny-row>

7. Offset 偏移:留白也是一种布局

有时候你不需要把列从左到右塞满------中间留个空,右边放内容,左边空着。这就是 offset 的用武之地:

vue 复制代码
<tiny-layout>
  <tiny-row>
    <!-- 左侧空 4 格,中间占 4 格,右侧自动空 4 格 = 居中效果 -->
    <tiny-col :span="4" :offset="4">
      <div class="col">居中显示</div>
    </tiny-col>
  </tiny-row>

  <!-- 偏移 2 格再占 8 格 -->
  <tiny-row>
    <tiny-col :span="8" :offset="2">
      <div class="col">左边留白 2 格</div>
    </tiny-col>
  </tiny-row>
</tiny-layout>

offset 通过 margin-left 实现,而 move 属性通过 left 定位实现。一般用 offset 就够了,move 在特殊场景下可以作为备选。


8. Col 排序:模板里写死的顺序也能改

Roworder 属性配合 Colno 属性,可以在不改变模板结构的情况下重排子项顺序:

vue 复制代码
<tiny-layout>
  <tiny-row :flex="true" order="asc">
    <tiny-col :span="4" :no="3"><div class="col">no=3</div></tiny-col>
    <tiny-col :span="4" :no="1"><div class="col">no=1</div></tiny-col>
    <tiny-col :span="4" :no="2"><div class="col">no=2</div></tiny-col>
  </tiny-row>
</tiny-layout>

order 取值:

  • asc:按 no 值升序排列(数字小的靠前)
  • desc:按 no 值降序排列(数字大的靠前)
  • 不设置:保持模板中的原始顺序

这在后台管理系统中特别有用------比如不同角色的用户看到的列顺序不同,不改模板,只改 no 值就行。


9. Tag 自定义标签:div 腻了来点新鲜的

默认情况下 LayoutRowCol 都渲染为 <div>。但 HTML5 有了语义化标签,你可能想让 Row 渲染成 <section>,Col 渲染成 <article>

vue 复制代码
<tiny-layout tag="main">
  <tiny-row tag="section">
    <tiny-col :span="6" tag="article">
      <div class="col">语义化布局</div>
    </tiny-col>
    <tiny-col :span="6" tag="article">
      <div class="col">SEO 友好</div>
    </tiny-col>
  </tiny-row>
</tiny-layout>

三个组件都支持 tag 属性,可以设置任意 HTML 标签名。对于需要无障碍访问或 SEO 优化的页面,这个功能很实用。


10. 实战:一个完整的后台管理仪表盘

综合运用所有特性,做一个响应式仪表盘:

vue 复制代码
<template>
  <tiny-layout>
    <!-- 第一行:四个统计卡片,响应式排列 -->
    <tiny-row :gutter="16" :flex="true">
      <tiny-col :xs="6" :sm="6" :md="3" :span="3">
        <div class="stat-card">今日访问<br><strong>12,845</strong></div>
      </tiny-col>
      <tiny-col :xs="6" :sm="6" :md="3" :span="3">
        <div class="stat-card">活跃用户<br><strong>3,250</strong></div>
      </tiny-col>
      <tiny-col :xs="6" :sm="6" :md="3" :span="3">
        <div class="stat-card">新增订单<br><strong>467</strong></div>
      </tiny-col>
      <tiny-col :xs="6" :sm="6" :md="3" :span="3">
        <div class="stat-card">总收入<br><strong>¥85,200</strong></div>
      </tiny-col>
    </tiny-row>

    <!-- 第二行:大图表面板 + 侧边信息 -->
    <tiny-row :gutter="16">
      <tiny-col :xs="12" :span="8">
        <div class="chart-panel">图表区域(占 8 格)</div>
      </tiny-col>
      <tiny-col :xs="12" :span="4">
        <div class="info-panel">最近动态(占 4 格)</div>
      </tiny-col>
    </tiny-row>

    <!-- 底部操作栏,居中 -->
    <tiny-row :flex="true" justify="center" :gutter="12">
      <tiny-col :span="2">
        <tiny-button type="primary">导出</tiny-button>
      </tiny-col>
      <tiny-col :span="2">
        <tiny-button>刷新</tiny-button>
      </tiny-col>
    </tiny-row>
  </tiny-layout>
</template>

<script setup>
import { TinyLayout, TinyRow, TinyCol, TinyButton } from '@opentiny/vue'
</script>

手机上看:四个卡片竖排两两一行(xs=6),到了桌面就横向四个一排。一套代码,所有尺寸通吃。


总结:Layout 的哲学

特性 一句话
基础栅格 cols 定总数,span 定占位
响应式 xs/sm/md/lg/xl 五个断点自适应
Flex 对齐 justify + align,语义清晰
间距 gutter 不用手写 padding
偏移 offset 轻松实现居中或留白
排序 order 不改模板结构就能重排
自定义标签 tag 支持语义化 HTML

Layout 组件本质上做了两件事:

  1. 把布局从"手写 CSS"变成了"配置数字" 。你不再需要写 display: flex; justify-content: space-between; width: calc(33.33% - 20px)------填 spangutter 就够了。

  2. 把响应式从"N 套 CSS"变成了"一套配置"xs/sm/md/lg/xl 五个属性就是你的全部媒体查询。

Layout + Container = 完整的 TinyVue 布局方案。Container 管页面级骨架(header/aside/main/footer),Layout 管内容区的栅格排版。两者配合,从页面结构到内容排列,全链路搞定。

下次有人问你"这个页面用什么布局",直接告诉他:Layout + Row + Col,填数就行。

OpenTiny NEXT 是一套企业智能前端开发解决方案,以生成式 UI 和 WebMCP 两大核心技术为基础,对现有传统的 TinyVue 组件库、TinyEngine 低代码引擎等产品进行智能化升级,构建出面向 Agent 应用的前端 NEXT-SDKs、AI Extension、TinyRobot智能助手、GenUI等新产品,实现AI理解用户意图自主完成任务,加速企业应用的智能化改造。 欢迎加入 OpenTiny 开源社区。添加微信小助扏:opentiny-official 一起参与交流前端技术~ OpenTiny 官网:opentiny.design TinyVue 代码仓库:https://https://github.com/opentiny/tiny-vue(欢迎star ⭐)

相关推荐
AI行业学习1 小时前
CC-Switch v3.16.1 官方下载 | 安装配置详细教程【2026.6.10】
java·开发语言·vue.js·python·mysql·eclipse·html
小二·2 小时前
Spring Boot 3 + Vue 3 全栈开发实战
vue.js·spring boot·后端
阿猫的故乡3 小时前
Vue组合式函数(Composables)从入门到实战:鼠标跟踪、请求封装、本地存储……全案例拆解
前端·vue.js·计算机外设
一壶纱3 小时前
一个用于 UniApp 项目的 Pinia 持久化插件
前端·javascript·vue.js
流浪码农~5 小时前
Element Plus DatePicker 动态设置每周起始日
前端·vue.js·elementui
如果超人不会飞5 小时前
TinyVue NavMenu导航菜单组件使用指南
前端·vue.js
颂love5 小时前
Vue的两大生态以及组件通信
前端·javascript·vue.js·typescript
Csvn5 小时前
Vue3 迁移血泪史:v-model 的 .sync 陷阱,90% 升级项目都会踩
前端·vue.js
Cobyte6 小时前
19.Vue Vapor 的实现原理原来这么简单
前端·javascript·vue.js