[csswg-drafts] [css-images] @image rule for manipulating images (#6807)

LeaVerou has just created a new issue for https://github.com/w3c/csswg-drafts:

== [css-images] @image rule for manipulating images ==
There have been a lot of issues over the years about manipulating an existing image in some way before it's used by CSS. 
Some examples from a quick search:

- https://github.com/w3c/csswg-drafts/issues/4706
- https://github.com/w3c/csswg-drafts/issues/3183
- https://github.com/w3c/csswg-drafts/issues/4996
- https://github.com/w3c/csswg-drafts/issues/2364

There are also a bunch of features we defined and never got implementor interest, such as [`filter()`](https://caniuse.com/css-filter-function) or `background-image-transform`. 

With my author hat on, I've also stumbled on use cases where I wanted to transform images, even in simple ways such as being able to override an image's intrinsic dimensions while setting `background-size` to a *different* size. Or just essentially setting `object-fit: cover` on a background-image so I could use `background-size: <percentage>{2}` without distortion.

What if we could address all of these in one fell swoop by creating a new at-rule to define images that CSS can then access through the `image()` function?

Something like:

```css
@image --foo {
 src: url("foo.png");
 aspect-ratio: 1 / 1;
 width: 100vw;
 object-fit: cover;
 filter: blur(10px);
 opacity: .5;
 transform: rotate(5deg);
}
```

Which would then be used like:

```css
background: image(--foo);
border-image: image(--foo); /* etc */
```

Since any `<image>` is allowed in `src`, this can be used to create variants of the same image:

```css
@image --foo-larger {
 src: image(--foo);
 scale: 2;
}
```

The descriptors I envision being allowed in `@image` are:

- `src: <image>`: Mandatory, sets the image we are manipulating. Can be any CSS `<image>` including gradients etc.
- `width`, `height`, `inline-size`, `block-size` to override intrinsic dimensions. Percentages resolve relative to original intrinsic size OR viewport (not sure which one makes more sense; at least the latter is always available)
- `aspect-ratio` to override intrinsic aspect ratio
- `margin` to add (transparent) spacing around image
- `object-fit`
- `opacity`
- `filter`
- `transform` and friends (`translate`, `scale`, `rotate`)
- `clip-path`
- `mask`

The `src` descriptor could also support setting the source to a different image depending on resolution, as a nicer to read alternative of [`image-set()`](https://drafts.csswg.org/css-images-4/#image-set-notation). 

Instead of:
```css
background-image: image-set( "foo.png" 1x,
                             "foo-2x.png" 2x,
                             "foo-print.png" 600dpi );
```

it would be:

```css
@image --foo {
 src: url("foo.png") 1x
           url("foo-2x.png") 2x,
          url("foo-print.png") 600dpi;
}
```

In fact, it would be nice if one could specify *different* descriptors depending on resolution, so that people could do things like:

```css
@image --foo {
 src: url("foo.png") 1x;
}

@image --foo {
 src: url("foo.png") 2x;
 filter: blur(10px);
}
```

In the future, we may even want to add descriptors providing a fallback, color space, or other metadata about images.

The advantages of this syntax I see are:
* It solves the problem using syntax that authors are already familiar with. Instead of needing to learn different ad hoc ways of transforming images that are specific to each use case, they only need to learn one `@image` rule and then they can even guess the descriptors they need as they are essentially a subset of existing CSS properties.  
* It's designed to be easy to extend in the future to solve more image manipulation use cases. 
* While lengthier, it's nicer to read than functional syntax like `filter()`. Compare:

```css
background-image: filter(url("foo.png"), hue-rotate(135deg) opacity(.5));
```

with:

```css
@image --foo {
 src: url("foo.png");
 filter: hue-rotate(135deg);
 opacity: .5;
}

/* ... */

background-image: image(--foo); 
```

The main downsides I see :

- With functional syntaxes like `filter()` it's possible to use `var()` references trivially, and interpolation works out of the box. It's unclear if it's possible to have `var()` references resolve at the point of usage of the image, and interpolation may be trickier to define (but possible). 
- It has the same issues as `@property` wrt to global scope and shadow DOM (but that applies to most at-rules anyway and we likely need to fix it for all of them)

Please view or discuss this issue at https://github.com/w3c/csswg-drafts/issues/6807 using your GitHub account


-- 
Sent via github-notify-ml as configured in https://github.com/w3c/github-notify-ml-config

Received on Tuesday, 9 November 2021 19:02:07 UTC