Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

proposal: using arbitrary elements as the source for CSS backgrounds

47 views
Skip to first unread message

Robert O'Callahan

unread,
Jul 13, 2009, 10:24:07 PM7/13/09
to
Webkit has a feature to use anonymous canvas elements as CSS backgrounds:
http://webkit.org/blog/176/css-canvas-drawing/

I thought it made more sense to let *any* element, not just a canvas, be
usable as a CSS background (which also enables reflections, thumbnails
of slides, etc), and implemented that:
http://weblogs.mozillazine.org/roc/archives/2008/07/the_latest_feat.html

I ended up not porting it to trunk, because using url(#foo) syntax to
refer to an element in the Web page from a stylesheet was just wrong.
Also I wanted a more flexible setup; sometimes instead of referring to
the content by ID you would prefer to access a particular DOM node from
script. E.g. you might have a hidden IFRAME and want to render a
particular node in that IFRAME. People have been asking for this
functionality.

So here's a new proposal:
1) A new CSS image type, -moz-element(foo). Normally 'foo' is the ID of
an element in the document to which the stylesheet applies.
2) A new DOM API, window.mozSetImageElement("foo", node). The node is
used instead of the element with ID foo when -moz-element(foo) is used.

Elements which expose a natural image --- <img>, <video> and <canvas>
--- could be used with mozSetImageElement even when they're outside a
document. That gives you the ability to emulate Webkit's canvas feature
perfectly.

For an element in a document, the instrinsic size of the generated image
is the size of the bounding box (getBoundingClientRect) in CSS pixels.
For an element not in a document, the intrinsic size of the generated
image is the intrinsic size of the element, if it's an <img>, <video> or
<canvas> (otherwise nothing is rendered).

This would let us do things like a tab preview window with live tab
previews, by filling it with elements using
background-image:-moz-element(fooNNN); background-size:..., plus some
calls to window.mozSetImageElement("fooNNN", browserElementNNN).

Comments appreciated. The code from my bling-branch is already very
close to this, so if this sounds good and useful it should be fairly
easy for me or someone else to dig out the code, bring it forward to the
trunk, change the syntax and add the DOM API.

Rob

Mike Shaver

unread,
Jul 13, 2009, 10:47:23 PM7/13/09
to Robert O'Callahan, dev-pl...@lists.mozilla.org
On Mon, Jul 13, 2009 at 10:24 PM, Robert O'Callahan<rob...@ocallahan.org> wrote:
> So here's a new proposal:

Sounds pretty useful for things we have coming up around tab preview
and other content munging -- maybe a good student/intern project?

Would it also work for stuff like border-image and list-image?

Mike

Sheppy

unread,
Jul 14, 2009, 12:56:25 AM7/14/09
to
On Jul 13, 10:24 pm, Robert O'Callahan <rob...@ocallahan.org> wrote:

> This would let us do things like a tab preview window with live tab
> previews, by filling it with elements using
> background-image:-moz-element(fooNNN); background-size:..., plus some
> calls to window.mozSetImageElement("fooNNN", browserElementNNN).

This sounds crazy useful to me.

Eric Shepherd
Developer Documentation Lead
Mozilla Corporation
http://www.bitstampede.com/

Dion Almaer

unread,
Jul 14, 2009, 1:09:15 AM7/14/09
to Sheppy, dev-pl...@lists.mozilla.org
This is extremely cool. It will allow us to keep nice clean markup that we
unobtrusively add new richness too.

> _______________________________________________
> dev-platform mailing list
> dev-pl...@lists.mozilla.org
> https://lists.mozilla.org/listinfo/dev-platform
>

Ehsan Akhgari

unread,
Jul 14, 2009, 5:20:47 AM7/14/09
to Robert O'Callahan, dev-pl...@lists.mozilla.org
On Tue, Jul 14, 2009 at 6:54 AM, Robert O'Callahan <rob...@ocallahan.org>wrote:

> So here's a new proposal:
> 1) A new CSS image type, -moz-element(foo). Normally 'foo' is the ID of an
> element in the document to which the stylesheet applies.
> 2) A new DOM API, window.mozSetImageElement("foo", node). The node is used
> instead of the element with ID foo when -moz-element(foo) is used.


I think having a new DOM API for this purpose can be useful, but it's not
ideal. We should preferably allow designers who only know CSS or only have
access to the stylesheets on a web page to use this feature without forcing
them to do half of their work in JS. In addition, some users may prefer to
browse the web without JS enabled (for example with NoScript). Further
more, there are use cases where we shouldn't allow script execution at all
(example: rendering email messages), so the proposed API would be useless in
those situations. This API in the current form might not be that useful for
theme developers for XUL applications as well, because they would be limited
to the identifiers registered by the chrome code which is out of their
control.

