封面被裁,是改版时最容易被忽略的细节。
同一张图,列表里是 480×270 的横条,首页主卡接近 16:9,详情页更宽。竖图放进去,object-fit: cover 只能保住中间一小段——主体的眼睛常常正好被切在边界上。
一张 1280×1700 的竖图,放进 876×340 的主卡里,可见区域大约只有原图高度的 20%。默认 object-position: center 永远取正中,于是:
换图能解决,但每换一次都要重新裁一遍,而且同一张图在三个位置的最优裁切并不一样。
服务端只存一个百分比坐标:
cover_position = "50% 30%"
前端把它直接交给 CSS:
.cover img { object-fit: cover; object-position: 50% 30%; }
后台的写作面板里,封面预览下方有水平/垂直两个滑块,也可以直接点预览图上想要的位置——点哪儿,哪儿就成为焦点。实时预览用的是同一套 background-position 规则,所见即所得。
服务端裁切意味着:每换一次版式、每加一个尺寸,都要重新生成一批图。而焦点坐标是与尺寸无关的:同一份数据能同时服务列表、头图、详情页,甚至以后新增的版式。
代价是浏览器要自己裁——但这正是 object-fit 的本职工作,不额外花什么。
焦点只管「看见哪一块」,不管「下载多大」。头图原来直接加载 835KB 的原图,改成上传时生成 1280 宽的 WebP 派生档后是 97KB,卡片档 480 宽只有 28KB。
两者配合起来才是完整的:
数据:cover_position → 决定裁哪里
派生:-hero / -card → 决定下多大
50% 50%,和改造前一致;onerror 回退原图;改动不大,但这类「看起来只是样式」的问题,往往要动数据模型才能真的解决。