布局与自适应
工具类是一条玻璃侧栏加内容区,按1440等比放大、900收顶栏、600换底部tab bar;小屋是一屏名片、一条轨道和一条日记流,内容容器一律不写高度。演示框都是「缩小的视口」:拖宽度、拖高度、切写法,读数是当场量出来的。
小屋 · 暖纸
小屋的六条原则里有一条就是「零固定高度」:内容多就往下长,内容少就居中留白。门厅是一张一屏名片,工具页是一条轨道上叠着的五层,随笔是一条日记流。断点是桌面优先的max-width 900 / 820 / 680 / 560。图是小屋的原画,按相对路径从老站引来。
门厅一屏名片:整张卡挂在一个长度变量--card-u上,长宽比恒定1.8348
卡宽按两条法则取小——宽度法则跟视口宽、高度保险最多吃掉可用高的72%——再夹在440到900之间。所有装裱尺寸写成calc(<1440×900下的像素值> * var(--card-px)),巨字、内边距、右半宽同源,缩放的永远是同一张卡。
演示拖宽、拖高,或点预设。现行按--card-u算;「旧」是冻结小样里三样各吃一条vw clamp的写法(示意),看长宽比怎么漂。画是小屋门厅原画。
数值 / 代码
@media (min-width: 821px) {
.hall {
--card-room-h: calc(100svh - 66px - clamp(24px, 4svh, 52px) - clamp(44px, 8svh, 88px));
/* 小屋代码现状写的是4vh / 8vh(裸 vh);按「裸 vh 不许」该换 svh,还没改 */
--card-u: clamp(440px,
min(calc(0.3514 * 100vw + 202.064px), calc(1.3231 * var(--card-room-h))),
900px);
--card-px: calc(var(--card-u) / 708.08); /* 「一个 1440×900 像素」,那一档正好1px */
}
}
.blob__big { font-size: calc(136 * var(--card-px)); } /* 系数就是1440×900下的像素值 */
.blob { padding: calc(58 * var(--card-px)) calc(64 * var(--card-px)) calc(52 * var(--card-px));
width: fit-content; } /* 色块宽由两个字撑出来 */
.plate { width: calc(281.6 * var(--card-px)); padding: calc(15.84 * var(--card-px)); }
.hall__card { border-radius: calc(46 * var(--card-px)); }
宽度法则过两点(1030→564、1440→708.08);高度保险 = 卡最多吃掉可用高的72%;
上界900是画的分辨率(源图636宽);下界440。1px 发丝线、倾斜角、字距行高不缩放。
用在哪
小屋门厅,以及工具页、随笔页门面那两张同款卡(两份样式表逐字相同)。门厅首屏就是这张卡,静态档(没有JS、减弱动效、≤900、省流量、WebGL不可用)是一屏、不能滚。≤820那一档不认--card-u,见下一条。
为什么
以前巨字、内边距、右半宽各吃一条斜率不同的vw clamp,卡越小越方(长宽比1.868→1.746),缩放的不是同一张卡。现在一个自由量,1440×900按定义逐像素不变;矮窗口里高度保险接手,1440×460以前溢出视口15.9px,现在卡片自己收到440.8×241、离底还有86px。
「不全屏的时候比例怪」
坑
宽度法则的斜率与截距是配着挑的:1440那一档必须算出整708.08,708.0806时挂画投影的负扩散-14.0000119px会被1/64的布局单位取整成-14.0156px,投影那一圈就有3万个像素对不上。禁止给色块、右半写固定宽高或aspect-ratio,也不给整张卡写任何尺寸——它只是装裱层。
出处:Ysevan_web/docs/xiaowu-ui-spec.md「1.1 定位」(「不能滚动的一屏」)、「4.2.1 --card-u:一个长度变量」(「斜率与截距是配着挑的」「长宽比因此恒定 1.8348」)、「4.3 fit-content 机制」(「三样同源」)、「4.6.3 同高与不裁切机制」(「独立决定」);Ysevan_web/app/hall.module.css「--card-u」;旧写法 Ysevan_web/docs/design/xiaowu-mockup.html「.blob」、「.plate」、「.blob__big」
窄屏也保持左右两半的横构图,整张卡等比收小,不上下堆叠
≤820时右半先由一条更陡的clamp定宽(clamp(100px, 30vw, 206px)),色块吃掉剩下的全部;巨字改吃11.5vw并且不许折行。320宽也还是一张挂画。
演示拖视口宽(320–820),数值是规格里≤820那一档的原值。切到「上下堆叠」看被否的那个样子(示意,照被否方案的max-height: 300px)。
数值 / 代码
@media (max-width: 820px) {
.blob { flex: 1 1 auto; min-width: 0; width: auto; /* 定尺寸策略反过来:右半先定,色块吃剩下的 */
padding: clamp(20px, 5.6vw, 40px) clamp(12px, 3.8vw, 34px) clamp(18px, 4.6vw, 34px); }
.blob__whose { font-size: clamp(10.5px, 3vw, 13px); letter-spacing: .16em; margin-bottom: 6px; }
.blob__big { font-size: clamp(40.25px, 11.5vw, 84px); white-space: nowrap; }
.blob__foot { margin-top: clamp(12px, 3.4vw, 22px); padding-top: clamp(10px, 2.6vw, 16px);
font-size: clamp(10.5px, 3vw, 13px); letter-spacing: .04em; }
.plate { width: clamp(100px, 30vw, 206px); padding: clamp(6px, 1.8vw, 10px); }
.hall__card { border-radius: clamp(20px, 5vw, 30px); }
.deco--pot { display: none; } /* 往卡外挂的盆栽在窄屏收起 */
}
用在哪
小屋门厅与两个门面,≤820。≤560没有门厅相关的进一步收小档:上面这些clamp的下界(40.25px巨字、100px右半、20px圆角)已经兜住320宽。巨字下限和副标题字距是2026-10-08第二轮定的(原来38px、.08em):门面副标题「六件自己做的东西」8个字,.08em时窄屏只放得下7个、把色块撑宽。
为什么
原方案≤820转纵向(色块上、画下),屋主否了。那幅水彩是636×900的竖幅,窄右半正合适;一转纵向,画横过来铺满卡宽,要靠max-height硬砍高度,门厅从「一张挂画」变成「一张海报压着一块色块」。
坑
色块的min-width:0不能省:没有它flex子项的最小宽是内容宽,色块压不下去,卡片顶破容器。巨字的nowrap是硬约束:「小屋」断成两行会把卡顶高、把右半的画连带拉长。≥821起换成--card-u,两个媒体查询之间(820, 821)有一条缝(浏览器缩放会把视口宽算成小数),旧的clamp作为基础声明保留着兜底,不能删。
出处:Ysevan_web/docs/xiaowu-ui-spec.md「10.1 @media (max-width: 820px) —— 门厅卡片等比收小」(「2026-08-26 用户裁定改写」「色块的定尺寸策略反过来」「巨字改吃」「≤560px 没有门厅相关的进一步收小档」「≥821px 起换成 --card-u 单一法则」);Ysevan_web/app/hall.module.css「.blobBig」(「clamp(40.25px, 11.5vw, 84px)」「字距 .04em」)
工具页一条轨道、一个钉住的舞台,五层叠在同一格里交接
门面和四个工具叠在舞台的同一个网格格子里,滚动只往轨道上写一个进度,每层按时间表算自己的入场、停留、退场。相邻两层的淡入淡出叠在一起,任何一刻至少有一件东西看得见;最后一层不退场,轨道正好停在它停留结束的地方。
演示在框里上下滚(键盘:Tab进框后用方向键、PageDown),或拖下面的滑块。时间表是规格原值,框高就是「一屏」;条形是每一层此刻的在场程度,接指针的那层标着点。工具文案是示例,门面是工具页原画。
一屏一屏要滚多远(1440×900实测,规格里的数;示意)
改前:每件一段5916px
现在:一条轨道2514px
实色=有一件完全显示,斜纹=交接中,空白=什么都看不见。改前三段交接各约103svh是空白的纸,现在没有。
数值 / 代码
轨道 .rail { min-height: calc(100svh + var(--rail-end) * 1svh); } /* --rail-end = 最后一层的 hold-end = 352 */
舞台 .stage { position: sticky; top: 0; min-height: 100svh; display: grid; } .layer { grid-area: 1 / 1; }
时间表(单位 svh;d = 滚进轨道的距离,轨道顶碰到视口顶为0)
门面:0 → 12(没有入场) 01 · 日程安排:52 → 112 02 · 刷刷:152 → 192
03 · 岗岗:232 → 272 04 · card:312 → 352(最后一层:hold-end 就是轨道终点,不退场)
淡入淡出 右栏 --fade 32、文案 --copy-fade 22、门面退场 (32 + 22) / 2 = 27
入场 t = clamp(0, (d − hold-start) / fade + 1, 1);退场 t = clamp(0, (d − hold-end) / fade, 1)
两条都过 smoothstep(两端零速度;不用 ease-out,它起点最快,一碰滚轮内容就往上窜)
在场 present = enter × (1 − exit)
位移 文案 translateY((1 − enter) × 26px − exit × 26px);图 (1 − enter) × 42px − exit × 34px
接指针 只有 data-tool-active 那层(present 最大的;交接正中打平时给后一层),其余 pointer-events: none
进度 脚本只写一个 --rail-progress(0 → 1),几何全在样式表
用在哪
小屋/projects的「展台」(有3D展品的四件)。没有3D展品的travel与设计合集不进轨道,摆在轨道之后的「小架」上(2026-09-28),舞台放开后接着滚到,小架最后一件就是页底。每个工具只有「打开」那一条链接可聚焦,见交互页「每个工具恰好一个Tab位」。
为什么
改前门面和三个工具各占一段、每段一个自己的舞台,「上一件完全显示→下一件完全显示」要滚142svh(1440×900下1278px),中间约一屏是空白的纸,屋主反馈切换不自然、间距太长。一条轨道之后交接只要40svh,两套文案只在交接正中4svh里同时出现、且都淡到0.025以下。最后一层的退场从hold-end起算,轨道到不了那之后,所以它结构上就不会退场。
「滚到最后一件就不用再往下拉了」
坑
叠放的层透明了也照样接指针:五层叠在同一格,最上面那层(card)会吃掉底下所有的点击——点着日程安排的「打开」,打开的是card。所以叠放那一档默认pointer-events:none,只有在场的那层接。时间表写成纯数字、每层按名字取,脚本才读得出来(写成calc()链,读到的是字符串"calc(12 + 40)")。
出处:Ysevan_web/docs/xiaowu-ui-spec.md「6. 工具页 /projects」(「2026-09-04 屋主裁定整节重写」)、「6.2 结构」(「切换不自然」)、「6.3 数值」(「轨道时间表」「右栏淡入淡出」「文案淡入淡出」「轨道高」「文案位移」「接指针」「smoothstep」「最后一层为什么不退场」)、「6.4 五个不会报错的坑」(「叠放的层透明了也照样接指针」)
默认样式就是一张竖排页,叠放、钉住、擦洗只写在(scripting: enabled)媒体查询里
同一份标记不加任何增强就是一张能读的竖排页:门面、四个工具、小架依次排下来。只有脚本能跑、宽于900、没开减弱动效三条同时成立,才在媒体查询里把它们叠起来。
演示拨三个环境开关(示意:真的媒体特性改不了,这里按同样的条件算),再切两种写法,看一个访客打开工具页第一眼能看到几件工具。最下面一行是这台浏览器真实的scripting结果。
Ysevan的 工具门面
01 · 日程安排打开日程安排
02 · 刷刷打开刷刷
03 · 岗岗打开岗岗
04 · card打开card
数值 / 代码
/* 默认:竖排页,不钉住、不擦洗;三张界面图竖排 */
.layer { … }
/* 增强只写在这一个媒体查询里 */
@media (scripting: enabled) and (min-width: 901px) and (prefers-reduced-motion: no-preference) {
.rail { min-height: calc(100svh + var(--rail-end) * 1svh); }
.stage { position: sticky; top: 0; display: grid; }
.layer { grid-area: 1 / 1; pointer-events: none; }
.layer[data-tool-active] { pointer-events: auto; }
/* 时间表的数字也只写在这里:竖排页读到的是 NaN,读法返回 null,意思就是「此刻没有叠放」 */
}
用在哪
小屋工具页(tools.module.css文末那一个媒体查询)。禁用脚本、不认scripting这个特性的老浏览器、窄屏、减弱动效四种情况,第一帧就是这张竖排页。
为什么
页面里不另写内联脚本(CSP的script-src只认构建时逐页算出的sha256哈希),「脚本能不能跑」只能交给scripting这个媒体特性来判。增强是加上去的一层:判断不出来、条件不满足,留下的就是能读的那一页——小屋「降级的终点就是今天那一页」同一个思路。
坑
反过来写(默认钉住擦洗、再用媒体查询撤掉):窄屏和减弱动效撤得掉,禁用脚本却没有对应的查询能撤——宽屏访客停在进度0,而进度0时几个工具的present都是0。2026-09-20以前就是这样:无JS的1440宽访客只看得见门面,下面几个工具左栏、右栏的有效不透明度全是0(实测)。
出处:Ysevan_web/docs/xiaowu-ui-spec.md「6.2 结构」(「叠放、钉住、擦洗全部写在一个媒体查询里」「只认构建时逐页算出的哈希」)、「6.3 数值」(「时间表只写在叠放那一档里」)、「6.4 五个不会报错的坑」(「默认样式必须是竖排页」)、「3.5 CSP 约束」(「sha256」);Ysevan_web/app/projects/tools.module.css「@media (scripting: enabled)」
随笔是iCity式日记流:一条一张卡,靠间距分隔,正文不截断
一张卡就是一条日记:左上签名、右上日期与年份、中间正文、底行天气心情地点与时间。没有标题、摘要、时间竖线,卡与卡之间不画线。页面两栏,左栏按内容自然宽、280封顶,≤900塌成单列。
演示拖宽度看两栏怎么塌成一列、左栏怎么跟着说明的长短变宽;切到「旧列表」看被换掉的样子(示意)。三条随笔是示例;左栏的长句是现行那句,短句是示意。签名头像在站上是一张小图,这里只画它的底色块。
Ysevan10月8日 · 星期四2026
下午把工具架上的卡片又对了一遍,左右两半终于等高了。
晚上下了点雨。
雨 · 平静 · 家里
Ysevan10月6日 · 星期二2026
今天只做了一件事:把一条很长的路走完。
晴 · 有点累 · 路上
Ysevan10月2日 · 星期五2026
( ˘ω˘ ) 放假第二天,睡到自然醒。
多云 · 开心
关于卡片对齐的一点记录下午把工具架上的卡片又对了一遍,左右两半终于…
2026-10-08
走完一条很长的路今天只做了一件事:把一条很长的路…
2026-10-06
放假第二天( ˘ω˘ ) 放假第二天,睡到自然…
2026-10-02
数值 / 代码
.notes { display: grid; grid-template-columns: fit-content(280px) minmax(0, 1fr);
gap: clamp(30px, 4.4vw, 60px); align-items: start; }
@media (max-width: 900px) { .notes { grid-template-columns: minmax(0, 1fr); } } /* 日记卡本身没有断点 */
#entries { display: flex; flex-direction: column; gap: clamp(12px, 1.6vw, 16px); } /* 靠间距分隔,没有发丝线 */
.entry { background: #FDFCF9; border: 1px solid var(--border); border-radius: 14px;
padding: clamp(14px, 1.8vw, 20px) clamp(16px, 2.2vw, 22px); }
.entryAvatar { width: 30px; height: 30px; border-radius: 9px; } /* 头像是图(2026-09-02起),图挂了露色块底 */
.entry__day { color: var(--xw-lava); } /* 「10月8日 · 星期四」,熔岩橙 */
.entry__text { white-space: pre-wrap; overflow-wrap: anywhere; } /* 纯文本直出,不截断、不做摘要 */
没有卡内分隔线、阴影、标题、摘要
用在哪
小屋/notes。正文的段首缩进、行距这些排法归排版章(随笔「中文论文排法」)。
为什么
旧列表「标题+摘要+时间竖线」把随手写的一句话包装成文章,读起来像博客归档,不像屋主自己的本子。左栏fit-content(280px):说明一句话时左栏就窄,换成长句就长到280封顶,永远不为凑一个固定宽度留空白。正文不截断:卡上唯一的链接是右上那块日期,它已经是「进详情页」的意思,再截断就得再造一个「展开」开关。
坑
签名行(头像+Ysevan)是一条日记的落款,不是自我介绍,不违反小屋「无自我介绍」那条红线;别因为红线把它删了。头像起初是楷书「屋」字,2026-09-02起是一张小图。左栏原来有标题「随笔本」,2026-09-05加了门面之后标题交给门面,左栏只留一句说明和两条小链接。
出处:Ysevan_web/docs/xiaowu-ui-spec.md「7. 随笔页 /notes」(「框架对齐 iCity」「签名行」)、「7.1 两栏网格」(「左栏 fit-content(280px)」「≤900px 时塌成单列」)、「7.4 日记流」(「一张卡就是一条日记」「public/avatar.jpg」)、「3.4 各页用字对照」(「随笔签名头像」)、「7.6 随笔正文的排法 › 列表卡:按空行切段,不截断」(「为什么不做」);Ysevan_web/app/notes/page.tsx「多半是工作里的琐事,偶尔是折腾工具的记录。」;Ysevan_web/app/notes/notes.module.css「.entryAvatar」
零固定高度:内容容器一律不写高度,内容多就往下长,内容少就居中留白
固定尺寸只给图形元件(顶栏的最小高、图标方块、头像、边框)。内容容器用min-height、fit-content、align-items: stretch、clamp()、minmax(0, 1fr);不许用overflow:hidden和固定行数省略去藏溢出。
演示一张工具卡(文案是示例)。换文案长短、换「字宽一点」(示意:同一段字在别的系统字体上更宽),再切到反例「写死高度+藏溢出」,读数是被藏掉的高度。
02刷题
刷刷
799题离线可用本机存储
打开刷刷
数值 / 代码
固定尺寸只在图形元件上:顶栏 min-height 66px(≤560 58px)、图标方块46 / 54 / 48、头像30×30、
边框1 / 2 / 3px、textarea min-height 108、<img width="636" height="900">
内容容器的手法:min-height(.shell { min-height: 100svh })、fit-content(色块、随笔左栏)、
align-items: stretch + max-height: 100%(画跟着色块取高)、clamp()(40余处)、minmax(0, 1fr)
禁止:内容容器上的 height、max-height;用 overflow: hidden 掩盖溢出;-webkit-line-clamp 固定行数省略;
position: absolute 摆主内容(只有绿植装饰可以);百分比 padding-bottom 撑宽高比
用在哪
小屋全站,六条原则第4条。全站唯一一处max-height是门厅画的max-height:100%——它不是限高,是「画跟着色块等高」那套机制的一部分。拿overflow:hidden藏溢出只有一个例外:body的overflow-x,用来兜住装饰;门厅卡上那个overflow:hidden是裁圆角,不是藏溢出。
为什么
内容会变:题库会加题、随笔会变长、工具说明会改写、字体在不同系统上宽度不一。任何一处写死高度,都会在某台设备上把字截掉或留一块死白。
坑
藏溢出的毛病看不出来:在写的那台机器上刚好装下,换一台字体更宽的机器、或者文案多一句,最后一行就悄悄没了,不报错。
出处:Ysevan_web/docs/xiaowu-ui-spec.md「1.2 六条原则」(「零固定高度」)、「11.1 零固定高度原则」(「除此之外,任何内容容器都不写高度」)、「11.2 禁止清单」、「11.5 为什么」(「内容会变」)
通用
两种气质都会碰到的:高度用哪种视口单位,以及一组都踩过、都不报错的布局陷阱。
高度单位按场景分:会滚的页面用svh,盖满可见区的浮层用dvh,封顶用svh,裸vh不许
手机地址栏一伸一缩,可视高差153px(屋主手机417宽:露着750,收起903)。页面本身会滚的——首屏、门面舞台、sticky舞台、滚动轨道长度——用svh,地址栏伸缩时不变;叠在页面上要正好盖满可见区的——全屏弹层、底部抽屉、整页不滚只在内部滚的应用外壳——用dvh;各种max-height封顶用svh,按最坏情况算;裸vh一律不许。
本站这里在用全站 · 更多面板
演示屋主手机417宽(示意)。切「地址栏露着 / 收起」,三种场景各两台:左边按规矩写,右边写错。①看手指底下的内容和滚动时间表跳不跳,②看底下露不露缝,③看抽屉顶上有没有被裁。三种场景都在页面已经往下滚了300px的时候看。
①页面会滚:首屏、sticky舞台、轨道长度
②盖满可见区:全屏弹层、底部抽屉、不滚的应用外壳
③封顶:长内容底部抽屉的max-height
内容尺寸:min(calc(540 × --u), calc(100svh − 其余各块)),例:卡集画廊的舞台,台式2040(--u 1.417)。可用高度那一项是封顶,按③用svh。
等比项540×u
可用高度项
写死69svh(被否)
数值 / 代码
/* ① 页面本身会滚:首屏、门面舞台、sticky 舞台、滚动轨道长度 → svh */
.hero { min-height: 100svh; }
.stage { position: sticky; top: 0; min-height: 100svh; }
.rail { min-height: calc(100svh + var(--rail-end) * 1svh); } /* 地址栏伸缩时长度不变,时间表不跳 */
/* ② 叠在页面上、要正好盖满可见区:全屏弹层、底部抽屉、整页不滚只在内部滚的应用外壳 → dvh */
.overlay { position: fixed; inset: 0; height: 100dvh; }
body.shell { height: 100dvh; overflow: hidden; } /* 页面不滚,只在里面滚 */
/* ③ 各种封顶 → svh,按地址栏露着的最坏情况 */
.sheet { max-height: calc(100svh - 40px - env(safe-area-inset-top)); }
/* ④ 裸 vh 一律不许:手机上它按地址栏收起时算(903),露着时多出153px压到屏幕外 */
/* 内容尺寸:等比项与可用高度项取小,可用高度是封顶,用 svh */
min-height: clamp(<下限>, min(calc(<系数> * var(--u)), calc(100svh - <这一屏上其余各块>)), <上限>);
用在哪
三种场景各用哪种单位、例子
| 场景 | 单位 | 例子 |
| ①页面会滚 | svh | 小屋门厅首屏、工具页的sticky舞台与452svh的轨道;本站的body最小高、侧栏 |
| ②盖满可见区 | dvh | 全屏弹层、底部抽屉的定位;card画廊整页不滚(body按100dvh排成一列、舞台flex:1吃剩余) |
| ③封顶 | svh | 「更多」面板、kit弹层、照片区的max-height;内容尺寸公式里的可用高度项 |
本站已照这四条改完(2026-10-08):body的最小高与侧栏只写svh,不再接一行dvh;「更多」面板、kit居中与底部弹层、照片区的封顶都是svh,原来的dvh、裸vh和100vh兜底行都删了。小屋2026-10-09也照这四条改完了规格和代码(规格11.6「视口单位的四条」,仓库里加了永久门禁)。
为什么
地址栏只在手机上滚动时伸缩。会滚的页面里用dvh,地址栏一收,首屏、舞台、轨道跟着长153px:手指底下的内容往下跳一截,按「滚了多少svh」写的时间表也被拉长、倒回去一段。盖满可见区的东西用svh,地址栏一收,底下就露出153px的缝,看得见后面的页面。封顶要在地址栏露着时也放得下,所以按小的那个svh算;裸vh手机上按地址栏收起时算,露着时就压到屏幕外。来历:两份记录原来说法相反——控制室记录(2026-09-23)写「一屏容器用100dvh、各种封顶用svh」,小屋规格写「占满一屏的容器用100svh、内容尺寸的兜底上限用100dvh」;控制室2026-10-08按场景定成上面四条:会滚的照小屋规格用svh,盖满可见区的用dvh,封顶照控制室记录用svh。
「我希望他就在一面里面,上下不对称看着不舒服,右边的那个(滚动条)可以直接不要了」
坑
「刚好装下」不合格:卡集舞台写死69svh,在2040×1019上量到卡底只剩4px就算装下,屋主真机上浏览器工具栏、任务栏、远程桌面都在吃高度,必然溢出(原则见总览「上下留白对称,『刚好装下』不合格」)。验收用带工具栏的真实高度:台式2040×930、笔记本2552×1180、手机417×750(判装不装得下用750,判会不会显得空用903),断言scrollHeight === clientHeight。只有一行auto的grid里子元素的max-height:100%不生效,上限直接写成calc(100svh - 40px - env(safe-area-inset-top)),不再补一行100vh当兜底——裸vh不许,屋主三台设备的Edge 153都认svh。
出处:控制室10-08定(按场景分的四条);memory/owner-devices-viewports.md:23「417×750 与 417×903」、:25「一屏容器用 100dvh」、:16(三台都是Edge 153);Ysevan_web/docs/xiaowu-ui-spec.md「11.1 零固定高度原则」(「100svh 而不是 100vh」)、「11.6 内容尺寸:主项是等比单位,视口单位只当兜底」(「以前写的是」「视口单位的四条」「余量必须来自结构」)、「6.3 数值」(「轨道高」);tools/card/CLAUDE.md:168「第三个实例」、:187「首屏装进一屏、上下留白相等」、:188(body 按100dvh排成一列);tools/star/CLAUDE.md:96「只有一行 auto 的 grid 里」;本站 tools/star/assets/star.css:342、:387、:513、:831、tools/star/assets/kit.css:85、:208、:278
布局陷阱集:每一个都踩过、都不报错,桌面上常常还看不出来
十一个,每个一个能复现的小框:先看反例的样子和量出来的数,再点「看修法」。前六个出自四个工具,中间三个出自小屋,最后两个是本站自己踩的。
演示每个小框右下角「看修法」切换反例和修法,读数当场量。第1个要在框里滚到中间再看底栏在哪;第11个点「跳到第3节」。
1玻璃卡里的fixed不贴屏幕
题型:单选 · 多选 · 判断
难度:全部
题库:综合业务
数量:20题
顺序:随机
只做错题:否
计时:关
最后一组选项
开始练习
3列flex里margin:auto顶掉stretch
8装饰写负right,overflow-x:hidden挡不住
10单行auto的grid里max-height:100%不生效
更新记录(示例)
0.3.0:外壳用上合集
0.2.0:每条都有演示
0.1.0:第一版样张
第39周 搭外壳
第40周 写色彩页
第41周 写交互页
最后一行
数值 / 代码
1、祖先带 backdrop-filter / filter / transform 时,position: fixed 改以它为参照
→ 玻璃卡里要贴底贴顶一律 position: sticky; bottom: 导航高 + 8u;非要 fixed 就挪出玻璃卡
(演示框里用一个静态 transform 代替磨砂:同一条规则,框里不新增 backdrop-filter)
2、min-height 的 grid 默认 align-content: stretch,多余空白平均分给每一行 → align-content: start
3、列 flex 里 margin: auto 顶掉 stretch,子项缩成内容宽 → 显式 width: 100%
4、flex 两个兄弟各挂一个 margin-left: auto,剩余空间被均分 → 先合成一个右侧组再整体靠右
5、百分比 padding 参照包含块的宽(品牌字在内约200px),padding: 8% 把34px的图标压到2px
→ 尺寸写死成 calc(var(--brand-box) * .84)
6、单行输入的值不含换行,浏览器直接吞掉 \n → 「第一行当标题」用 rows="1" 的 <textarea>
7、figure 默认 margin: 1em 40px → reset 那一行要有 figure:p, h1, h2, h3, ul, ol, li, figure { margin: 0; }
8、overflow-x: hidden 不显示滚动条,但挡不住 scrollWidth 被顶大(iOS 照样能左右拖)
→ 锚在 right: 0,要往外挪用 right: clamp(0px, 5vw, 84px);往外挂的装饰必须有收起的断点
9、overflow: hidden 裁圆角的卡会把挂在它身上的装饰一起裁掉 → 装饰挂在外面那一层
10、只有一行 auto 的 grid,格子不定高,子元素 max-height: 100% 算不出来
→ max-height: calc(100svh - 40px - env(safe-area-inset-top))(封顶用 svh,不再补一行裸 vh)
11、吸顶顶栏的高度只让 html 的 scroll-padding-top 管一次;条目的 scroll-margin-top 只留12px
用在哪
①刷刷「开始练习」底栏(3.11.0–3.12.0手机上滚动途中看不到、滚到底盖住最后一组36px)、plan「更多」面板;②plan的.app-shell(顶栏形态下侧栏那行凭空长出两百多像素);③card画廊(整条舞台从950缩到594);④plan分组小标题的动作链接与计数;⑤岗岗品牌图标;⑥plan笔记页「记一条」;⑦⑧⑨小屋门厅;⑩本站的底部弹层(更新记录面板撑到2849px);⑪本站601–900宽的锚点(768下顶栏下面空76px)。
为什么
这些都不报错,常常只在某一档宽度、滚到中途、或者换一台机器才露馅:只看页面顶部截图、只在开发机上看,三轮验收都没发现第1个。所以每个修法都配了量法:量滚动顶中底三处的位置、量scrollWidth、量计算样式,不靠目测。
出处:1 memory/glass-panel-breaks-fixed.md:8、:10、tools/shua/design-proposal.md:379「玻璃面板里的贴底」、tools/plan/docs/ui-redesign-proposal-v2.md:542「两个踩过的坑」;2 tools/plan/docs/ui-redesign-proposal-v2.md:547「平均分给每一行」;3 tools/card/CLAUDE.md:190「列 flex 里 margin:auto」;4 tools/plan/docs/ui-redesign-proposal-v2.md:302「flex 的 margin-left: auto」;5 tools/gang/design-proposal.md:1160「这里刻意不用百分比 padding」;6 tools/plan/CLAUDE.md:174「八点五、<input> 会把换行吃掉」;7 Ysevan_web/docs/xiaowu-ui-spec.md「11.3 CSS reset 必须覆盖 figure」(「一定要在这一行里」);8 Ysevan_web/docs/xiaowu-ui-spec.md「11.4 实现避坑」(「装饰禁用负 right 偏移」);9 Ysevan_web/docs/xiaowu-ui-spec.md「11.4 实现避坑」(「装饰不要挂在带 overflow: hidden 的容器上」);10 tools/star/CLAUDE.md:96「只有一行 auto 的 grid 里」;11 tools/star/CLAUDE.md:94「吸顶顶栏的高度」