Communitygithub.com

wensity/wensity-layout

使用间距比例、清晰分组、对齐、网格、容器、表格和响应式结构来布局 Web UI,适配从 320px 手机到宽屏桌面。在创建页面、区块、表单或仪表板布局,或更改 React、Next.js、Tailwind CSS 或 CSS 中的间距、对齐、网格、容器或响应式行为时使用。

wensity-layout 是什么?

Wensity Layout 是一个专注于 Web UI 布局的技能,它通过三大核心习惯——固定间距比例、按距离分组和统一对齐系统——来帮助开发者创建清晰、一致且具有响应式的页面布局。该技能适用于 React、Next.js、Tailwind CSS 或纯 CSS 项目,特别适合处理间距不协调、元素无法对齐、移动端布局断裂、或用户明确提到 padding、margin、gap、grid 等问题。 该技能提供了一个基于 4px 基础的间距比例表,从 4px 到 128px 共 13 个级别,并给出了每个级别的典型使用场景。它强调“组内间距小于组间间距”的核心规则,建议内外部间距比例约为 1:2 或 1:3。此外,还详细涵盖了容器宽度(从 prose 到 full bleed)、12 列网格系统、响应式结构(移动优先,根据内容而非设备设置断点)、表格布局、密度控制、触摸目标(44x44px)、z-index 分层、sticky 和 fixed 元素处理等完整布局体系。 该技能特别强调实际验证,提供了最终的检查清单,包括确保所有间距值基于 4px 比例、组内间距明显小于组间间距、段落宽度限制在 65ch 左右、移动端结构重组而非简单缩放、无水平滚动、触摸目标至少 44px 等关键检查点。它被设计为在创建页面、区块、表单或仪表板布局时自动触发,并会在用户提到与布局相关的任何术语时主动提供帮助。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/wensity/skills/tree/HEAD/skills/wensity-layout

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

Wensity Layout

布局是一种方式,让页面在人们阅读任何文字之前,就能告诉他们什么重要、什么属于一起。好的布局来自三个习惯:固定的间距比例、按距离分组,以及统一的对齐系统。本技能会建立这三个习惯,并涵盖响应式结构。

如果项目已经有间距比例和容器宽度,请使用它们。

1. 间距比例

使用 4px 作为基准。每个 margin、padding 和 gap 都来自这个列表:

值px典型用途
14图标到标签,紧凑的内联间距
28控件内部,标签与其输入框之间
312密集列表中的项目之间,按钮垂直内边距
416卡片内边距(紧凑),相关控件之间的间距,移动端页面边距
520按钮水平内边距(大)
624卡片内边距,表单字段之间的间距
832区块内群组之间
1040区块标题与其内容之间(大)
1248移动端区块内边距
1664应用内区块之间,平板端区块内边距
2080
2496桌面端营销页面区块内边距
32128英雄区域内边距,一个大陈述周围的空间

Tailwind 的默认比例已经遵循 4px 基准(p-4 是 16px),所以请使用它的步长,不要发明 p-[13px]。只有在渲染时检查过视觉校正(例如图标看起来偏了 1px)的情况下才允许使用奇数值。

2. 按距离分组

最重要的布局规则:组内间距小于组间间距。 标签距离其输入框 8px;下一个字段距离 24px。卡片标题距离其文本 8px;下一张卡片距离 24px。当内部和外部间距相等时,所有内容都会漂浮散开,无法形成分组感。

  • 目标是将内部和外部间距的比例控制在 1:2 或 1:3 左右。
  • 标题上方留出更多空间,下方留出更少空间。 标题属于其后的内容。典型:标题上方 48px,下方 16px。
  • 在盒子之前先考虑间距。 先通过距离进行分组。只有当距离不够时(如密集表格、工具栏、复杂背景上的内容),才添加边框、分割线或背景。给每个分组都加盒子会使页面显得沉重。
  • 使用 gap 处理同级元素(flex gap-4、grid gap-6),而不是给子元素加 margin。这能保持间距集中管理,并避免列表端部出现多余的 margin。

3. 节奏,而非雷同

如果一个页面的每个区块都有 96px 内边距、一个居中的标题和一个三列网格,那它就毫无节奏可言。有目的地变化密度:

  • 将密集的区块(功能网格、表格、标志)与开放的区块(一个陈述、一张大图)交替排列。
  • 让重要的区块占据更多空间。空间是你分配注意力的方式。
  • 只有当内容确实是同类事物时才重复布局。

