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

[css-images] [css-gcpm] Overloaded definitions of element() #1981

Open
kosek opened this issue Nov 14, 2017 · 11 comments
Open

[css-images] [css-gcpm] Overloaded definitions of element() #1981

kosek opened this issue Nov 14, 2017 · 11 comments

Comments

@kosek
Copy link

kosek commented Nov 14, 2017

Hi,

I have noticed that the following two modules define element() function/notation in the completely different way:

https://www.w3.org/TR/css-images-4/#element-notation
https://www.w3.org/TR/css-gcpm-3/#funcdef-element

I see that css-images define element() for use in properties that can reference image whereas css-gcpm currently uses element() for content property. But using same function name for different purposes and with different function arguments is very confusing for CSS authors.

Each function should be named differently or their behaviour should be unified.

Jirka

@SebastianZ
Copy link
Contributor

SebastianZ commented Nov 14, 2017

This name conflict is already filed as issue 6 in CSS Images 4.

Sebastian

@SebastianZ
Copy link
Contributor

SebastianZ commented Nov 15, 2017

So far I see five different (mostly non-exclusive) solutions for this conflict:

1. Define running elements in HTML

Instead of CSS, running elements could be defined within HTML, e.g. via a <running> element, as they have some associated semantic.

Doing so would allow to style them without the need for the running() and element() functions currently defined in the CSS GCPM Module.

Example:

<running position="top-center">
  <h1>My awesome title</h1>
  <h2>With a great subtitle</h2>
</running>
@page {
  @top-center { color: #808080; }
}

2. Rename the element() function in the CSS GCPM Module

If defining the element outside of CSS is not an option, another solution would be to simply rename the element() function within the CSS GCPM Module. It could even be called running(), so definition and usage would be consistent.

Example:

@page {
  @top { content: running(header); }
}

h1 { position: running(header); color: #808080; }

3. Merge the element() functionality defined in the CSS Images Module into image()

As the use case within CSS Images is to use the element as an image, it may also make sense to incorporate the syntax of the element() function into the image() function. Doing so, the syntax of the <image-src> value used in image() could be extended to look like this:

<image-src> = [ <url> | <id-selector> ]

Example:

  background-image: image(#header);
}

h1 { position: running(header); color: #808080; }

4. Let one definition of element() serve both use cases

Only define element() once, e.g. just let it take <id-selector>s. This would make the running() function redundant, because the element would be identified by the selector instead of a custom identifier.

Example:

@page {
  @top-center { content: element(#header); color: #808080; }
}

5. Define the element within the margin at-rule instead via content

Instead of defining the contents of the page margins via the content property they could be defined as value for the margin at-rule.

Examples:

@page {
  @top-center #header { color: #808080; }
}
@page {
  @top-center "My awesome title" { color: #808080; }
}

Sebastian

@kosek
Copy link
Author

kosek commented Nov 15, 2017

I will let WG and editors to decide what is the best way to fix this.

Just for the record element() in GCPM spec has been used earlier than in CCS Images and has more shipping implementations already. So it makes more sense to rename it in CSS Images to something like element-snapshot() or whatever.

It's good that issue is mentioned in the spec text, I have missed it, I have only searched GitHub issues before filling new one.

@SebastianZ
Copy link
Contributor

Just for the record element() in GCPM spec has been used earlier than in CCS Images...

That's correct. The element() function was first mentioned in a GCPM Working Draft back in 2006, while the first mention in CSS Images was in a 2011 Working Draft. Having said that, this doesn't have any influence on which syntax to decide on.

...and has more shipping implementations already.

As far as I can see on MDN and caniuse and my own tests, the only existing implementation of this is in Firefox and that one is prefixed. And that -moz-element() function uses the CSS Images syntax. There are no implementations of the unprefixed version yet, so everything is still open for discussion.

But you're right that also the definition within CSS Images could be renamed. Thinking further about that, I've added a fifth solution, which suggests to merge the syntax of the element() function into image().
In my eyes, that would actually be a very clean solution, because image() is already meant to reference or create images.

Sebastian

@kosek
Copy link
Author

kosek commented Nov 16, 2017

MDN/Caniuse are not good sources for checking implementation status of GCPM module. Browsers have poor printing support but GCPM and unprefixed element() function is already implemented in various formatting engines, e.g.:

https://www.antennahouse.com/product/ahf64/ahf-css6.html#css3-functions
https://www.princexml.com/doc/functions/#css-functions

@faceless2
Copy link

faceless2 commented Oct 2, 2020

Another solution would be to merge element() with url(), rather than with image().

  • SVG already uses fill: url(#patternid) to reference a <pattern> element.
  • css-masking-1 uses mask: url(#maskid) to reference a <mask> element.
  • css-fill-stroke proposes a fill-image property which is to be the same as background-image - i.e. it takes a URL. For consistency with SVG this really has to allow a url() to a <pattern> element.

In all these cases the functionality is exactly the same as what's proposed with element().

It seems weird that while I can fill: url(#patternid) in SVG, in CSS I would have to do background-image: element(#patternid) to achieve the same thing (as suggested by an example in css-images-4).

And what about mask: element(#maskid)? It's a synonym for url(#maskid)?

@cdoublev
Copy link
Collaborator

cdoublev commented Dec 17, 2020

I found this issue after searching for the reasons why as a front-end dev, I can use url(svg-path#fragment) for almost any property accepting a url(), but not url(#svg-child-element) except for some properties (where url refers to a resource versus. an image?) as demonstrated by @faceless2.

While searching for those reasons, I discovered element() and image(), resulting in more confusion. element() doesn't seem to provide anything more than url() for images, and the extra features of image() seem also superflous.

@SebastianZ
Copy link
Contributor

@faceless2 wrote:

Another solution would be to merge element() with url(), rather than with image().

Obviously you only refer to the definition within CSS Images 4, not the one in CSS GCPM 3.

That idea sounds intriguing and I really like it, though reusing url() also has a downside. It's not feature-detectable because URLs with anchors are already valid. I.e. background-image: url(#x); is parsed by user agents, and therefore an author cannot use @supports (background-image: url(#x)) { ... } to check whether the user agent supports using an element as an image or not.

Sebastian

@SebastianZ
Copy link
Contributor

@cdoublev wrote:

and the extra features of image() seem also superflous.

The extra features come "for free" because image() also takes images referenced via url(). So, in that regard it makes sense to merge element() into url().

Though I just realized another little downside of merging it into url(). element() (or selector(), see #5811) might allow different selectors than just ID selectors in the future. Those can't be expressed via url().

Sebastian

@cdoublev
Copy link
Collaborator

cdoublev commented Dec 21, 2020

Thanks, I hadn't noticed that image() can take a url().

I'm not sure that selecting an element via other types of selectors would be an upside. An image value referencing an element will always resolves to a single (~= unique, like an ID) target, while other selectors are more often used to select multiple targets.

@SebastianZ
Copy link
Contributor

@cdoublev wrote:

I'm not sure that selecting an element via other types of selectors would be an upside. An image value referencing an element will always resolves to a single (~= unique, like an ID) target, while other selectors are more often used to select multiple targets.

You might be surprised that even ID selectors can match multiple elements, see https://jsfiddle.net/SebastianZ/qumshra7/. So the algorithm behind that feature already needs to take that into account and pick the first matched element. The spec. currently mentions this as "The ID is first looked up in the elementSources map".
This basically means the logic works similarily to document.querySelector() in JavaScript to pick just the first matched element.

But anyway, I am not completely against reusing url() for this purpose, though as I wrote earlier, the main downside is the missing feature detectability via @supports, which means you can't provide a fallback without JavaScript if it doesn't work in a user agent.

Also note that both solutions are non-exclusive.

Sebastian

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment