Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Images should always provide dimensions #23244

Open
felixarntz opened this issue Jun 17, 2020 · 14 comments
Open

Images should always provide dimensions #23244

felixarntz opened this issue Jun 17, 2020 · 14 comments
Labels
Backwards Compatibility Issues or PRs that impact backwards compatability [Block] Gallery Affects the Gallery Block - used to display groups of images [Block] Image Affects the Image Block [Block] Media & Text Affects the Media & Text Block [Feature] Media Anything that impacts the experience of managing media [Package] Block library /packages/block-library [Type] Enhancement A suggestion for improvement.

Comments

@felixarntz
Copy link
Member

felixarntz commented Jun 17, 2020

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:

  • core/image
  • core/gallery
  • core/media-text
  • (did I miss any?)

Related

@felixarntz felixarntz added [Feature] Media Anything that impacts the experience of managing media Backwards Compatibility Issues or PRs that impact backwards compatability [Package] Block library /packages/block-library [Block] Image Affects the Image Block [Block] Gallery Affects the Gallery Block - used to display groups of images [Block] Media & Text Affects the Media & Text Block labels Jun 17, 2020
@oxyc
Copy link
Member

oxyc commented Jun 17, 2020

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
Copy link
Member

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
Copy link
Member

oxyc commented Jun 18, 2020

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);
} 

WICG/intrinsicsize-attribute#16 (comment) 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
Copy link
Member Author

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
Copy link
Contributor

azaozz commented Jun 27, 2020

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
Copy link
Member

oxyc commented Aug 6, 2020

Here's an earlier issue regarding this as well #6652

@dotsam
Copy link

dotsam commented Aug 26, 2020

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

&.alignfull img,
&.alignwide img {
width: 100%;
}

@sabernhardt
Copy link
Contributor

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):

img {
max-width: 100%;
height: auto;
}

Front-end image block:

.wp-block-image {
// The image block is in a `figure` element, and many themes zero this out.
// This rule explicitly sets it, to ensure at least some bottom-margin in the flow.
margin-bottom: 1em;
img {
max-width: 100%;
}

@adamsilverstein
Copy link
Member

@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
Copy link

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
Copy link

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
Copy link

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
Copy link

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

@jordesign jordesign added the [Type] Enhancement A suggestion for improvement. label Aug 24, 2023
@asafm7
Copy link

asafm7 commented Jan 14, 2024

A couple of notes:

  • Having explicit width and height attributes is necessary for features like Jetpack Image CDN (Photon) to work. (currently, Photon isn't very helpful with blocks).
  • Currently, width and height settings are defined as inline style. This can cause responsiveness issues. For example, in this product loop, the featured images overlap in narrow screens once given a width:
    image
  • It might be worth auto-calculating the height once a width is set (and vice versa) according to the chosen aspect ratio. This way both width and height attributes are always present.
  • Images in galleries currently don't have dimensions settings.
  • Maybe have a fallback using the theme's contentSize, for not loading unnecessary huge images. In galleries, this fallback can be divided by the number of columns.
  • Just to be clear, I'm referring to the custom width and height fields, and not the built-in resolutions drop-down.
  • Combined with tools like Jetpack Image CDN, this can be a performance boost

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Backwards Compatibility Issues or PRs that impact backwards compatability [Block] Gallery Affects the Gallery Block - used to display groups of images [Block] Image Affects the Image Block [Block] Media & Text Affects the Media & Text Block [Feature] Media Anything that impacts the experience of managing media [Package] Block library /packages/block-library [Type] Enhancement A suggestion for improvement.
Projects
None yet
Development

No branches or pull requests