WordPress / gutenberg

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

Image Block: Surface aspect-ratio tool for custom image dimensions #38990

Closed jasmussen closed 1 year ago

jasmussen commented 2 years ago

Many pattern designs rely on a specific dimension of an image in order to provide a compelling example. For example this circular avatar pattern:

circular avatar in a quote pattern

At the moment, if you mean to update this person with a photo of your own, unless you replace it with a new image of the same dimensions and crop, the pattern will be broken. In order to solve this, the pattern should be able to retain its dimensions and aspect-ratio, so even if you drag a landscape photo into the pattern, it will be correctly masked to fit.

In the user interface, we can surface such preset aspect ratios in a flyout menu. This keeps the width/height controls, as the Featured Image has:

ar plus width

One issue that exists with the featured image block in trunk is that if you apply both a width and a height, the aspect ratio essentially becomes non-functional. This shouldn't happen, so a few things we can do, both for Image, and for Featured Image as a followup.

We can, when you apply an aspect ratio, the width value is removed, set visually to "Auto" and disabled. You'd have to choose "original" aspect ratio to enable them again.

An image with an aspect ratio can work together with an explicit width, however, it just can't work with both width and height. So what we could do instead is to clear the aspect ratio back to "Original" if you fill out both width and height values. I.e.:

We can potentially pair this with a snackbar that notes why either is being cleared.


This ticket was updated May 10.