4. 对齐

  • 一个起始边。 一个区块内的标题、段落、按钮和图像共享同一起始线。大多数“看起来不对劲”的抱怨都源于两条线相距几像素。
  • 默认从起始边对齐(text-align: start,在英文中为左对齐,在阿拉伯语或希伯来语中为右对齐)。仅居中简短、独立的内容:英雄标题、单个 CTA 块、空状态。表单、表格、列表和较长的文本都从起始边对齐。
  • 表格和统计列中的数字靠右对齐。
  • 按文本对齐,而非按盒子对齐。 图标旁边的标签应与标签的 cap-height 或中心对齐,而非与行框顶部对齐。在 flex 行中,单行使用 items-center;多行文本则使用 items-start,并在图标上添加一个小的顶部 margin。
  • 视觉校正: 播放图标、箭头和圆形形状在数学上居中时看起来会偏。在看到效果后,将其微调 1 到 2px。

5. 容器和宽度

容器最大宽度用途
Prose65ch(约 640 到 720px)文章、文档、长段落
Narrow560 到 640px表单、登录、聚焦任务、居中的英雄陈述
Content1120 到 1280px大多数营销区块和应用页面
Wide1440 到 1600px仪表板、画廊、编辑器
Full bleed100%背景、图像、应与边缘接触的产品展示图
  • 页面边距: 手机端 16px,平板端 24px,桌面端 32 到 48px。保持一致:整个站点每个断点只用一个边距值。
  • 将背景与内容宽度分开。 区块的背景可以全宽铺开,而其内容保持在内容容器内。
  • 在宽屏上不要让文本占满全宽。 图像和网格可以扩展,段落不行。

6. 网格

  • 营销布局用 12 列 可以获得一半、三分之一、四分之一以及不对称分割(7 和 5,8 和 4)。不对称分割看起来比 6 和 6 更有设计感。
  • 卡片使用自动填充网格,使列数跟随空间变化:
.cards { display: grid; gap: 24px; grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr)); }

min(100%, 280px) 可防止在窄于 280px 的屏幕上溢出。auto-fill 在只有一两张卡片时能保持卡片宽度稳定;auto-fit 则会拉伸卡片以填满行。根据需要选择。

  • 让灵活轨道能够收缩。 默认情况下,Grid 和 flex 子元素拒绝收缩到其内容大小以下,这就是为什么长文本或宽表格会溢出仪表板。对灵活轨道使用 minmax(0, 1fr),对包含文本的 flex 子元素使用 min-width: 0(Tailwind min-w-0):
.app-shell { display: grid; grid-template-columns: 16rem minmax(0, 1fr); }
.row > .text { min-width: 0; }
  • 仅对内容等高的元素使用等高。 默认情况下,一行中的卡片会拉伸到最高卡片的高度。这对于一组计划(价格比较)是可以的;但当一张卡片显然是特色卡片时就不对了。
  • Bento 网格: 根据重要性改变瓦片大小,保持一个间距值,并给每个瓦片分配真实内容。空的装饰性瓦片看起来像模板。
  • 使用 subgrid(grid-template-rows: subgrid)当一行中的卡片需要其标题、正文和按钮互相垂直对齐时。

7. 响应式结构

移动端优先设计,然后随着空间增加添加结构。

  • 断点跟随内容,而非设备。 在布局开始看起来不对劲的地方添加一个断点。Tailwind 的 sm 640、md 768、lg 1024、xl 1280 是很好的默认值。
  • 重组结构,而非仅仅缩小。 在移动端,三列功能网格变为一列,并排的文本和图像堆叠且图像放在后面(如果图像承载信息则放在前面),表格变为卡片列表或在其容器内水平滚动,侧边栏变为抽屉。
  • 对出现在不同宽度的组件使用容器查询(例如侧边栏和主列中的卡片):
.card-wrap { container-type: inline-size; }
@container (min-width: 480px) { .card { grid-template-columns: 160px 1fr; } }

在 Tailwind v4 中:父元素上使用 @container,子元素上使用 @md:grid-cols-2。

  • 根据屏幕缩放间距。 区块内边距:移动端 48px,平板端 64px,桌面端 96px。间距可以从 16 到 24 再到 32 逐步变化。
  • 视口高度: 对于全高布局,使用 min-h-dvh(或 100dvh),而不是 h-screen(100vh)。在带有工具栏的移动浏览器上,100vh 比可见区域更高,因此内容会隐藏在其下方。
  • 带刘海手机的安全区域: 固定底部栏使用 padding-bottom: env(safe-area-inset-bottom),并在视口 meta 标签中使用 viewport-fit=cover。
  • 从右到左的语言: 使用逻辑属性(margin-inline-start、padding-inline、inset-inline-end;Tailwind ms-*、pe-*、start-*)替代 left 和 right,并使用 dir="rtl" 进行测试。镜像方向性图标(返回箭头、尖角符),但不要镜像标志或所有图标。
  • 永远不要出现水平页面滚动。 在 320px 宽度下检查。常见原因有:固定宽度、长单词或 URL、w-screen 元素(包含滚动条宽度)、或负 margin。

8. 表格

  • 表头行 扮演标签角色,当表格滚动时使用 sticky(position: sticky; top: 0),并设置带色调的背景或更强的底部边框。
  • 行高按密度: 紧凑型 36px,默认型 44px,舒适型 52px。当用户需求不同时,提供一个切换选项。
  • 行之间通过细线分隔或斑马纹分隔,不可同时使用。
  • 数字使用 tabular-nums 靠右对齐;文本靠左对齐;状态和操作放在最后几列。
  • 移动端的宽表格: 在其自身容器内水平滚动(overflow-x: auto),第一列 sticky;或者切换到每行堆叠的卡片。绝不能让表格将页面推向侧面。
  • 空状态、加载状态和错误状态 位于表格框架内部,保留表头,以便用户知道即将显示什么。

9. 密度

根据屏幕的使用频率匹配密度:

  • 营销和引导: 开放。每屏项目少,间距大,字号大。
  • 日常使用的应用屏幕: 紧凑。行高 36 到 44px,间距 8 到 12px,字号 14px。每天使用同一屏幕的人希望一次看到更多内容。
  • 表格和数据工具: 密集,如果用户需求不同则提供密度切换。
  • 不要在一个面板内混合不同的密度。

10. 触摸目标和点击区域

  • 任何可触摸点击的元素,目标尺寸至少 44x44px,即使可见图标只有 16px。(WCAG 2.2 AA 要求至少 24x24px;44px 是舒适尺寸。)通过 padding 增大点击区域,或者使用一个以控件为中心的不可见伪元素,这样布局不会改变:
.icon-btn { position: relative; }
.icon-btn::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: max(100%, 44px); height: max(100%, 44px);
  transform: translate(-50%, -50%);
}
  • 单独的触摸目标之间至少要有 8px 间距,以免拇指同时点到两个。

11. 层级

保持一个小型的 z-index 范围,并且只使用这些值:

:root { --z-dropdown: 10; --z-sticky: 20; --z-overlay: 30; --z-modal: 40; --z-toast: 50; --z-tooltip: 60; }

使用 showModal() 打开的本地 <dialog> 以及具有 popover 属性的元素会渲染在浏览器的顶层,高于所有 z-index,因此它们不需要设置 z-index。z-index: 9999 意味着堆叠上下文未被理解。应该修复堆叠上下文(通常是父元素上意外的 transform、filter 或 isolation),而不是提高数值。

12. Sticky 和固定元素

  • Sticky 头部:保持简短(56 到 64px),并且仅在页面滚动到其下方时才给它们添加背景(实色或模糊),这样页面顶部保持干净。
  • 在被锚定的标题上添加等于头部高度的 scroll-margin-top,以便页面内链接不会落在头部下方。
  • 移动端的固定底部栏需要上述的安全区域 padding,并且不能覆盖页面上的最后内容;页面底部应填充等于该栏高度的内边距。

13. 完成前检查

  • 每个间距值都在 4px 比例上。
  • 组内间距明显小于组间间距。
  • 标题上方空间多于下方。
  • 每个区块有一个起始边;表格中数字靠右对齐。
  • 灵活轨道使用 minmax(0, 1fr);文本子元素可以收缩。
  • 即使在大屏上,段落宽度也限制在约 65ch。
  • 移动端布局会重组结构,而不仅仅是缩小。
  • 320px 宽度下没有水平滚动;全高区块使用 dvh。
  • 触摸目标至少 44px(绝不小于 24px)。
  • z-index 值来自定义的范围。
  • 眯眼测试:最重要的内容和分组在模糊细节后仍然清晰可辨。

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

相关技能