Community图像github.com

nkurunziza-saddy/layout

为Web产品UI提供结构和间距。定义间距尺度、分组、对齐、密度(紧凑或舒适)、点击区域、应用外壳(侧边栏、工具栏、内容区、检查器)、最大宽度、容器查询响应式、下拉菜单和弹窗尺寸、长文本和翻译文本预留空间、布局稳定性(加载时无偏移)以及不能遮挡焦点的粘性元素。

layout 是什么?

该技能为产品UI的布局和间距提供了一套结构化、可重复的决策系统。它规定了间距、对齐、密度和外壳布局的明确规则,确保UI在不同屏幕尺寸和容器下的视觉一致性与功能性。技能强调使用固定的4px基准间距尺度,并通过优先级排序(外壳、宽度与度量、间距、对齐、尺寸、最坏情况数据、自适应、测量)逐步构建布局。为了提升可访问性和稳定性,它强制要求逻辑属性、DOM顺序,并禁止间距值偏离既定尺度。该技能适用于任何Web项目,并提供了清晰的参考文档,用于检查间距正确性、点击区域最小尺寸、容器查询、逻辑属性使用,以及如何通过渲染像素测量来验证布局。

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

Installed? Explore more 图像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜欢的 AI 中提问

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

文档

布局

本技能决定元素放置的位置、彼此相隔多远以及它们的大小。它以相同的顺序做出相同的决策,并根据渲染后的像素检查结果。

在做出任何决策之前,请应用 product-ui §1(品味日志和优先级)和 §5(哪项技能拥有什么)。

按此顺序决策

  1. 外壳。 命名屏幕区域:侧边栏、工具栏、内容区、检查器。每个区域要么是一个滚动容器,要么不是。详细信息和宽度:shell-and-responsive.md。原因:外壳决定了内部布局必须适应的所有宽度。
  2. 宽度和度量。 根据内容设置内容列:表单440px,阅读720px且正文限制为type度量(66ch),数据1200px。列永远不会因为屏幕宽而拉伸。原因:超过75个字符的行会失去读者,拉伸的表单会让眼睛在屏幕上扫来扫去。
  3. 间距。 仅使用下面的尺度,不使用其他。先用间距分组;在间距无法承载时,再添加填充,然后是分割线。spacing-and-density.md。
  4. 对齐。 选择共享的边缘,将所有内容对齐到其上。1-4px的偏差是一个错误。在视觉看起来不对的地方进行光学校正。spacing-and-density.md。
  5. 尺寸。 选择该区域的密度,然后是点击区域的大小。spacing-and-density.md。
  6. 最坏情况数据。 在完成前,根据最长、最短、缺失、翻译后和仍在加载的内容调整盒子大小。stability-and-text.md。
  7. 自适应。 使结构响应其容器,而不是设备。shell-and-responsive.md。
  8. 测量。 以2倍率渲染,测量间隙和边缘,修复像素显示的问题。measure.md。

尺度

一个尺度,4px基准。永远不要写一个不是步进值的间距值。原因:一次性值(10px, 14px, 18px)使节奏无法察觉和保持。

Tokenpx典型用途
--space-xs4标签到其描述;图标到标签(在chip组件中)
--space-sm8组内项目;控件内边距(块方向)
--space-md12带边框的控件之间;控件内边距(内联方向)
--space-lg16字段之间;紧凑卡片边距
--space-2020卡片内的块之间
--space-xl24组之间;舒适卡片边距
--space-2xl32区域之间
--space-3xl48页面第一个标题上方
--space-4xl64页面最后一个块下方

用于光学对齐的1-2px微调是唯一不在该尺度上的值。命名它们(--play-nudge: 2px)。

无需参考文档的规则

  • 用间距分组。 组之间的间隔至少是组内间隙的2倍:内部8px意味着外部16px或更大。处处间距相等会导致分组模糊,而模糊在这里是一个功能性错误。
  • 在添加分割线之前移除它们。 首先是间距,其次是填充,最后才是分割线,并且仅用于密集数据。原因:每一条线都会消耗注意力,但间距免费提供了相同的信息。
  • 两样东西之间的间距上方等于下方。 原因:更靠近某个邻居的东西会被读作属于它。
  • 控件必须看起来像控件。 按钮、链接或开关具有形状、下划线或工具栏位置。静态文本从不共享这些特征。原因:样式像文本的控件会隐藏,而样式像控件的文本会招来无效点击。
  • 操作位于其操作的数据之上,绝不位于下方。设置某物的控件应紧邻它。
  • 主要内容优先并且位于起始侧。 视觉顺序等于DOM顺序:永远不要使用 order、row-reverse 或grid placement来重新排序内容。原因:键盘和屏幕阅读器的顺序遵循DOM。
  • 对于需要镜像的场景,使用逻辑属性(margin-inline-start、padding-block、inset-inline-end、text-align: start)。原因:无需第二张样式表即可支持RTL。
  • 绝不要将关键控件放在窗口或侧边栏的底部边缘。 原因:人们会部分地将窗口推出屏幕。
  • 滚动显示被隐藏的内容。 超出边缘的内容要有可见的提示:16-32px的露头或渐变淡出。
  • 没有任何东西会移动。 悬停、选择和聚焦永远不能改变元素的大小。已加载的数据占据骨架所占据的盒子。

正反例对照

错误做法正确做法原因
表单内 gap: 12px,其字段集之间也是 gap: 12px内部 gap: 8px,之间 gap: 24px组需要至少2倍的间隔
padding: 10px 14pxpadding: var(--space-sm) var(--space-md)仅使用步进值
标题在 x=24,描述在 x=26两者都在 x=241-4px的偏差看起来像错误
图标按钮 16×16 且 padding: 016px 图标,::before { inset: -12px } 以获得 40px 目标鼠标目标应为 40px
.row + .row { margin-top: 8px } 且行上有悬停和点击.row { padding-block: 4px },无 margin行之间的间隙是死区,并使悬停闪烁
.menu { width: 200px }width: max-content; min-width: 160px; max-width: 320px菜单贴合其最长标签
卡片上使用 @media (max-width: 768px)卡片父元素上使用 @container (width < 400px)窄侧边栏中的卡片需要自己的宽度,而不是屏幕的宽度
<img src> 没有尺寸,然后卡片跳动设置 width、height 或 aspect-ratio盒子在字节加载之前就已存在
粘性标题,锚点落在它下面滚动容器上设置 scroll-padding-block-start: 56px焦点和锚点绝不会落在chrome下面

完成前

在diff中搜索这些模式,然后验证。

模式修复
margin、padding 或 gap 的值不在尺度中最近步进值
组内和组间使用了同一个 gap 值组内 ≤ 组间一半
仅图标按钮小于24px,或小于40px且无 ::before使用伪元素扩展
可点击行或菜单项之间的 gap 或 margin项内的内边距
菜单、按钮或文本框上的固定 widthmax-content、min-width、max-width;文本使用 min-height
可复用组件内的 @media (max-width父元素上的 @container
外壳使用 height: 100vh100dvh
持有长文本的 1fr 轨道或flex子项minmax(0, 1fr) 或 min-width: 0
镜像UI中的 margin-left、padding-right、left: 0、text-align: left逻辑形式
未设置 scroll-padding-block 的粘性页眉或页脚设置为其chrome的高度
骨架行高或列宽与加载后的不同匹配它们
无尺寸或 aspect-ratio 的 <img>添加一个

使用 measure.md 验证:以2倍率分别在390px宽度和外壳最宽宽度下渲染,运行脚本,裁剪每个候选项并计算像素。然后在存有粘性chrome的屏幕上Tab浏览,并加载最长的字符串。报告你无法检查的内容为“未验证”。

Individual skills in this repo

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

nkurunziza-saddy/break

Stress-tests a piece of UI with worst-case data and every reachable state, then reports what broke with a numbered fix for each. Use it when the user types /break, or asks to "break this", "stress-test", "try the worst case", "what happens with long names", "check the empty and error states" or "find the edge cases" on a component or screen.

nkurunziza-saddy/motion

Builds motion for product UI on the web. It decides whether something should move at all, then why, which tool (CSS transition, WAAPI, Motion, spring), which properties, curve, duration, interruption, exit and reduced-motion path, and it writes the code. Also covers stagger and choreography, gestures (drag, flick, sheets), motion tokens and animation performance.

nkurunziza-saddy/pick-library

Picks the right library for a frontend task from a curated, status-checked list, instead of hand-rolling it or installing an abandoned package. Use it when the user asks "what should I use for…", "is there a library for…", or names a package, and when you are about to build a toast, command menu, drawer, date picker, table, virtual list, drag and drop, chart, OTP input, animated number, theme switch, form validation…

nkurunziza-saddy/surfaces

What product UI is made of on the web. It sets elevation levels with exact shadow recipes for light and dark mode, when to use a shadow and when a border, the transparent border for forced-colours mode, a small radius scale with concentric nesting, image outlines, every interactive state as a surface change (hover, pressed, selected, disabled, focus-visible), icons (one set, currentColor, outline and fill, stroke tha…

相关技能