-
Notifications
You must be signed in to change notification settings - Fork 746
Description
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:
- [css-backgrounds-4]
background-filter
#4706 - Add background-rotate property that we just have to rotate the background without affecting the text and only one layer #3183
- Suggestion: “background-opacity” CSS property (as suggested by CSS-Tricks.com). #4996
- [css-backgrounds-4] Transformation of background images #2364
There are also a bunch of features we defined and never got implementor interest, such as filter()
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:
@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:
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:
@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 ratiomargin
to add (transparent) spacing around imageobject-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()
.
Instead of:
background-image: image-set( "foo.png" 1x,
"foo-2x.png" 2x,
"foo-print.png" 600dpi );
it would be:
@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:
@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:
background-image: filter(url("foo.png"), hue-rotate(135deg) opacity(.5));
with:
@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 usevar()
references trivially, and interpolation works out of the box. It's unclear if it's possible to havevar()
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)