WordPress / gutenberg

The Block Editor project for WordPress and beyond. Plugin is available from the official repository.
https://wordpress.org/gutenberg/
Other
10.37k stars 4.15k forks source link

Images should always provide dimensions #23244

Open felixarntz opened 4 years ago

felixarntz commented 4 years ago

Background

In order for the browser to set up a webpage's layout it's important that images have their dimension attributes width and height provided, as this will inform the browser of the effective aspect ratio of the image before it is even loaded. Without these attributes provided, the page layout will reflow once the image has loaded, causing so-called "layout shift" which is harmful for user experience (think about the experience where you want to click on something but just as you're about to do so the page content moves and you accidentally click on something else). These layout shifts always happen - the experience is worse on a slow network connection, but they are visible pretty much no matter how fast the connection is.

Historically the classic editor has always provided these attributes, but that was changed in Gutenberg, where now the majority of images is without width and height. This issue seeks to address this to reduce the cumulative layout shift across WordPress sites for content generated with Gutenberg. I've been working on a closely related core issue (feel free to chime in there as well!) that addresses this in a more "patch-y" way that will retroactively work, but we should address this in Gutenberg too to get the proper experience in the editor itself as well.

See the difference in experience here, based on the above core patch: Before: before the patch After: after the patch

The main question we should discuss and answer first is: Why was it initially decided to omit width and height attributes?

Goal

The following blocks should always provide width and height on img elements, regardless of whether the user provided a custom size or not:

Related

oxyc commented 4 years ago

Not sure about historical reasons but an idea to avoid the layout shift even if images are shown as max-width: 100% is using aspect ratio boxes.

<!-- (width / height) set by block based on image natrual size -->
<figure class="wp-block-image size-large" style="--aspect-ratio: 810/540;">
  <img src="">
</figure>
.wp-block-image:not(.is-resized) {
  &[style*="--aspect-ratio"] img {
    width: 100%;
    height: auto;
  }

  @supports (--custom:property) {
    &[style*="--aspect-ratio"] {
      position: relative;
    }

    &[style*="--aspect-ratio"]::before {
      content: "";
      display: block;
      padding-bottom: calc(100% / (var(--aspect-ratio)));
    }  

    &[style*="--aspect-ratio"] img {
      position: absolute;
      top: 0;
      left: 0;
      height: 100%;
    }  
  }
}
adamsilverstein commented 4 years ago

even if images are shown as max-width: 100%

@oxyc - Can you explain the advantage/reason for showing images as max-width: 100%? Does tagging the image with width and height negate them?

oxyc commented 4 years ago

This confused me because specifying width and height actually did fix the layout shifting for responsive images. It did not use to do this until recently: https://chromestatus.com/feature/5695266130755584

So aspect ratio boxes (what I gave an example of in my previous comment) are a thing of the past for images and what this issue proposes makes a significant improvement by eliminating layout shift.

Can you explain the advantage/reason for showing images as max-width: 100%?

Basically it's used to ensure an image doesnt grow larger than it's container, even if the image is larger.

Does tagging the image with width and height negate them?

No, but up until recently the attributes didn't actually matter together with max-width: 100%. Now it seems browsers have shipped an internal style which leverages width/height properties to know the image aspect ratio before it has loaded:

img, video {
    aspect-ratio: attr(width) / attr(height);
} 

https://github.com/WICG/intrinsicsize-attribute/issues/16#issue-453241787 explains it and at the end of the threads it has a video that demos and explain it as well.

Available since Chrome 79, Firefox 71, Safari Tech Preview

felixarntz commented 4 years ago

No, but up until recently the attributes didn't actually matter together with max-width: 100%. Now it seems browsers have shipped an internal style which leverages width/height properties to know the image aspect ratio before it has loaded:

That's a good point. It should be fair to say though that having the dimension attributes present would not have resulted in a negative effect in that case either. For cases where e.g. an image would be left- or right-aligned beside some text, having the attributes has already been a key for reducing layout shifts much longer.

Another reason the dimension attributes on the img are crucial to reduce layout shifts is the following example: If you set an image to width:100%;height:auto, it will be displayed like that regardless of whether or not width and height attributes are present. However, without the attributes you'd get the layout shift because the browser wouldn't know the aspect ratio of the image right away.

I guess my main question at this point is: Is there any actual downside from including width and height that I may be missing?

azaozz commented 4 years ago

Is there any actual downside from including width and height...

Don't think so. Having width and height in the img tag has been best practice since... late 90's? :) Seems that knowing the (intrinsic) size of images as soon as the HTML is loaded helps modern browsers too.