I have two proposals, which may at least serve as a ground point for a full
CSS-based feature:

a) Accept a full CSS3 selector as -moz-element's argument. This way,
authors could write:

div#main {
background-image: -moz-element(div#sidebar p.foo > img:first-of-type);
}

b) Invent a new CSS rule in order to "mark" elements for use with
-moz-element, such as:

div#main {
background-image: -moz-element(foo);
}

div#sidebar p.foo > img:first-of-type {
-moz-element-id: foo;
}

I think -moz-element-id should not be cascaded, and we should specify what
happens when the selectors in each case match more than one element (for
example, selecting the first element in DOM order).

I personally prefer the former approach because by reading a single rule you
will know everything that there is to know about the rule, but I'm not sure
if implementing it is possible without insane changes to the CSS parser.
Incidentally, this syntax is an extension of the url(#foo) syntax, because
#foo is a valid CSS3 selector.


The obvious downside of this proposal is that CSS3 selectors can only
reference elements inside the same document, so elements not bound to a
document or for example elements inside IFRAMEs can't be targetted in this
way. In that case, we can direct users to the mozSetImageElement API that
you proposed. This way, we would have an API which is designed to deal with
these special cases, but users are still free to only use this API if they
want.


Comments/suggestions/criticisms appreciated.

--
Ehsan
<http://ehsanakhgari.org/>

Robert O'Callahan

unread,
Jul 14, 2009, 5:39:41 AM7/14/09
to
On 14/7/09 9:20 PM, Ehsan Akhgari wrote:
> On Tue, Jul 14, 2009 at 6:54 AM, Robert O'Callahan<rob...@ocallahan.org>wrote:
>> So here's a new proposal:
>> 1) A new CSS image type, -moz-element(foo). Normally 'foo' is the ID of an
>> element in the document to which the stylesheet applies.
>> 2) A new DOM API, window.mozSetImageElement("foo", node). The node is used
>> instead of the element with ID foo when -moz-element(foo) is used.
>
> I think having a new DOM API for this purpose can be useful, but it's not
> ideal. We should preferably allow designers who only know CSS or only have
> access to the stylesheets on a web page to use this feature without forcing
> them to do half of their work in JS.

It is usable without JS as proposed. E.g.

<body style="background: repeat -moz-element(v)">
<div style="height:0; overflow:hidden">
<video id="v" autoplay src="rickroll.ogv"></video>
</div>
</body>

In practice, ensuring useful elements have IDs shouldn't be a big issue,
I would have thought. It's certainly far, far easier to implement an ID
match than selectors here.

Rob

Robert O'Callahan

unread,
Jul 14, 2009, 5:57:09 AM7/14/09
to
Another use without JS, just for the record:

#thumbnails > div { background-size:cover; }

<div id="slide1">...</div>
<div id="slide2">...</div>
<div id="slide3">...</div>
...
<div id="thumbnails">
<div style="background-image: -moz-element(slide1);"></div>
<div style="background-image: -moz-element(slide2);"></div>
<div style="background-image: -moz-element(slide3);"></div>
</div>

Rob

Ehsan Akhgari

unread,
Jul 14, 2009, 6:12:30 AM7/14/09
to Robert O'Callahan, dev-pl...@lists.mozilla.org
On Tue, Jul 14, 2009 at 2:09 PM, Robert O'Callahan <rob...@ocallahan.org>wrote:

> On 14/7/09 9:20 PM, Ehsan Akhgari wrote:
>
>> On Tue, Jul 14, 2009 at 6:54 AM, Robert O'Callahan<rob...@ocallahan.org
>> >wrote:
>>
>>> So here's a new proposal:
>>> 1) A new CSS image type, -moz-element(foo). Normally 'foo' is the ID of
>>> an
>>> element in the document to which the stylesheet applies.
>>> 2) A new DOM API, window.mozSetImageElement("foo", node). The node is
>>> used
>>> instead of the element with ID foo when -moz-element(foo) is used.
>>>
>>
>> I think having a new DOM API for this purpose can be useful, but it's not
>> ideal. We should preferably allow designers who only know CSS or only
>> have
>> access to the stylesheets on a web page to use this feature without
>> forcing
>> them to do half of their work in JS.
>>
>
> It is usable without JS as proposed. E.g.
>
> <body style="background: repeat -moz-element(v)">
> <div style="height:0; overflow:hidden">
> <video id="v" autoplay src="rickroll.ogv"></video>
> </div>
> </body>


