object-fit :封面在 chrome 上提供像素化图像

Ski*_*hil 17 css browser

我有一个简单的卡片元素,里面有一个<img>标签。该图像具有object-fit: cover;属性。当我使用 Chrome 时,它​​会产生非常奇怪的像素化效果。另一方面,FireFox 可以毫无问题地绘制图片。这是 chrome 的 bug 还是只是他们的渲染算法不太好?

火狐图像 铬合金

左边是 firefox 的图像,右边是 chrome 的图像,检查手臂和身体。

chrome 版本 107.0.5304.107 火狐版本 107.0

解决方法是行不通的,因为这只能解决我的问题。这是另一台电脑上同样的问题。(不同品牌,不同规格)问题仍然存在。(右边是Chrome,仍然检查手臂) 其他电脑

her*_*zel 12

TL;DR:你只能减轻这种影响 \xe2\x80\x93image-rendering是不可预测的

\n

现状 2023-01-18

\n

显然,大多数基于 chromium(blink 引擎)的浏览器(google chrome、opera、vivaldi、brave、ie13/edge 等)会根据所需的缩放/调整大小在不同的插值方法之间切换,以优化渲染性能。

\n

镀铬调整大小

\n

左:内在 3000x3000px 缩小到 240x240px
\n看起来不错 \xe2\x80\x93 大概是双线性或双三次插值。

\n

右:内在 4000x3000px 缩小并适合 240x240px
\n明显的“锯齿状”边缘 \xe2\x80\x93 大概是通过附加平移/拟合引入的简单最近邻插值 \xe2\x80\x93object-fit:cover

\n

显然,当两者都满足时,基于 chromium 的浏览器将回退到更简单的最近邻下采样方法

\n
    \n
  • 固有尺寸和渲染尺寸以及
  • \n
  • 固有纵横比和渲染纵横比
  • \n
\n

差异显着。

\n

解决方法:通过优化图像避免过度调整大小

\n
    \n
  • 避免不必要的高分辨率 - 尝试调整图像大小并裁剪图像以匹配实际布局尺寸:例如,如果您的图像始终以 1/1 纵横比使用 - 您最好裁剪 16/9 图像。用谷歌灯塔行话来说: “提供尺寸适当的图像,以节省蜂窝数据并缩短加载时间。”
  • \n
  • 定义响应式图像和/或艺术方向图像候选:
    \n Smashing magazine:响应式图像正确完成:A Guide To And srcset
  • \n
\n

然而,上述方法只会减轻这种影响。

\n

希望我们会看到为或 之image-rendering类的值指定更好的支持/实现。smoothhigh-quality

\n

MDN 网络文档:图像渲染

\n

示例片段(仅用于比较/测试)

\n

