一张头图的响应式之旅
参考站点的头图在矮屏笔记本上占了视口的 97%。我想弄清它的高度怎么变,最后把复杂度从代码搬进了出图规范。
- CATEGORY
- 研究
- YEAR
- 2026
- STATUS
- 笔记
- TOOLS
- css / object-fit / srcset
entry记录
我在做一个物流平台的门户网站,首页最上方是一张通栏头图,轮播港口、船闸、货轮的实景航拍,设计参考了另一家物流平台的官网。参考站点的头图在矮一点的屏幕上几乎占满整个浏览器窗口,一眼看不到下面的任何内容,我想弄清它的高度怎么变,以及正确的做法是什么。先交代三个词:浏览器里网页实际可用的显示区域称为视口,不等于屏幕分辨率;图片等比放大到铺满容器,多出的部分裁掉,不变形也不留白,这种裁法称为 cover 裁切,即 CSS 的 object-fit: cover;设计师画头图时用的画布尺寸称为画板。
我原以为参考站点头图的高度会跟着窗口连续变化。在真实浏览器里换几个尺寸测量,再读线上的 CSS,规则只有两条:默认 700px,屏幕宽度不超过 1536px 时改成 608px。高度只按宽度分两档固定像素,完全不看屏幕多高。在 1366×768 的笔记本上,去掉浏览器工具栏后可视高度约 625px,608px 的头图占视口 97%,几乎铺满;同一档里 768×1024 的竖屏只占 59%。这还连带两个问题:用 background-size: 100% 100% 铺图,容器比例一变,画面就被非等比拉伸;头图里的轮播和底栏也是写死的像素高度,单给容器加高度上限会把内容裁掉。根因是用宽度断点去解决高度问题,高度问题应该用和视口高度挂钩的单位(vh,以及在移动端地址栏伸缩时不跳动的 svh)解决。
我自己的需求有三条:头图高度取视口高的 80%,给下一屏留 20%,让人知道下面还有内容;素材是一张 3840×800 的超宽图,画面里的货轮在任何屏幕上都必须完整可见;图片等比缩放,不变形。cover 天然满足第三条,难在第二条:cover 会裁掉两侧,裁多少取决于屏幕比例。按像素测量素材,货轮连船头和尾浪位于图片宽度的 53.6% 到 68.2%,占图宽 14.6%。可见图宽的比例 f = 视口宽 ÷(0.8 × 视口高 × 4.8),4.8 是素材的宽高比;只要可见窗口盖住 53.6% 到 68.2% 这一段,货轮就完整。第一版把裁切焦点对准货轮(object-position: 63%),所有桌面屏上都保得住。顺带算出,竖屏手机上 f 只有 12%,比货轮的 14.6% 还小,三个条件在数学上不可能同时满足,手机端暂不考虑。
这时补充了一个背景:这张图是按 1920×1080 的画板设计的,货轮本来就该在画面右下角,这是构图。第一版把焦点移到货轮上,等于把货轮拖向画面中心,数学上更稳,却破坏了设计好的构图。第二版改为严格居中裁切,换一个变量保货轮:居中时可见窗口是 50% − f/2 到 50% + f/2,要盖住货轮右端的 68.2%,需要 f ≥ 36.5%,换算成视口宽高比 ≥ 1.40。16:9、16:10、3:2 的桌面屏都满足,只有 4:3 差一点,所以用 height: min(80svh, 56vw) 兜底,只在 4:3 这类窄屏上让高度略降到约 75%,构图和货轮同时保住。之后加了第二张主体居中的船闸全景,居中裁切对它没有额外成本:窗口怎么收窄,都是从两侧对称裁背景,主体始终在屏幕中央。以后新增轮播图,用一条核验式检查:f ≥ 2 × max(主体右边界 − 50%, 50% − 主体左边界)。选裁切方案之前,先弄清这张图想表达什么。
方案能用了,但代码里塞满了为那艘偏右的货轮服务的东西:高度封顶、焦点坐标、核验公式。我问了一个问题:如果不再考虑货轮位置的限制,方案能否简化?可以,只剩几行:高度先写 80vh 给旧浏览器回退,再写 80svh,避免移动端地址栏伸缩造成跳动;溢出隐藏;图片宽高铺满,加 object-fit: cover。约束不会凭空消失,只是从代码移到了素材规范里:代码不再替素材兜底,素材就必须保证主体在任何屏幕都看得到的区域。我接受这个交换,因为这样代码只写通用规则,不用随某一张图修改。
接着看 3840 的宽度还有没有必要,当初选它是为了适配 4K 屏、避免两侧露白。防露白由 cover 保证,与素材宽度无关;4K 屏全屏显示时,可见部分本身就是 3840 个物理像素宽,3840 是清晰度的物理下限,省不掉。真正的浪费在比例:4.8:1 的图在 16:9 屏上只有中间 46% 可见;4K 屏头图要 1728px 高,素材只有 800px,被放大 2.16 倍,画面发虚。于是画板直接定为 1920×864,这正是 1920×1080 视口下头图的真实形状(2.222:1),再按 2 倍导出 3840×1728。同样是 3840 宽,新比例在 16:9 屏上全图呈现,设计稿所见即所得;4K 屏的 1728px 高度也恰好 1:1,不再发虚。素材的比例按最常见的视口确定,分辨率按最高目标屏的物理像素反推,这样素材的形状就等于容器的真实形状。
画板固定后,各种屏幕会裁掉哪里就成了确定的几何关系。我把这层关系画成一张模板,设计师可以半透明叠在画板最上层当参考线。中央是核心安全区,主体和必须完整的元素只放这里,所有目标屏幕上都完整可见;左右的红带在视口比 16:9 更窄时最先被裁;红带内侧的黄带只有 4:3 这类更窄的视口才会裁到;上下的绿带在视口比 16:9 更宽时被裁。另定三条规则:四边向品牌蓝渐变收边,裁到哪里都自然;构图以画板中心为锚点;图上不直接画字,标题这类内容用网页元素叠上去。
规范和演示页做好后,在一台 1440×900 的屏幕上实测,头图完整显示,并没有像预期那样裁掉两侧的红带。原因是屏幕分辨率不等于网页视口:浏览器的标签栏、地址栏占掉约 90 到 140px 高度,1440×900 的屏幕在日常浏览时,视口其实只有约 1440×770;头图容器变成 1440×616,比例 2.34,比画板的 2.222 更扁,cover 的裁切方向随之翻转,不再裁左右,而是保留全宽、只轻裁上下,各约 21px,仍在绿带内。之前的验证用的是精确 1440×900 的视口,相当于按 F11 全屏,所以看到的是裁两侧的状态。判断裁切方向只要一条规则:视口高度大于视口宽度 ÷ 1.778 时裁两侧,否则裁上下;1440 宽时临界点是 810px。规范改了一处:上下 108px 的绿带原本只算比 16:9 更宽的带鱼屏才需要注意的可选约束,升为常规约束,因为日常带工具栏浏览就会裁到它,1920×1080 的屏幕带工具栏时上下各约 50px。验证要用带工具栏的浏览窗口。
2K(2560×1440)和 4K(3840×2160)都是 16:9,与画板比例一致,构图和 1080p 完全相同。清晰度上,头图需要的物理高度是屏幕物理高度的 0.8 倍:2K 缩小显示,锐利;4K 恰好 1:1;5K、6K 的 Retina 屏和 5120 宽的超宽屏约 1.33 倍放大,轻微发软,可以再出一档 3 倍图。新比例下 16:9 屏上图片显示宽度正好等于视口宽度,前端用 srcset(供浏览器按屏幕条件挑选图源的属性)配合 sizes="100vw",浏览器就能为普通屏选 1 倍图、为高分屏选 2 倍图,不会选错。
按规范重新出了两张 3840×1728 的 WebP 实拍图,连同安全区模板一起放进轮播演示页;第三张模板当标定尺,任何时候切到它,都能对照色带核验当前的裁切。抽查货轮图:集装箱区位于图宽的 56.8% 到 86.5%,连船头和尾浪大约到画板 x≈1700,基本贴着核心安全区的右边界(1680)收住,没有进入红黄带。主体偏右留出动感,正是规范想要的构图。唯一的小问题是体积:货轮图 523KB,略超 400KB 的建议预算,导出质量再降一档即可。
起点是一个很小的问题,头图在某些屏幕上太高;终点是一套只有几行的前端代码,加上一份给设计师用的出图规范和一张安全区模板。竖屏手机没有处理。
process对比
前端(全部规则)
.hero {
position: relative;
width: 100%;
height: 80vh;
height: 80svh;
overflow: hidden;
}
.slide {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 0.8s ease;
}
.slide.active {
opacity: 1;
}
.slide img {
width: 100%;
height: 100%;
object-fit: cover;
}安全区(1920×864 画板)
- 核心安全区
- 中央 1440×648 · 主体和必须完整的元素只放这里
- 红带
- 左右各 96px · 视口比 16:9 更窄时最先被裁
- 黄带
- 左右 96–240px · 4:3 等更窄的视口才会裁到
- 绿带
- 上下各 108px · 视口比 16:9 更宽时裁上下,日常浏览很常见
高分屏
- 2K
- 需要 1152px · 素材 1728px · 缩小显示,锐利
- 4K
- 需要 1728px · 素材 1728px · 恰好 1:1
- 5K / 6K Retina、5120 宽超宽屏
- 约 1.33 倍放大 · 轻微发软,可再出一档 3 倍图
result小结
- 结论
- 前端只剩 80svh 加 object-fit: cover 几行;构图的约束交给一张 1920×864 画板的安全区模板。
- 参数
- 画板 1920×864 · 导出 1×、2×(3840×1728)· 核心安全区 1440×648 · 红带 96px · 黄带 96–240px · 绿带 108px
- 没做完
- 竖屏手机没有处理;5K、6K 屏约 1.33 倍放大,会轻微发软;货轮图 523KB,略超 400KB 的建议预算。
log日志
- 2026-08-28
- 首次记录