Yes, of course. But the DOM API you proposed was supposed to cover the
cases where ensuring that an has an ID is not feasible, right? My proposal
was based on trying to extend that idea without resorting to a JS API as
much as possible.


> In practice, ensuring useful elements have IDs shouldn't be a big issue, I
> would have thought.


I think we can't limit the CSS-only syntax to IDs by this reasoning. Of
course implementation feasibility is an obvious concern here as well.


> It's certainly far, far easier to implement an ID match than selectors
> here.


How hard would parsing the full selector and matching it would be? I'm not
really sure because I don't know the code, but I can only assume that we
should already have a selector parsing and matching API internally which we
probably used in implementing the query selectors API. Is that a correct
assumption?

--
Ehsan
<http://ehsanakhgari.org/>

Robert O'Callahan

unread,
Jul 14, 2009, 6:29:05 AM7/14/09
to
On 14/7/09 10:12 PM, Ehsan Akhgari wrote:
> Yes, of course. But the DOM API you proposed was supposed to cover the
> cases where ensuring that an has an ID is not feasible, right? My proposal
> was based on trying to extend that idea without resorting to a JS API as
> much as possible.

It's not so much for working with elements where the author just forgot
to give them an ID, as for working with elements in specific
subdocuments, working with elements that aren't in a document, and
writing script library APIs that work with a passed-in element reference
where you may not want to change the ID of that element. None of those
scenarios would be helped by support for general selectors.

Maybe there are some use cases with missing IDs that my proposal leaves
uncovered, but I am not convinced they are more than a tiny fraction of
the space, and I don't think they are worth worrying about now.

> How hard would parsing the full selector and matching it would be? I'm not
> really sure because I don't know the code, but I can only assume that we
> should already have a selector parsing and matching API internally which we
> probably used in implementing the query selectors API. Is that a correct
> assumption?

That's correct. However, handling dynamic changes would be very
difficult with your model. The rule setting the background-image for an
element would depend on two selector chains: the selectors for the rule,
and the selectors in the special property value.

Rob

Axel Hecht

unread,
Jul 14, 2009, 6:38:05 AM7/14/09
to

I understood this to be mostly for JS that just creates image tags or
the like, and never adds them to the document in question.

>> In practice, ensuring useful elements have IDs shouldn't be a big issue, I
>> would have thought.
>
>
> I think we can't limit the CSS-only syntax to IDs by this reasoning. Of
> course implementation feasibility is an obvious concern here as well.
>
>
>> It's certainly far, far easier to implement an ID match than selectors
>> here.
>
>
> How hard would parsing the full selector and matching it would be? I'm not
> really sure because I don't know the code, but I can only assume that we
> should already have a selector parsing and matching API internally which we
> probably used in implementing the query selectors API. Is that a correct
> assumption?

I think that ID is actually a pretty good choice, as it only selects a
single element. Otherwise we're up for some interesting questions:

Say you a background selector matching 3 elements inside a CSS rule that
applies to 3 elements. Which background would you apply to which element?

You could make some more or less arbitrary rule on how to select a
single element to apply for all, but the markup-way to denote that is to
restrict the selector to IDs, IMHO.

Axel

Dao

unread,
Jul 14, 2009, 10:52:39 AM7/14/09
to
> 2) A new DOM API, window.mozSetImageElement("foo", node). The node is
> used instead of the element with ID foo when -moz-element(foo) is used.

Would that work with elements from different documents? For instance,
could a video from the content area be rendered in a full-screen window?

Zack Weinberg

unread,
Jul 14, 2009, 12:29:31 PM7/14/09
to Robert O'Callahan, dev-pl...@lists.mozilla.org
Robert O'Callahan <rob...@ocallahan.org> wrote:

> On 14/7/09 10:12 PM, Ehsan Akhgari wrote:
> > Yes, of course. But the DOM API you proposed was supposed to cover
> > the cases where ensuring that an has an ID is not feasible,
> > right? My proposal was based on trying to extend that idea without
> > resorting to a JS API as much as possible.
>
> It's not so much for working with elements where the author just
> forgot to give them an ID, as for working with elements in specific
> subdocuments, working with elements that aren't in a document, and
> writing script library APIs that work with a passed-in element
> reference where you may not want to change the ID of that element.
> None of those scenarios would be helped by support for general
> selectors.
>
> Maybe there are some use cases with missing IDs that my proposal
> leaves uncovered, but I am not convinced they are more than a tiny
> fraction of the space, and I don't think they are worth worrying
> about now.