Previous version In the user interface, we can surface such preset aspect ratios in a dropdown. Shown here, 6 common presets: AR Dropdown The dropdown affords a rich visual shape representation of the aspect ratio numbers. When an aspect ratio is applied, the Height input field says "Auto", to indicate that its value is dynamically dependant on the width. If you then proceed to add a custom value to the height field after all, that gives you a custom aspect ratio: AR Dropdown, Custom This is simple to translate to CSS as the aspect ratio of a 540x320 image as shown in the example can simply be stated using `aspect-ratio: 540 / 320;`. See also [this codepen for how that can work responsively](https://codepen.io/joen/pen/mdBMwQR). To represent aspect ratios, especially as custom aspect ratios are possible, it would be useful if the shape icon was dynamically drawn based on each aspect ratio.

This ticket was updated Sep. 13.

See initial proposal When you set square image dimensions on a rectangular image, the image gets skewed (note, there's [a bug in the editor view](https://github.com/WordPress/gutenberg/issues/38381) at the moment). The skewed image is not that useful, and rarely what you want. Since we know the original aspect ratio, we can surface a scaling tool when a non-natural aspect ratio is shown, letting you choose the scaling type so that the image gets _masked_ instead of skewed: Masking i4 The tool would simply apply `object-fit: cover;` to the image, and work the same as how the Featured Image block does, letting you choose the scaling mode in a segmented control: Screenshot 2022-02-22 at 15 44 55 The ability to set the scaling mode would be very useful for patterns that perhaps include circular photos which when replaced with your own non-square images could become pill-shaped. Site Logo could also benefit from the maintaining the original aspect ratio. In order for masked image to scale responsively according to a new aspect ratio, the `aspect-ratio` property can be leveraged as is shown in [this codepen](https://codepen.io/joen/pen/mdBMwQR). See also: * #38068 * #38556 * #31373 * #38988 * #39452
mtias commented 2 years ago

Instead of prioritizing explicit width / height, I'd want to explore using the aspect ratio tool (similar to the hard-cropping one) used. We can apply it to the cover block as well. We can still support resizing while maintaining aspect ratio.

We should also do this in conjunction with #41142 to support the creation of pattern with placeholders much better.

richtabor commented 2 years ago

Instead of prioritizing explicit width / height, I'd want to explore using the aspect ratio tool

I agree.

It's a bit rudimentary, but I've experimented with aspect-ratio tied to image sizes — where selecting an aspect ratio calculates the proper height value from the width (and the object-fit crops it properly). Then when you resize, the height/width ratio is maintained.

https://user-images.githubusercontent.com/1813435/170721809-b948377d-f909-4969-becd-db3622bd2b0f.mp4

This is just an example, not the UI I think we should go with this implementation. :)

jasmussen commented 2 years ago

Nice, that looks good Rich. I took a quick stab at a remix based on your ideas:

aspect-ratio

As shortcuts to setting dimensions as well as applying object-fit: cover;, a single unified control is much simpler. I imagine the settings icon takes you to setting a custom aspect ratio. I tried a slew of icon styles, but ended up in the same place as you, ultimately with square, portrait and landscape options. Seems like a good baseline to start with?

The use of a segmented control is an open question. I tried a button-control as well, but that didn't flow quite as nicely:

option
isocialtish commented 2 years ago

I was just speaking with a customer who was requesting this feature specifically in the Post Featured Image block.

MaggieCabrera commented 2 years ago

Would the Aspect ratio options actually change the dimension values or would they change the aspect-ratio CSS value?

As shortcuts to setting dimensions as well as applying object-fit: cover;, a single unified control is much simpler.

How do you decide which object fit to use in which case? And what happens when the user provides its own dimensions, do we still see the object fit controls?

jasmussen commented 2 years ago

Would the Aspect ratio options actually change the dimension values or would they change the aspect-ratio CSS value?

I'd love for it to set aspect-ratio. It wouldn't work in all browsers, but as a progressive enhancement it would in new ones, and it would gracefully fall back.

How do you decide which object fit to use in which case? And what happens when the user provides its own dimensions, do we still see the object fit controls?

Stretch isn't that useful, and something you could accomplish on your own if you wanted to, by supplying off dimensions. Contain could have use cases, but I also think we could start without it, and then add a choice between the type of object-fit when we find that necessary.

MaggieCabrera commented 2 years ago

Would the Aspect ratio options actually change the dimension values or would they change the aspect-ratio CSS value?

I'd love for it to set aspect-ratio. It wouldn't work in all browsers, but as a progressive enhancement it would in new ones, and it would gracefully fall back.

But if dimensions are given, aspect ratio won't apply at all. And I think all images do have inline width and height values, I'd have to test it on the block. Still, controlling both dimensions and aspect ratio would be contradictory.

jasmussen commented 2 years ago

Just to step back for a moment, the main problem to solve with the aspect ratio presets is to enable you to drag and drop your big landscape photo into this pattern, and have the perfect circle and dimensions of the original pattern stick and be unchanged, just with your new updated photo:

Screenshot 2022-09-08 at 16 46 41

When you pick an aspect ratio, I suppose the 2nd value becomes determined by the first one, so we could potentially gray out one of the width/height input fields if need be.

I also made this codepen which dives into some of the responsiveness.

MaggieCabrera commented 2 years ago

When you pick an aspect ratio, I suppose the 2nd value becomes determined by the first one, so we could potentially gray out one of the width/height input fields if need be.

That sounds reasonable! and I agree that aspect-ratio is preferable, I was worried about confusing interactions with it.

Thanks for providing the extra context for this.

scruffian commented 2 years ago

When we get round to this we should add the same tools to the Post Featured Image block.

mtias commented 2 years ago

Can we explore a design that combines the number presentation of the crop tools and a more visual symbol of what the rectangle looks like?

jasmussen commented 2 years ago

Here's an iteration that focuses on a single aspect ratio dropdown with 6 preset sizes:

AR Dropdown

The dropdown affords a richer visual shape representation of the aspect ratio numbers. When an aspect ratio is applied, the Height input field says "Auto", to indicate that its value is dynamically dependant on the width.

If you then proceed to add a custom value to the height field after all, that gives you a custom aspect ratio:

AR Dropdown, Custom

This is simple to translate to CSS as the aspect ratio of a 540x320 image as shown in the example can simply be stated using aspect-ratio: 540 / 320;.

To represent aspect ratios, especially as custom aspect ratios are possible, it would be useful if the shape icon was dynamically drawn based on each aspect ratio.

jasmussen commented 2 years ago

I went ahead and updated the ticket name and description with the latest mockups.

richtabor commented 2 years ago

Here's an iteration that focuses on a single aspect ratio dropdown with 6 preset sizes:

Looking good. ✨

iamtakashi commented 1 year ago

When we get round to this we should add the same tools to the Post Featured Image block.

+1

At the moment, users need to upload a specific aspect of featured images to shape a certain layout.

pattyok commented 1 year ago

This is great. The first thing users will ask is where is the Focal Point Picker? It needs to be included in the solution.

mtias commented 1 year ago

Another thing I'd like to include in the scope for this issue is being able to define aspect ratios and width / height pairs as presets from a theme perspective. Then a theme can define a specific dimension pair for a header that shows up to be reused on featured images or plain image blocks (essentially, anywhere the aspect ratio / width control shows up). Aspect ratios should be definable as an abstract unit-less ratio of width and height (16:9) but also as discrete unit values (1920px / 1080px) which would represent the same aspect ratio but also set a default width and height.

SaxonF commented 1 year ago

@mtias just to confirm I understand the above. We would like to add something like the below to theme.json spec:

"aspectRatio":  [
   {
      "width": 16,
      "height": 9,
      "name": "16/9"
   },
   ...
]

Could also do [[16,9],[1:1],...] or ["16:9", "1:1", ...].

discrete unit values (1920px / 1080px) which would represent the same aspect ratio but also set a default width and height.

I'm wondering whether an alternative and a way to kill two birds with one stone is to enable adding custom width values to layout in theme.json. This was also mentioned here as a way to standardise containers etc across your site beyond content/wide. In the case of images you'd choose your aspect ratio and then choose your width driven by your theme with height set to auto.

In order to solve this, the pattern should be able to retain its dimensions and aspect-ratio, so even if you drag a landscape photo into the pattern, it will be correctly masked to fit.

This is an important point (acceptance criteria) to emphasise as we build this out. When replacing an image (e.g. via drag and drop) all existing values should be kept.

mtias commented 1 year ago

@SaxonF yes, though I'm not sure if we should make it additive (i.e. theme presets are appended to the default list) or an entire replacement. The former seems more correct to me given many of these aspect ratios are just table stakes and generally relevant.

I do think aspect ratio and width / height go hand in hand so we should aim for an approach that can combine its representation and use.

SaxonF commented 1 year ago

he former seems more correct to me given many of these aspect ratios are just table stakes and generally relevant.

@mtias Sounds good to me. Side note, it might be nice to standardise on whether we extend or replace options. It looks like in other cases such as typography->fontSize we replace? I like how Tailwind have an an explicit theme -> extend -> aspectRatio.

I do think aspect ratio and width / height go hand in hand so we should aim for an approach that can combine its representation and use.

Could we just lean on default block styles? In future a theme dev could also create block variations to tie together styles like borderRadius, aspectRatio, width.

"blocks": {
                 "core/post-featured-image": {
                 "aspectRatio": "var(--wp--preset--aspect-ratio--16-9)",
                 "layout": {
                       "width": "var(--wp--preset--layout--large)"
                 }
             }
              }

I don't feel too strongly about it and maybe both should be possible. If we did want to allow discrete unit values than we can just calculate aspect ratio and add default dimensions to dropdown option description.

image

richtabor commented 1 year ago

I'm not sure if we should make it additive (i.e. theme presets are appended to the default list) or an entire replacement.

I'm thinking additive. A theme should be able to add its own, but in doing so — don't replace the existing options.

Theme.json spec

The theme.json value should be a unit-less string, either an numeral value 1.7, or a ratio 16/9.

Although a theme should be able to remove core-provided default aspect ratios — similar to color palettes and gradients (defaultAspectRatios, set to true initially). How about this:

"settings": {
  "dimensions": {
    "aspectRatios":  [
       {
          "name": "Header",
          "slug": "header",
          "ratio": "16/11"
       }
     }
  ]
}

Visuals

Here's one way we could plug the existing aspect ratio selection pattern that we employ on the Image block's cropping mechanism, into the inspector of the Image block. I do think that this would be easier to implement initially on the Post Featured Image block though.

In this scenario, the theme has added two aspect ratios (21:9 and Header), which is added to a separate menu group.

1 2

It doesn't look/feel consistent, but we could clean it up quite a bit by adjusting the existing components:

proper

Reference

The existing aspect ratio mechanism within the Image block crop flow:

ref
SaxonF commented 1 year ago

@richtabor design wise it looks good to me with adjusted controls. I'm assuming we will want the dropdown used in image crop to use the same component.

Unrelated to this issue but worth discussing whether image dimensions belongs in settings or appearance especially with aspect ratio now part of it.

jasmussen commented 1 year ago

It doesn't look/feel consistent, but we could clean it up quite a bit by adjusting the existing components:

I like the cleaned up version. Doesnt seem like we need additional subheadings, ideally.

paaljoachim commented 1 year ago

I just had a client whom tested out the FSE Twenty Twenty Three for the first time and end up using Page Templates that the Query Loop used different size images. It is important to add the feature to the Featured Image block making it possible to have all featured images be cropped to use the same size.

richtabor commented 1 year ago

It is important to add the feature to the Featured Image block making it possible to have all featured images be cropped to use the same size.

@paaljoachim ✅ https://github.com/WordPress/gutenberg/pull/47854

paaljoachim commented 1 year ago

Great! Thanks for linking in the Add aspect-ratio to post featured image block PR, @richtabor I look forward to trying this out in Gutenberg plugin 15.2. To see how it works in the Query Loop with different size featured images.

iamtakashi commented 1 year ago

Is there any chance to add the aspect-ratio control to Site Logo block as well? It'd be nice if themes could specify the ratio for the logo. cc @richtabor

richtabor commented 1 year ago

Is there any chance to add the aspect-ratio control to Site Logo block as well?

We probably could, though I wouldn't say that most logos abide by a particular aspect-ratio. I think it only works particularly well if you wanted a Site Logo to be square.

Maybe we could have width/height dimensions with the linked functionality that's proposed in https://github.com/WordPress/gutenberg/issues/47963#issuecomment-1426019838 — though I'm not 100% sure. Especially with the funky width dimension control stuff referenced here: https://github.com/WordPress/gutenberg/issues/47979

iamtakashi commented 1 year ago

We probably could, though I wouldn't say that most logos abide by a particular aspect-ratio. I think it only works particularly well if you wanted a Site Logo to be square.

Yes, I'm thinking about an avatar like "logo" for a personal blog theme or a portfolio theme.

westonruter commented 1 year ago

Is there any chance to add the aspect-ratio control to Site Logo block as well? It'd be nice if themes could specify the ratio for the logo.

Incidentally, I just filed https://github.com/WordPress/gutenberg/issues/48608 to add a preview in the block settings sidebar for when the Site Logo is selected as a Site Icon. As it stands right now, the user doesn't know that the icon is a square and they don't know how the image will get cropped.

jasmussen commented 1 year ago

We probably could, though I wouldn't say that most logos abide by a particular aspect-ratio. I think it only works particularly well if you wanted a Site Logo to be square.

One way I think about aspect ratio is less about maintaining a particular aspect ratio, it's more about emulating the Figma image behavior, where the image is kind of like a background image set to cover. For site logo that might still be useful because a pattern could be designed to look square, just like the avatar example, and when you drop in your huge DSLR photo it goes splat. I do recognize that logos will naturally have different dimensions, so that might not be appropriate either, but with the proper reset and resize tools, it might be fine still? Not a strong opinion.

mtias commented 1 year ago

@westonruter yes, I was talking with @pablohoneyhoney and @richtabor that it'd be good in this case to also display the image in the sidebar and allow replacing from there, not just the block canvas. We are lacking some useful context that would display well there.

jasmussen commented 1 year ago

A quick pass based on conversations above, with three options. First off, we add the aspect ratio as a flyout menu, as I believe @richtabor has explored. And this keeps the width/height controls, as the Featured Image has:

ar plus width

One challenge with that, you can test this with the featured image block in trunk, is that if you apply both a width and a height, the aspect ratio essentially becomes moot. So an option would be to entirely absorb the width/height controls in the dropdown, and place them under "Advanced":

ar replaces width

Finally, here's an extension of that, which is slider based, making it overlap quite a bit with #48080:

slider based

Should we move forward with one of these?

richtabor commented 1 year ago

First off, we add the aspect ratio as a flyout menu, as I believe @richtabor has explored.

I lean this way. It's a marked improvement to what we have currently and fits in with the existing controls fine.

One challenge with that, you can test this with the featured image block in trunk, is that if you apply both a width and a height, the aspect ratio essentially becomes moot.

I don't think we should move them. How about when you apply an aspect ratio, the width value is removed, set visually to "Auto" and disabled. In trunk, you can't modify the width with aspect ratio applied anyhow.

Alternative is to not disable width, but if the value is changed from "Auto" then the aspect ratio value is cleared — you're breaking out of the ratio mold.

jasmussen commented 1 year ago

I don't think we should move them. How about when you apply an aspect ratio, the width value is removed, set visually to "Auto" and disabled. In trunk, you can't modify the width with aspect ratio applied anyhow.

Alternative is to not disable width, but if the value is changed from "Auto" then the aspect ratio value is cleared — you're breaking out of the ratio mold.

Agree that a good first step is bringing over the benefits from what's shipping in Featured Image to the Image block. It also does seem safe to keep width/height. The main issue as you note in the second item, is that ideally we avoid the situation where you have both an aspect ratio and a width/height. Clearing the aspect ratio if you fill out both seems like it could work, can even pair with a snackbar if need be: "Aspect ratio was cleared because bla".

I'll update the issue.

paaljoachim commented 1 year ago

A perspective.

These default Dimension settings are currently seen in the Post Featured Image block: Screenshot 2023-05-10 at 10 21 50

Adding the full Dimension panel to the Image block, Media & Text block etc as well as adding the additional Dimension tools to the Cover block could be very helpful. We would see a better consistency of equal settings for blocks that use images. @aaronrobertshaw

mtias commented 1 year ago

Yes, let's make sure we can bring the constrained fill / cover to image blocks, logo blocks, etc, and follow up on aspect ratio controls separately.

jasmussen commented 1 year ago

How about this?

ar plus width

The heuristic for when the contain/cover control gets added could be similar to that of the Featured Image block, i.e. it gets added as soon as it makes sense.

Note also that I omitted "Fill" from the segmented control here, as it appears low value in how it stretches the image. Do we actually want to keep that?

cbirdsong commented 1 year ago

This is great. The first thing users will ask is where is the Focal Point Picker? It needs to be included in the solution.

This was my immediate thought. People are going to use this on portraits and immediately get it cropping someone's head from the eyebrows down.

I would also raise this issue:

It is so wasteful to duplicate work across so many single-purpose blocks.

jasmussen commented 1 year ago

This was my immediate thought. People are going to use this on portraits and immediately get it cropping someone's head from the eyebrows down.

Agreed. I wonder, can we approach this as a separate issue? The control that exists on the Cover block has a rather huge resting footprint:

Screenshot 2023-05-11 at 09 09 02

I like to think that we can potentially put that in an ItemGroup/Flyout combo to reduce its footprint, and in doing so port it to both Featured Image and Image blocks separately. What do you think?

richtabor commented 1 year ago

@jasmussen I took the ideas and put them in today's Image block panel to theorize the simplest implementation for getting this into the 6.3 release. Here's the prototype.

What do you think of this approach, utilizing the existing Settings panel (where the block's image settings already are)?

https://github.com/WordPress/gutenberg/assets/1813435/5b5236eb-540c-4772-83a7-b0a41361070b

Key concepts:

Additional thoughts:

jasmussen commented 1 year ago

Prototype looks great, and agree with your takeaways, nice iteration. One question, though:

Changing height or width (either Input or ResizableBox) will set aspect ratio back to "Auto".

This is the tricky bit. Going back to the original issue, the challenge to solve is to allow you to create a pattern that looks like this:

... and then let you drop any odd image into that circular avatar dropzone to update it, and have it not explode. In other words, you need to be able to combine a custom width and height with the cover value, and if I'm not misunderstanding, then changing this back to "Auto" would break that ability.

richtabor commented 1 year ago

Good point. We would technically need to separate image replacement from image resizing (even though the attributes do change when you replace an image). 🤔

richtabor commented 1 year ago

So you're thinking if set to "cover" then the aspect ratio is maintained when replacing? Or we implement the whole syncing of height and width? https://github.com/WordPress/gutenberg/issues/47963#issuecomment-1426019838

jasmussen commented 1 year ago

Could we do it so an image replacement (drop one image on top of another) never changes its dimensions? It seems like when I design the pattern and set the image to 100x100+cover, I should be able to trust that's and remains.

If the main question is "when do we show the cover/contain" control, can we do that whenever dimensions are entered that aren't the intrinsic ones from the image?

Worst case, we could have a "Custom" aspect ratio, which is just width/height. Like, if you set your image to 400x200, we apply aspect-ratio: 400/200;, and it works.

richtabor commented 1 year ago

Worst case, we could have a "Custom" aspect ratio, which is just width/height. Like, if you set your image to 400x200, we apply aspect-ratio: 400/200;, and it works.

I'm ok with this.

If the main question is "when do we show the cover/contain" control, can we do that whenever dimensions are entered that aren't the intrinsic ones from the image?

What about if aspect ratio is not Auto/Original, then the cover/contain control is available?

jasmussen commented 1 year ago

What about if aspect ratio is not Auto/Original, then the cover/contain control is available?

That works.

scruffian commented 1 year ago

Now that https://github.com/WordPress/gutenberg/pull/51545 is merged I think we can close this.

rfischmann commented 10 months ago

Why were the 25%/50%/75%/100%/Reset buttons removed since WordPress 6.3? They were so useful… 😓

jasmussen commented 3 weeks ago

Here's a mockup showing how we might reintroduce those 25/50/75/100% shortcuts.