Can an image have pseudo-elements?
In my testing I have not been able to use :before or :after with image elements, but I would love some more information.
EDIT: W3C isn't clear either unfortunately:
Note. This specification does not fully define the interaction of :before and :after with replaced elements (such as IMG in HTML). This will be defined in more detail in a future specification.
It wouldn't really make any sense. The :before and :after insert the extra content inside the matched element, and img doesn't have an inside.
Related
I did research on it and as far as I know - CSS pseudo-elements ::before and ::after behaves like just span tags nested in a parent element.
On the other hand I have read they are might be extremely useful and in some cases even indispensable. If that is true they need to have some additional or different behavior than just span tags nested into the parent element.
If so what are the pros for using them over span tags?
The most common use of ::before and ::after selectors is to add content to an element solely via CSS, without the need to change the HTML itself. This may be required in situations where you can’t change the HTML, or for semantic reasons.
I recently noticed on a project that the ::after pseudoelement did not add any content after an input element:
input::after { content: "xxxxxxxxxx"; } // no "virtual last child" inserted into DOM "after" the input
(reference to "virtual last child" is from MDN page here)
Of course, an element such as a div will have content "after" it, and the last child "::after" will be inserted into the DOM:
div:empty::after { content: "xxxxxxxxxx"; }
//In DOM
<div>::after</div>
but nothing is inserted in these cases:
head, script { content: "qaqaqa"; }
My initial assumption was that any HTML elements that are rendered by the browser with tags that should be closed (.e.g, p, body, html, div,....etc) will have ::after inserted as a last child (and ::before inserted as a first-child), whereas elements that do NOT fit this (e.g., script, head, img, br, input,...etc) will not exhibit this behavior. My CodePen attempts suggested this was correct.
I read through documentation which finally led me to this resource, in which a note reads:
Note. This specification does not fully define the interaction
of :before and :after with replaced elements (such as IMG in HTML).
This will be defined in more detail in a future specification.
(for definition of "replaced elements" see here)
So now my refined assumption regarding ::after and ::before is that these pseudoelements are only applicable to "renderable" elements which cannot be classified as "replaced elements" (Note this refined assumption now excludes textarea from use with ::after / ::before, whereas my initial assumption would have included it - textarea::after was tested with CodePen and no ::after last child is inserted into the DOM).
Would the refined assumption be correct?
HTML does not define which elements are replaced elements or which elements can contain ::before and ::after pseudo-elements. Neither do CSS2.1 or selectors-3. The latest rewrite of css-content-3, however, states pretty unambiguously:
Replaced elements do not have '::before' and '::after' pseudo-elements
although implementations of course are not consistent with the draft (famously or otherwise, WebKit/Blink) since this wasn't hitherto defined.
Whether an element can have ::before and ::after pseudo-elements is not defined by its content model (i.e. if it's void or otherwise), or whether it has an end tag, in HTML. And again, a lot of this is implementation-dependent. For example, some implementations allow br of all things to have ::before and ::after pseudo-elements, because nobody knows exactly how br is supposed to be implemented in terms of CSS and each browser does it its own way (because neither HTML nor CSS actually defines this).
A head element and any of its descendants can have ::before and ::after pseudo-elements — all you have to do is change their display to something other than none. Obviously, they're not supposed to be displayed, but that doesn't stop anyone trying to be clever.
As far as CSS is concerned, input and textarea are both considered replaced elements, even though textarea has a start tag, end tag, and content. Whether these elements should or must be replaced elements is not stated (not even in section 14.5 of WHATWG HTML), but most browsers render them as replaced elements by default, and this behavior usually can't be changed. And for the purposes of the ::before and ::after pseudo-elements not being supported, that's all that matters.
Don't guess, read: https://drafts.csswg.org/selectors-3/#gen-content
The ::before and ::after pseudo-elements can be used to describe generated content before or after an element's content.
input has no content, so no after element is shown. Same applies for every HTML element with no content (br, menuitem, link...). All auto-closing tags have no content, and some others (like script) have none too.
couldn't find an example that uses css :before to add <use> inside a <svg> tag. So far I've tried:
.icon-test:before {
content : '<use xlink:href="test.svg#icon-test"></use>';
}
.icon-test:before {
content : '\003Cuse xlink\003Ahref\003D\0022test\002Esvg\0023icon-test\0022\003E\003C\002Fuse\003E';
}
<svg class="icon-test"></svg>
Does anybody know the correct way to do it? Or this is not possible?
Basically the end result should yield something like:
<svg class="icon-test">
<use xlink:href="test.svg#icon-test"></use>
</svg>
But I want to simplify the usage by using :before. Thanks!
use ::before
is not possible. You will receive text;
A little more detail compared to Jarosław Goszowski's answer:
The ::before and ::after pseudoelements create a new CSS layout box as the first or last child of the CSS layout box for the element(s) matched by the rest of the selector.
The :: notation distinguishes pseudoelement selectors from pseudoclass selectors, and is supported in all browsers after IE8 (in other words, all browsers that will support inline SVG). The single : syntax is only supported for backwards-compatibility.
The psuedo-elements do not create new elements in the DOM, and cannot be used to insert markup. They only affect CSS layout. The content is injected after the HTML markup has been parsed. You cannot even use HTML entities like &; you definitely cannot use entire element markup.
Because they only affect CSS layout, pseudo-elements can only exist for elements whose content follows the CSS layout model. That means you cannot have pseudo-elements for:
<img> and <video> elements (the content of the element is replaced by the external file, it does not have a CSS layout model);
<input> and <select> elements (the content is replaced by the form widgets created by the browser, no CSS layout model);
SVG elements (the content is drawn according to SVG rules, not CSS layout).
So there are two reasons why you cannot use pseudoelements to inject your <use> elements: one, pseudoelements don't have an effect on SVG; two, even if they did, pseudoelements can only be used to inject plain text (or complete image files), not markup.
One content (:after for box and :before for arrow) property for data-tooltip and I want another content property for the field icon using custom icon fonts like fontello or fontawesome. How can I achieve this.??
If you're asking whether it's possible for an element to have more than one :before or :after pseudo-element at a time, that's not possible in CSS2.1. The reason is twofold:
Any element can only have exactly one :before or :after pseudo-element at a time due to cascading rules. See this answer for details.
Even if an element could have more than one of each kind of pseudo-element, the browser wouldn't know how exactly it should lay all of them out in the formatting structure. This can be worked around by having CSS offer a way to specify multiple pseudo-elements or nest pseudo-elements within other pseudo-elements, but neither of these ideas have been implemented.
If you need a complex structure that cannot be achieved with a single element with one :before and one :after pseudo-element, you will need to modify your HTML to accommodate this structure.
I was looking at a couple Twitter Bootstrap templates and I saw that a lot of ::before and ::after were inserted before and after div tags.
Can anybody tell me what they are?
The ::before and ::after pseudo elements are for css and are in no way bootstrap specific.
A quick example of some of the stuff it can do is this:
Say you have a basic p element:
<p>Hello</p>
In your css, if you had this:
p::before{
content:'Hi';
}
The p tag in html would now say:
HiHello
If it was
p::after{
content:'Hi';
}
It would be:
HelloHi
This can be very useful if you're using it with things such as phone numbers, or e-mail addresses e.g
p.phone_number::before{
content:'Phone #: ';
}
<p class='phone_number'> would now have Phone #: before it.
You can do very many things, even use it for styling.
If you look at The shapes of CSS, you will see that it's used on the more complex shapes.
One thing that ::before and ::after have in common and MUST have to work, is the content attribute. If it doesn't have a content attribute it wont show up. Don't mistake this as having a blank content, though, as this will work provided you give it a height/width like any other element.
::before and ::after aren't the only Pseudo elements though, here is a list:
::after
::before
::first-letter
::first-line
::selection
You can also double up on these elements:
For example:
p:hover::before{
content:'Hovered! ';
}
They represent pseudo-elements, which you don't include directly in your markup, but are available to you to create some neat effects with CSS. You have mentioned ::before and ::after, and they represent pseudo-elements that appear, shockingly, before and after your elements.
The whole list is included below and should be fairly self-explanatory:
::after
::before
::first-letter
::first-line
::selection
ref: https://developer.mozilla.org/en-US/docs/Web/CSS/Pseudo-elements
Note the use of the double-colon, which is consistent with the spec. Sometimes you will see pseudo-elements specified with a single colon, but that was only because we needed to support browsers that didn't understand the double-colon syntax.