\r\n
\r\n
function replaceImg() {\n  let images = document.querySelectorAll("img");\n  images.forEach((img) => {\n    let wNative = img.naturalWidth;\n    let hNative = img.naturalHeight;\n    let wRendered = img.offsetWidth;\n    let hRendered = img.offsetHeight;\n    let scale =\n      Math.min(...[wRendered, hRendered]) / Math.min(...[wNative, hNative]);\n\n    if (scale < 0.3) {\n      scale *= 2;\n      (async() => {\n        let dataUrl = await imageToDataURL(\n          img.src,\n          wNative * scale,\n          hNative * scale\n        );\n        img.src = dataUrl;\n        img.classList.add("imgDataUrl");\n      })();\n    }\n  });\n\n  async function imageToDataURL(imageUrl, width, height) {\n    let img = await fetch(imageUrl);\n    img = await img.blob();\n    let bitmap = await createImageBitmap(img);\n    let canvas = document.querySelector("canvas") ? document.querySelector("canvas") : document.createElement("canvas");\n    let ctx = canvas.getContext("2d");\n    canvas.width = width;\n    canvas.height = height;\n    ctx.drawImage(bitmap, 0, 0, width, height);\n    let dataUrl = canvas.toDataURL("image/jpeg");\n    return dataUrl;\n  }\n}
Run Code Online (Sandbox Code Playgroud)\r\n
* {\n  box-sizing: border-box\n}\n\nbody {\n  font-family: sans-serif\n}\n\nfigure {\n  width: 240px;\n  height: 240px;\n  display: inline-block;\n}\n\nimg {\n  max-width: 100%;\n  height: 100%;\n  aspect-ratio: 1/1;\n  object-fit: cover;\n}\n\n.obj-contain {\n  object-fit: none;\n  object-fit: none;\n}\n\n.pixelated {\n  image-rendering: pixelated;\n}\n\n.crisp {\n  image-rendering: crisp-edges;\n}\n\n.auto {\n  image-rendering: auto;\n}\n\n.imgDataUrl {\n  outline: 2px solid red;\n}
Run Code Online (Sandbox Code Playgroud)\r\n
<p><button onclick="replaceImg()"> Replace with dataURL</button></p>\n\n\n<figure>\n  3000 x 3000: auto\n  <img class="auto" src="https://picsum.photos/id/76/3000/3000" alt="">\n</figure>\n\n\n<figure>\n  4000 x 3000: auto\n  <img class="auto" src="https://picsum.photos/id/76/4000/3000" alt="">\n</figure>\n\n<figure>\n  1200 x 1000: auto\n  <img class="auto" src="https://picsum.photos/id/76/1000/800" alt="">\n</figure>\n\n<figure>\n  240 x 240: auto\n  <img class="auto" src="https://picsum.photos/id/76/240/240" alt="">\n</figure>\n\n<figure>\n  300 x 240: auto\n  <img class="auto" src="https://picsum.photos/id/76/300/240" alt="">\n</figure>\n\n<figure>\n  600 x 480: auto\n  <img class="auto" src="https://picsum.photos/id/76/600/480" alt="">\n</figure>\n\n\n\n<figure>\n  3000 x 1500: auto\n  <img class="auto" src="https://picsum.photos/id/76/3000/1500" alt="">\n</figure>\n<figure>\n  1600 x 800: auto\n  <img class="auto" src="https://picsum.photos/id/76/1600/800" alt="">\n</figure>\n<figure>\n  800 x 400: auto\n  <img class="auto" src="https://picsum.photos/id/76/800/400" alt="">\n</figure>\n\n<figure>\n  600 x 300: auto\n  <img class="auto" src="https://picsum.photos/id/76/600/300" alt="">\n</figure>\n\n\n<figure>\n  800 x 400: pixelated\n  <img class="pixelated" src="https://picsum.photos/id/76/600/300" alt="">\n</figure>
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

用于测试的 Codepen 示例

\n

\xc2\xbb 情人眼里出西施\xc2\xab

\n

即使很困难,像素插值也有很多选择(快速双线性、双三次、lanczos、b 样条、AI/DL 训练算法等)。

\n

公平地说:

\n
    \n
  • 一些用户会更喜欢稍微“锯齿状”的边缘而
    不是稍微“模糊”的边缘\n(琐事:当cleartype和其他字体\n抗锯齿技术被引入时,这是一件大事\xe2\x80\x93我很高兴抗锯齿阵线赢得了这场战争......)
  • \n
  • 后者会抱怨渲染模糊。
    \n另请参阅解决相反问题的 SO 问题
  • \n
  • 其他人 - 使用高像素密度显示器 - 可能根本不会注意到前面提到的“惰性”优化技巧
  • \n
\n

正如@Rene van der Lende所评论的:
\nChromiums 缩小尺寸的图像渲染本身并不坏 \xe2\x80\x93 有时 Firefox(或 safari 和非苹果 webkit 浏览器,如 Epiphany 或 midori)可能会遇到类似的问题,但在其他场合。

\n


小智 7

你应该试试 :

overflow-clip-margin: unset;
overflow: visible;
Run Code Online (Sandbox Code Playgroud)

这个对我有用。