If you set an image to width:100%;height:auto...

Yes, as far as I've seen most images are styled with either width: 100% or max-width: 100% which makes having the width and height attributes really important.

oxyc commented 4 years ago

Here's an earlier issue regarding this as well https://github.com/WordPress/gutenberg/issues/6652

dotsam commented 4 years ago

I don't know if this should be a new issue, but with core adopting its patch to always add image width/height as of 5.5, the Block Library style for alignfull and alignwide is breaking image aspect ratios, as it overrides the image width, but does not set height: auto

https://github.com/WordPress/gutenberg/blob/c87c9b01e6506e47dc9435637d7c97fb260258cb/packages/block-library/src/image/style.scss#L14-L17

sabernhardt commented 4 years ago

I think the images do need height: auto in the front-end block styles, but not only the images in alignfull and alignwide blocks.

Except when overridden, the editor scales images inside the .block-editor__container element. Then on the front-end, the height does not adjust accordingly with the max-width.

Editor (.block-editor__container img): https://github.com/WordPress/gutenberg/blob/c87c9b01e6506e47dc9435637d7c97fb260258cb/packages/edit-post/src/style.scss#L86-L89

Front-end image block: https://github.com/WordPress/gutenberg/blob/c87c9b01e6506e47dc9435637d7c97fb260258cb/packages/block-library/src/image/style.scss#L1-L8

adamsilverstein commented 3 years ago

@felixarntz Can you confirm this would still be an improvement, even though we added automattic image width/height markup in 5.5? I'm thinking that if Gutenberg inserted the width/height, core would respect that, so it would be potentially more accurate or customizable by the user.

thpglobal commented 3 years ago

I've had to avoid using the image block because images stop being responsive. I agree with @felixarntz that the "right" default for images is width=100% and height=auto. Otherwise I get distorted pictures. At the moment it seems to fill in the actual image size and then distorts it. One dimension or the the other always needs to be auto.

briandash2 commented 1 year ago

I've had to avoid using the image block because images stop being responsive. I agree with @felixarntz that the "right" default for images is width=100% and height=auto. Otherwise I get distorted pictures. At the moment it seems to fill in the actual image size and then distorts it. One dimension or the the other always needs to be auto.

I just realized that if you put the image block inside a column block set to 100% it fixes the responsive issue

joshuadelange commented 1 year ago

Hi all, I am wanting to add to this conversation coming from the perspective of using WP as a headless CMS.

We want the dimensions of the image in order to know the aspect ratio to avoid layout shifts. We use the REST API and then parse the Gutenberg blocks with the Gutenberg block parser package in our static site generator. Unfortunately this now lacks the width and height attributes.

We have considered extracting the images from the blocks and then bulk querying the media API, but as one of our projects contains 90.000+ posts, this adds an extra layer of complexity and slows down the build quite a bit.

It seems that having the image width and height present by default in the core/image attributes is a reasonable expectation. I'd love to hear your thoughts on this matter. We would love to open a PR ourselves to implement this if that would be desired.

joshuadelange commented 1 year ago

@oxyc @adamsilverstein @felixarntz Would love to hear your thoughts on the above comment. Let me know if you'd like more information.

asafm7 commented 8 months ago

A couple of notes: