image-rendering 不能单独解决模糊,必须配合整数倍缩放;crisp-edges 是唯一支持放大缩小双向禁用平滑插值的标准值,pixelated 仅放大生效;需直接作用于 img 标签、避免隐式缩放与覆盖。

image-rendering 不能单独解决模糊,必须配合整数倍缩放
加了 image-rendering: pixelated 或 crisp-edges 还是糊,大概率是因为原始图尺寸和最终渲染尺寸不是整数倍关系。比如一张 16×16 的像素图,设 width: 65px —— 65 ÷ 16 = 4.0625,非整数,浏览器直接弃用 pixelated,退回到默认双线性插值。
必须确保:width 和 height(或 CSS 中的 width/height)是原始图尺寸的严格整数倍(2×、3×、4×),且不使用 max-width、transform: scale() 或 flex 自动挤压等隐式缩放方式。
- 用
<img src="icon.png" style="max-width:90%" style="max-width:90%">比纯 CSS 控制更可靠(避免 JS 动态计算导致小数像素) - 响应式场景下,用
@media切换不同整数倍尺寸(如width: 32px→64px),而非连续缩放 - 检查 computed styles 中
width/height是否为整数(DevTools → Styles → Computed)
pixelated 和 crisp-edges 到底该选哪个
pixelated 名字听着对味,但实际只在放大时生效;缩小(比如从 64px → 32px)时规范明确要求退化为 auto,结果还是糊。而 crisp-edges 是目前唯一能在放大和缩小两个方向都强制禁用平滑插值的标准值,效果接近最近邻算法,边缘硬、色块稳。
- 优先写
image-rendering: crisp-edges,覆盖所有缩放方向 - 为兼容旧版 Safari(≤14),补一行
image-rendering: -webkit-optimize-contrast - 别用
smooth或留空——这就是默认双线性插值,模糊源头 -
pixelated仅适合明确需要马赛克感的放大动效,且必须禁用任何缩小逻辑
为什么加了样式却没生效
常见失效不是因为写错了值,而是被其他层覆盖或作用对象错误。比如 Tailwind 默认注入 image-rendering: smooth,或者你把样式写在父容器上,但 image-rendering 只对 <img> 元素本身起作用。
- 必须直接作用于
<img>标签,不能写在<div> 上再靠继承 <li>第三方库(如 Normalize.<a style="color:#f60; text-decoration:underline;" title="css" href="https://m.php.cn/zt/15716.html" target="_blank">css</a>、某些 UI 组件)可能已设 <code>image-rendering: smooth,需用更高优先级选择器或!important -
background-image不受该属性影响;transform: scale()绕过image-rendering控制路径 - 移动端 Retina 屏若没配
srcset,浏览器仍加载@1x图,再锐化也没用 - 错误做法:
<canvas width="32" height="32"></canvas>+image-rendering: pixelated+ CSS 拉伸到128px - 正确做法:保持
canvas.width/canvas.height为原始尺寸(如32),JS 中设ctx.imageSmoothingEnabled = false - 动态缩放用
ctx.scale(4, 4)+ctx.drawImage(img, 0, 0),而不是拉伸 canvas 元素本身
Canvas 里设 image-rendering 是白忙活
image-rendering 是 CSS 渲染合成层的控制项,只管最终输出阶段的缩放行为。<canvas></canvas> 内部绘制走 JS 光栅管线,CSS 对 ctx.drawImage() 完全无效。











