如何在加载图像之前保持图像的固有大小,从而使布局稳定?

How to keep an image size intrinsic, before it is loaded, so layout is stable?

我一直认为您可以指定 <img/>widthheight 属性,这样浏览器就可以知道它的物理尺寸而无需下载(至少 header) 首先。但显然这些属性被视为 CSS 属性 - 因此当您尝试执行 width: 50%; height: auto 之类的操作时会被覆盖。然后,直到图片下载完成,计算出的高度仍然是0
有没有办法通过 HTML/CSS?

显式设置图像的物理尺寸(实际上是它的纵横比)

(...并在使用 Masonry 时避免 "flashes of unknown aspect ratio" / 紧张 re-layouting - 你也许可以解决这个问题,但我对基本问题更感兴趣。即使我正在努力简洁地询问它:)

因此,一旦我们通过 CSS 设置 height: auto,浏览器就会忽略由 widthheight HTML 属性设置的固有大小。

可能的解决方法和未来可能的解决方案:

  1. 使用 Intrinsic Ratio Box hack
    <div style="height: 0; padding-bottom: 42.857%; position: relative">
      <img style="position: absolute; left: 0; height: 0; width: 100%; height: 100%" … />
    </div>
    
  2. 使用数据 URI 和 JavaScript 预加载具有相同纵横比的占位符(注意舍入错误!)
    <img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAQIAJQAlAAD/2wBDAFA3PEY8MlBGQUZaVVBfeMiCeG5uePWvuZHI////////////////////////////////////////////////////wAALCAAPACMBAREA/8QAFgABAQEAAAAAAAAAAAAAAAAAAAEE/8QAFBABAAAAAAAAAAAAAAAAAAAAAP/aAAgBAQAAPwDQgoICv//Z"
      onload="this.src='https://via.placeholder.com/3500x1500.jpg'"/>
    
    如果我们使用 "blurry placeholder" 技术,框架可能已经存在。
  3. 与两个相同,但使用 SVG - 更容易即时创建,但没有模糊的占位符 "for free",显然
    <img src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
      width='350px' height='150px'%3E%3C/svg%3E"
      onload="this.src='https://via.placeholder.com/3500x1500.jpg'"/>
    
  4. 如果一旦 intrinsicsize 登陆(WICG, github/Chrome)并被采用,将有一个正确的方法来做到这一点:
    <img intrinsicsize="350x150" width="…
    

当然,所有这些都有缺点。
您可以在 this Pen 中尝试 2 和 3 - 它需要更多的工作和测试,我可能会等待 4,我认为这是对不需要修复的东西的修复。愚蠢的浏览器:)

为 2021 年更新,我们现在有一种广泛支持的符合标准的方式来做到这一点,那就是 CSS aspect-ratio 属性.

您可以像这样简单地使用高度和宽度:

.myimage {
  width: 50%;
  height: auto;
  aspect-ratio: 1280 / 720;
}

这将首先计算宽度为父元素的 50%,然后将高度设置为 auto(最好将其显式设置为 auto,以防其他东西为了可维护性而改变高度),它将使用用于计算应保留的高度的纵横比值。

影响图像元素,即使在图像已加载之后也是如此。这意味着如果纵横比 属性 与图像的实际纵横比不匹配,图像将被拉伸以适应。您可以通过在前面加上“auto”值来防止这种情况。

aspect-ratio: auto 1280 / 720;

这样一来,它将在加载图像之前使用定义的纵横比,并且实际纵横比已知,然后在浏览器知道固有纵横比后回退到自动。

这不受 Internet Explorer 和 Safari 等非标准浏览器的支持,因此如果您想在纯粹使用 CSS 的浏览器中使用此方法,您需要继续使用 (作为旁注,第 4 个选项不是也从未成为标准的一部分)。

但是,如果是今天(至少不是同一个人)可能甚至不会有人问这个问题,因为现在有一个 HTML 解决方案是旧的预响应网页设计 HTML 解决方案。大多数现代浏览器现在使用图像元素的高度和宽度属性来计算纵横比,而 CSS 高度和宽度会覆盖这些值,除非它们被设置为自动。

因此...

<img src='myimage.jpg' class='myimage' width='1280' height='720' />
.myimage {
  width: 50%;
  height: auto;
}

这将保留正确的垂直高度,即使在 Safari 中也是如此。截至目前,还有一些 browser-specific implementation notes 需要考虑。

在 Chromium 和 Firefox 中,它目前是使用 CSS 宽高比 属性 实现的,在计算的宽高比前面加上“自动”。

aspect-ratio: auto attr(width) / attr(height);

由于 Safari 不支持宽高比 属性 但在我撰写本文时,它的实现有更多细微差别。因此,如果 src 属性中没有有效的图像值,它不会保留 space,这意味着如果您使用老式的基于 JavaScript 的图像延迟加载,则需要包括后备图片。

无论如何,您都应该在图像标签中尽可能多地包含高度和宽度属性。他们现在确实在做一些事情。