If we define the syntax to be -moz-element(#id) instead of
-moz-element(id), then if in the future we ever want to allow more
complex selectors there is no backward compatibility problem.

zw

Ehsan Akhgari

unread,
Jul 14, 2009, 12:53:14 PM7/14/09
to Zack Weinberg, dev-pl...@lists.mozilla.org, Robert O'Callahan
On Tue, Jul 14, 2009 at 8:59 PM, Zack Weinberg <zwei...@mozilla.com>wrote:

> Robert O'Callahan <rob...@ocallahan.org> wrote:
>

> > On 14/7/09 10:12 PM, Ehsan Akhgari wrote:
> > > Yes, of course. But the DOM API you proposed was supposed to cover
> > > the cases where ensuring that an has an ID is not feasible,
> > > right? My proposal was based on trying to extend that idea without
> > > resorting to a JS API as much as possible.
> >
> > It's not so much for working with elements where the author just
> > forgot to give them an ID, as for working with elements in specific
> > subdocuments, working with elements that aren't in a document, and
> > writing script library APIs that work with a passed-in element
> > reference where you may not want to change the ID of that element.
> > None of those scenarios would be helped by support for general
> > selectors.
> >
> > Maybe there are some use cases with missing IDs that my proposal
> > leaves uncovered, but I am not convinced they are more than a tiny
> > fraction of the space, and I don't think they are worth worrying
> > about now.
>

> If we define the syntax to be -moz-element(#id) instead of
> -moz-element(id), then if in the future we ever want to allow more
> complex selectors there is no backward compatibility problem.
>

This sounds like a great idea. We can even special case the #foo syntax to
not hit the selector engine if it proves to be a bottleneck in performance
later on when we have full selector support.

--
Ehsan
<http://ehsanakhgari.org/>

Dave Townsend

unread,
Jul 14, 2009, 1:26:43 PM7/14/09
to

Would you intend to still handle dynamic updating even with just a plain
ID. So if I changed the ID of an element in JavaScript would te
background change accordingly?

Boris Zbarsky

unread,
Jul 14, 2009, 2:47:18 PM7/14/09
to
Dave Townsend wrote:
> Would you intend to still handle dynamic updating even with just a plain
> ID. So if I changed the ID of an element in JavaScript would te
> background change accordingly?

Yes. We already have infrastructure for this (e.g. this is how all of
the SVG paint server stuff works).

-Borsi

Robert O'Callahan

unread,
Jul 14, 2009, 3:19:20 PM7/14/09
to

Yes.

Rob

Robert O'Callahan

unread,
Jul 14, 2009, 3:21:19 PM7/14/09
to

That sounds reasonable. Apart from anything else it makes it clear that
it's an ID reference. It might mislead people into thinking they can put
a full URI there, but if they try it, it won't work, so I don't think
that's a problem.

Rob

moz....@windingwisteria.com

unread,
Jul 14, 2009, 4:39:35 PM7/14/09
to dev-platform

What's the behavior in nested situations?

<body id="main">
...
<div style="background-image: -moz-element(main);">...<div>
...

John Daggett

Robert O'Callahan

unread,
Jul 14, 2009, 8:27:03 PM7/14/09
to

My branch takes the approach that you can only traverse an element
reference once in a given stack of paints. So in your example, we start
painting <body>, inside there we're painting <div>, we follow the
reference to #main, we enter <body> again, but when we get to the <div>
again we refuse to following the reference to #main again, since we're
already using that one. The -moz-element draws nothing in that case.

Each occurrence of an ID reference can appear once on a painting stack,
so if you have

<body id="main" style="border:...">


<div style="background-image: -moz-element(main);">...<div>
<div style="background-image: -moz-element(main);">...<div>

</body>

the body border will actually be rendered 5 times, with stacks
root
root <div1's reference>
root <div1's reference> <div2's reference>
root <div2's reference>
root <div2's reference> <div1's reference>

I suppose it would be simpler to say that each referenced element can
only appear once in the painting stack, so the above example would only
draw the body border 3 times.

Rob

fantasai

unread,
Jul 16, 2009, 12:41:50 PM7/16/09
to Robert O'Callahan

Full URI there would be useful, no? You could grab snippets of SVG,
for example.

~fantasai

L. David Baron

unread,
Jul 16, 2009, 2:46:07 PM7/16/09
to fantasai, dev-pl...@lists.mozilla.org

I could see url() being useful there. But I think -moz-element() is
different since it reflects all dynamic changes to the *current*
document.

-David

--
L. David Baron http://dbaron.org/
Mozilla Corporation http://www.mozilla.com/

L. David Baron

unread,
Jul 16, 2009, 3:01:37 PM7/16/09
to dev-pl...@lists.mozilla.org
On Thursday 2009-07-16 11:46 -0700, L. David Baron wrote:
> I could see url() being useful there. But I think -moz-element() is
> different since it reflects all dynamic changes to the *current*
> document.

Actually, that's probably wrong; url() could reflect dynamic changes
too. Although I'm not sure what our story in general is for dynamic
changes to resource documents (e.g., separate documents containing
SVG filters, etc.) or for when the resource is in the same document.

Boris Zbarsky

unread,
Jul 16, 2009, 3:28:01 PM7/16/09
to
L. David Baron wrote:
> Actually, that's probably wrong; url() could reflect dynamic changes
> too. Although I'm not sure what our story in general is for dynamic
> changes to resource documents (e.g., separate documents containing
> SVG filters, etc.)

There generally aren't any, since such documents can't be reached from
script and can't run script themselves. The only dynamic change that
can happen is "resource document finished loading, so the thing we're
pointing to might actually exist now".

> or for when the resource is in the same document.

That works with dynamic changes.

-Boris

Robert O'Callahan

unread,
Jul 16, 2009, 6:34:54 PM7/16/09
to
On 17/7/09 7:28 AM, Boris Zbarsky wrote:
> L. David Baron wrote:
>> Actually, that's probably wrong; url() could reflect dynamic changes
>> too. Although I'm not sure what our story in general is for dynamic
>> changes to resource documents (e.g., separate documents containing
>> SVG filters, etc.)
>
> There generally aren't any, since such documents can't be reached from
> script and can't run script themselves. The only dynamic change that can
> happen is "resource document finished loading, so the thing we're
> pointing to might actually exist now".

Actually if you enable SMIL I think animations will run in external
resource documents. This is probably what we want.

Rob

Robert O'Callahan

unread,
Jul 16, 2009, 6:41:05 PM7/16/09
to

The problem with using a full URI here is that you can't then use this
from a stylesheet to refer to an element in the main document. #id would
refer to an element in the stylesheet, which makes no sense and would
have to be ignored.

The code in my branch uses url() syntax and special-cases #id to refer
to an element in the main document, but that feels dirty. Having
mozSetImageElement interfere with the interpretation of url()s feels
even dirtier.

Another problem is that if you write url(foo.svg#a) then browsers that
support SVG images today will display foo.svg. Changing that to display
just part of foo.svg is an interop issue. Also, the SVG WG had their own
ideas about using the fragment identifer to display a subregion of the
image in a different way, although I'm not sure if those ideas are still
on the table.

Rob

Boris Zbarsky

unread,
Jul 16, 2009, 8:24:31 PM7/16/09
to

Hmm. That doesn't affect most of what I was thinking (which was "which
node is the paint server"), right? You can't animate @id.

We'll have to figure out a way to invalidate the resource document
consumers on animation in the resource document, though.

-Boris

Robert O'Callahan

unread,
Jul 16, 2009, 9:14:02 PM7/16/09
to
On 17/7/09 12:24 PM, Boris Zbarsky wrote:
> We'll have to figure out a way to invalidate the resource document
> consumers on animation in the resource document, though.

That should already work using the existing notification mechanisms.

Rob

Ryo Kawaguchi

unread,
Aug 24, 2009, 4:48:09 PM8/24/09
to
Robert O'Callahan wrote:
> 2) A new DOM API, window.mozSetImageElement("foo", node). The node is
> used instead of the element with ID foo when -moz-element(foo) is used.

Sorry to pick up an old thread.

Is window.mozSetImageElement("foo", node) equivalent to
node.style.backgroundImage = "-moz-element(#foo);"?

Also, why do we use a string to specify the source element as opposed to
the destination element?

-Ryo

Robert O'Callahan

unread,
Aug 24, 2009, 9:03:38 PM8/24/09
to
On 24/08/09 1:48 PM, Ryo Kawaguchi wrote:
> Robert O'Callahan wrote:
>> 2) A new DOM API, window.mozSetImageElement("foo", node). The node is
>> used instead of the element with ID foo when -moz-element(foo) is used.
>
> Sorry to pick up an old thread.
>
> Is window.mozSetImageElement("foo", node) equivalent to
> node.style.backgroundImage = "-moz-element(#foo);"?

No. Calling mozSetImageElement("foo", xyz) means that from now on
-moz-element(#foo) will render element xyz instead of whatever element
has ID "foo".

> Also, why do we use a string to specify the source element as opposed to
> the destination element?

I'm not sure what you mean.

Rob

0 new messages