How should the following work:
img::before { content: "Image: " }
If it should work at all. Note that ::before
and ::after
create elements inside the elements they are applied upon. For example, when applies on a span
element it would look like:
<span><::before/>... actual content ...<::after/></span>
For the img
element, which is technically a replaced element, this raises some questions. The most logical way to do it when pseudo-elements would apply to replaced elements seems to be that an anonymous box is created inside the actual element. However, the height
and width
properties are traditionally used to scale the image, which would in this case be the anonymous box. That seems inconsistent. Especially as you expect img { border:solid }
to go around the generated content...
The CSS WG is looking for input on this issue. Comments are open for those who have anything to say about it. (Feel free to try out versions of Opera that have support for it to see how it works there...)
My understanding was that CSS3 was going to introduce a new pseudo-element (::outside IIRC) which would also work with replaced elements. Although I certainly wouldn't mind if CSS2.1 were to let :before/after work with <img> as shown by that infamous CSS2 example...
I have been wondering myself for some time. I eventually concluded that it'd probably be best if the generated content applied (and only applied) to the alt
tekst. My thoughts on this are not quite organized enough to bother explaining as of why, but it "feels" right to me so far. I'll probably get back on the subject if it were to rise on www-html
.
ACJ: I think you are right. And it is going to make much more sense in XHTML 2.0 where the alternative tekst is the content of the img element. Another reason why the alt
attribute was a mistake. But otherwise, elements that do not allow child nodes can not support ::before
and ::after
.
How about the br tag?
I agree with ACJ. By the way, for the object element, the generated content can be added inside the object element. e.g.
<object type="image/svg+xml" data="example.svg"><::before/>... nested content ...<::after/></object>
Especially as you expect
img { border:solid }
to go around the generated content...
Do I? I don't think I do. Just as I would want height
and width
to only apply to the image and not the generated content, so too would I want border
to only apply to the image. From a design standpoint, it is part of the image's decorations. If the border is unrelated, it would be around an appropriate wrapper.
If you choose to advocate for before
and after
to only apply to the alternative text, then there is a need for two pseudo-classes that allow external text if you wish to avoid a proliferation of useless div
s.
Does generated content go inside an inline-block
? In that case, this matter is certainly a headache.
I'm going to go against the grain and say it should do what you expect... "Image: [image data]". Here's why. I see the content as the data model - this is after the xml processing - as something like:
<img> [image data] </img>
Likewise, I see the model for a paragraph as:
<p> [text data] <em> [text data] </em> [text data] </p>
So adding content in the above creates:
<img> <::before> [text data] </::before> [image data] </img>
It is the same when adding image/* as the ::before content (if that is allowed... don't know).
P.S. My well-formed XHTML fragment doesn't work... it uses CDATA sections. Please Fix!
And that breaks width/height... Should have paid more attention to the comments. The fix may be that the width and height apply to the replaced content, the [image data], rather than the element's CSS width/height itself. Then the element's width/height expand to fill it as specified by the spec. But that may cause more problems than just adding an implied box around the image data. I guess I don't have a strong opinion any way... Just food for thought.
ACJ, then it is no longer a replaced element anymore. Most browsers treat that as an inline box to which generated content should apply. (At least, in my opinion.) Same for the object
element by the way. You could assume that inside the object
element there is an anonymous box for the image so ::before
and ::after
can apply, but what about height
, width
and border
?
I've tested around with this some time ago. Opera indeed works quite weird (or sense making, dunno) with the image border if the image is displayed inline (it doesn't go around the image anymore). I think generated content for empty elements should just be ignored (like Mozilla does right now, apart from the HR
).
I think that it should generate:
<img alt="foo" src="bar"><::before>Image: </::before></img>
If the image is available then the generated content should be ignored because the element is replaced. If the image is not available then it should display the alt
text as normal, and ignore the generated content since the HTML spec says the IMG
element must be empty.
Making special cases and messing with the alt
attribute seems very messy to me.
What happens if the generated content is also an image?
Agree with zcorpan. The CSS should generate <img alt="foo" src="bar">Image: </img>
, and that text should be ignored by UAs (just like Gecko and MSIE do right now). Opera's implementation—in my opinion at least—is screwy. It's a simple rule, let's not mess it up.
The problem is that there is no rule. Please pay attention. Also, is the following a replaced element:
foo { content:"bar" }
(According to the editor of CSS 3 Generated Content it is not. According to me that is confusing, but whatever.)
Personally, I don't see a conceptual problem with an <img>
tag having content, the spec is just arbitrarily not allowing it. What does it look like? Perhaps the inverse of other elements: The image would be in the foreground and the contained content would essentially be a background, showing through transparent portions.
It would be nice to be able to raise the z-order value of the inner content to force it above the image (overlaid image labels), but it seems like interpreting the inner content as background means that no z-index value could put it above the actual image content.
Should I talk to my Senator about allowing xhtml <img>
tags to have content?
I liked the foreground/background idea. I suppose it would be possible to use normal z-index values:
img::before { content: "Image: "; }
creates background text for transparent areas,
img::before { content: "Image: "; z-index: 1 }
creates foreground text. I'd imagine inline boxes in both cases. Border would obviously apply to image only (how weird ideas like positioning the generated content outside the image might work out I won't get started on..)