Related
I've got some CSS code in order to display the title attribute when touching on abbreviations and symbols of a smartphone's screen. Within a section '#media only screen and (max-width: 767px)' of my stylesheet I have the following code:
span[title]:active::after,abbr:active::after {
color: Maroon;
font-weight: bold;
content: 'Meaning: ' attr(title);
position: fixed;
top: 3ex;
left: 2ex;
display: block;
z-index: 100;
background-color: White;
box-shadow: .3ex .3ex .1ex Grey;
border: 1px solid grey;
padding: .4ex;
width: 70%;
height: auto;
}
It does work flawlessly on Android -I've tested it on Chrome, Firefox and Samsung browser- and my iMac -tested it on Chrome, Firefox, Safari and Opera after stretching the width of the browser's window, but it doesn't work on iOS at all! The trick/workaround of adding '-webkit-transform: translate3d (0,0,0);' added to the code did not help to this.
I should appreciate any help a lot!
Thank you very much indeed!
SOLVED!
I tried the solution as proposed in the following link: Enable CSS active pseudo styles in Mobile Safari
and it works fine. The problem was that Safari Mobile disables :active pseudo-class by default, and this simple idea solves it.
I tried some other working solutions, such as 'body ontouchstart=””' and similar ones, but all of them gave errors when checking the code against W3C validator.
Many thanks to all those that answered and tried to help!
The :active property only works on activabe elements. Documentation says:
There may be document language or implementation specific limits on which elements can become :active or acquire :focus.
So the most simple thing to do is to set the tabindex attribute to 0 for each element you want to be activable.
This has the big advantage that your code will work with keyboard.
EDIT: adding tabindex=-1 for all elements can be done easily with jQuery using
$("abbr[title]").attr("tabindex", -1);
or using standard javascript
var ele=document.querySelectorAll("abbr[title]");
for (var i=0;i<ele.length;i++) {
ele[i].setAttribute("tabindex", -1);
}
I'm re-asking this question because its answers didn't work in my case.
In my stylesheet for printed media I want to append the url after every link using the :after pseudo-class.
a:after {
content: " <" attr(href) ">";
text-decoration: none;
color: #000000;
}
In Firefox (and probably Chrome but not IE8), text-decoration: none is ignored, and the underline stretches unattractively across the bottom of the url. The color however is correctly set to black for the url. Is there a way to make the text-decoration work?
The original question appended fixed size images instead of variable width text. Its answers use padding and background images to avoid having to use the text-decoration property. I'm still looking for a solution when the content is variable width text.
If you use display: inline-block on the :after pseudo, the text-decoration declaration will work.
Tested in Chrome 25, Firefox 19
IE8's implementation of the :before and :after pseudo-elements is incorrect. Firefox, Chrome and Safari all implement it according to the CSS 2.1 specification.
5.12.3 The :before and :after pseudo-elements
The ':before' and ':after'
pseudo-elements can be used to insert
generated content before or after an
element's content. They are explained
in the section on generated text.
...
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification
The specification indicates that the content should be inserted before or after the element's content, not the element (i.e. <element>content:before content content:after</element>). Thus in Firefox and Chrome the text-decoration you're encountering is not on the inserted content but rather on the parent anchor element that contains the inserted content.
I think your options are going to be using the background-image/padding technique suggested in your previous question or possibly wrapping your anchor elements in span elements and applying the pseudo-elements to the span elements instead.
I had the same problem and my solution was to set height and overflow:hidden
http://jsfiddle.net/r45L7/
a {
text-decoration: underline;
}
a:after {
content: "»";
display: inline-block;
text-decoration: none;
height:16px;
overflow: hidden;
padding-left: 10px;
}
It works on IE, FF, Chrome.
As an alternative, you can use a bottom border rather than a text-decoration.
This assumes that you know the color of the background
a {
text-decoration: none;
border-bottom: 1px solid blue;
}
a:after {
content: "foo";
border-bottom: 1px solid white; /* same color as the background */
}
1)
:after{
position: absolute;
}
is not perfect, because element content will not wrap
2)
:after{
display: inline-block;
}
is not perfect, because sometimes we wish after content should always wrap with last word of element content.
For now, I could not find find a perfect solution fits all 3 conditions(1. content could auto-wrap if it's too long 2.after content should wrap with element content, which means after content should not occupy single by it self. 3.text-decoration should only apply on element condition not apply to after content.)
I thoughts for now is using other way to mimic text-decoration.
What I do is I add a span inside the a element, like this :
<span>link text</span>
Then in your CSS file :
a::after{
content:" <" attr(href) "> ";
color: #000000;
}
a {
text-decoration:none;
}
a span {
text-decoration: underline;
}
The only thing that worked for me was declaring a separate repeated selector with the same text-decoration property that it was inheriting from its parent, then in the main selector, setting text-decoration to none.
IE apparently does not know what to do when you set text-decoration: none on a pseudo element without that element having the text-decoration property declared (which by default, it has nothing declared by default). This makes little sense because it is obviously being inherited from the parent, but alas, now we have modern browsers.
span.my-text {
color: black;
font-size: 12px;
text-decoration: underline;
}
span.my-text:after {
text-decoration: underline; // Have to set text-decoration here so IE knows it can be overwritten below
}
span.my-text:after {
color: red;
text-decoration: none; // In the same repeated selector, we can now overwrite text-decoration in our pseudo element.
}
I realise this isn't answering the question you're asking, but is there a reason you can't use the following (background-based approach):
a.file_pdf {
background-image: url(images/pdf.png);
background-position: center right;
background-repeat: no-repeat;
padding-right: 15px; /* or whatever size your .png image is plus a small margin */
}
As far as I know, the Firefox implementation of :after observes the property of the selector's class, not the psuedo-class. It might be worth experimenting with different doctypes, though? The transitional, rather than strict, sometimes allows for different results (albeit not always better results...).
Edit:
It appears that using
a:after {
content: " <" attr(href) ">";
text-decoration: none;
color: #000000;
background-color: #fff; /* or whatever colour you prefer */
}
overrides, or at least hides, the text-decoration. This doesn't really provide any kind of answer, but at least offers a workaround of sorts.
You can autoselect links to pdf-files by:
a[href$=".pdf"]:after { content: ... }
IE less than 8 can be enabled to work properly by implementing this link in the head of the html-file:
<!--[if lt IE 8]><script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script><![endif]-->
It works also very good in al IE versions when you use the after-before-content-thing for dosplaying quotation marks.
Position the content absolutely as follow:
a {
position: relative;
margin: 0 .5em;
font-weight: bold;
color: #c00;
}
a:before,
a:after {
position: absolute;
color: #000;
}
a:before {
content: '<';
left: -.5em;
}
a:after {
content: '>';
right: -.5em;
}
This works for me in Firefox 3.6, not tested in any other browsers though, best of luck!
Hi I was also having trouble with this as well and happened to stumble across a workaround.
To get around it, I wrapped the URL in div and used something like this.
.next_page:before {
content: '(';
}
.next_page:after {
content: ')';
}
I'm having trouble understanding the behavior of the CSS :after property. According to the spec (here and here):
As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content.
This doesn't seem to place restrictions on which elements can have a :after (or :before) property. However, it seems to only work with specific elements... <p> works, <img> doesn't, <input> doesn't, <table> does. I'm could test more, but the point is made. Note that this seems pretty consistent across browsers. What determines whether an object can accept a :before and :after property?
img and input are both replaced elements.
A replaced element is any element whose appearance and dimensions are
defined by an external resource. Examples include images (<img> tags),
plugins (<object> tags), and form elements (<button>, <textarea>,
<input>, and <select> tags). All other elements types can be referred
to as non-replaced elements.
:before and :after only work with non-replaced elements.
From the spec:
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.
With span:before, span:after, the DOM looks like this:
<span><before></before>Content of span<after></after></span>
Evidently, that won't work with <img src="" />.
:before and :after are not required to work for replaced elements, and CSS specifications do not specify how they would work for them, and the concept of replaced element is somewhat vague.
The CSS 2.1 specification clearly suggests that they can work for replaced elements, just saying that it does not “fully define” how. This relates to the issue that a replaced element is expected to have its own visual rendering, which is not controlled by CSS, whereas the pseudo-elements should add something to the content of the element. The spec adds that this will be defined “in more detail” in a future specification, but this has not taken place so far.
Browser vendors just decided to avoid problems by not implementing these pseudo-elements for some elements at all.
It is not clear at all what “replaced element” means, and the meaning appears to have changed somewhat. It is often interpreted as meaning the same as empty element (an element with EMPTY declared content, i.e. an element that cannot have any content), but CSS 2.1 itself shows a sample style sheet with the selector br:before (though browsers have ignored this, implementing br their own way). It can be argued that more and more elements have moved into the scope of CSS rendering, at least in part. For example, an input element (incuding its font, colors, etc.) is largely controllable with CSS in modern browsers.
Current browsers (Firefox, IE, Chrome) do not seem to support the :after and :before pseudo-elements for empty elements other than hr. For hr, IE and Chrome place the generated content inside a bordered box, which is the implementation of hr; the content makes the box taller. Firefox places the content of both (!) pseudo-elements after the horizontal rule that is its implementation of hr. This variation illustrates the kinds of “interaction” problems that are referred to in CSS 2.1.
It is often claimed that these pseudo-elements cannot be used for empty elements since their HTML definitions do not allow any content. This is a category error. The syntax rules of a markup language do not restrict what you can do in CSS
To conclude, :after and :before are currently not usable for empty elements (except marginally for hr), but this is mainly due to implementations and may change in the future.
I've spent several hours plucking out my hair only to find that some other css override content (or display:none) property of my selector.
For example, if the following code is written in some other place, before or after element will never show:
#id > child:before {
content: none!important;
}
<html>
<div id="id" class="class">
<child>
Before element is not showing
</child>
</div>
<style>
child:before {
content: 'before';
color: 'red';
}
</style>
</html>
Just find the css which is overwriting your style and spam stronger selectors and !important to make it work
#id>child:before {
content: none!important;
}
<html>
<div id="id" class="class">
<child>
Before element is <strong>showing</strong>
</child>
</div>
<style>
#id.class>child:before {
content: 'before'!important;
border: 1px solid red;
}
</style>
</html>
<img> is a replaced element and using :before or :after pseudo-elements on it works if the image fails to load and otherwise it does not work. If you intend to have a fallback in case of image load failure, the following css useful:
img{
position: relative;
}
img:after{
position: absolute;
content: "Any allowed type of content including a fallback image";
left: 0;
}
For a good example, please refer to https://css-tricks.com/7-practical-uses-for-the-before-and-after-pseudo-elements-in-css/
Elements that doesn't have closing tag are void elements and they can't display content inside them:
https://www.w3.org/TR/html5/syntax.html#void-elements
All Blink, Webkit and Quantum browsers allow you to create pseudo elements only on checkboxes but this is controversial since no spec allow this behavior.
Here an example:
https://codepen.io/equinusocio/pen/BOBaEM/
input[type="checkbox"] {
appearance: none;
color: #000;
width: 42px;
height: 24px;
border: 1px solid currentColor;
border-radius: 100px;
cursor: pointer;
transition: all 100ms;
background-size: 30%;
outline: none;
position: relative;
box-sizing: border-box;
background-color: #eee;
transition: background-color 200ms;
&::before {
content: '';
position: absolute;
left: 2px;
top: 2px;
bottom: 2px;
height: 18px;
width: 18px;
border-radius: 50%;
background-color: currentColor;
will-change: transform;
transition: transform 200ms cubic-bezier(.01,.65,.23,1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
&:checked {
background-color: aquamarine;
&::before {
transform: translateX(100%);
}
}
}
I'm having trouble understanding the behavior of the CSS :after property. According to the spec (here and here):
As their names indicate, the :before and :after pseudo-elements specify the location of content before and after an element's document tree content.
This doesn't seem to place restrictions on which elements can have a :after (or :before) property. However, it seems to only work with specific elements... <p> works, <img> doesn't, <input> doesn't, <table> does. I'm could test more, but the point is made. Note that this seems pretty consistent across browsers. What determines whether an object can accept a :before and :after property?
img and input are both replaced elements.
A replaced element is any element whose appearance and dimensions are
defined by an external resource. Examples include images (<img> tags),
plugins (<object> tags), and form elements (<button>, <textarea>,
<input>, and <select> tags). All other elements types can be referred
to as non-replaced elements.
:before and :after only work with non-replaced elements.
From the spec:
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.
With span:before, span:after, the DOM looks like this:
<span><before></before>Content of span<after></after></span>
Evidently, that won't work with <img src="" />.
:before and :after are not required to work for replaced elements, and CSS specifications do not specify how they would work for them, and the concept of replaced element is somewhat vague.
The CSS 2.1 specification clearly suggests that they can work for replaced elements, just saying that it does not “fully define” how. This relates to the issue that a replaced element is expected to have its own visual rendering, which is not controlled by CSS, whereas the pseudo-elements should add something to the content of the element. The spec adds that this will be defined “in more detail” in a future specification, but this has not taken place so far.
Browser vendors just decided to avoid problems by not implementing these pseudo-elements for some elements at all.
It is not clear at all what “replaced element” means, and the meaning appears to have changed somewhat. It is often interpreted as meaning the same as empty element (an element with EMPTY declared content, i.e. an element that cannot have any content), but CSS 2.1 itself shows a sample style sheet with the selector br:before (though browsers have ignored this, implementing br their own way). It can be argued that more and more elements have moved into the scope of CSS rendering, at least in part. For example, an input element (incuding its font, colors, etc.) is largely controllable with CSS in modern browsers.
Current browsers (Firefox, IE, Chrome) do not seem to support the :after and :before pseudo-elements for empty elements other than hr. For hr, IE and Chrome place the generated content inside a bordered box, which is the implementation of hr; the content makes the box taller. Firefox places the content of both (!) pseudo-elements after the horizontal rule that is its implementation of hr. This variation illustrates the kinds of “interaction” problems that are referred to in CSS 2.1.
It is often claimed that these pseudo-elements cannot be used for empty elements since their HTML definitions do not allow any content. This is a category error. The syntax rules of a markup language do not restrict what you can do in CSS
To conclude, :after and :before are currently not usable for empty elements (except marginally for hr), but this is mainly due to implementations and may change in the future.
I've spent several hours plucking out my hair only to find that some other css override content (or display:none) property of my selector.
For example, if the following code is written in some other place, before or after element will never show:
#id > child:before {
content: none!important;
}
<html>
<div id="id" class="class">
<child>
Before element is not showing
</child>
</div>
<style>
child:before {
content: 'before';
color: 'red';
}
</style>
</html>
Just find the css which is overwriting your style and spam stronger selectors and !important to make it work
#id>child:before {
content: none!important;
}
<html>
<div id="id" class="class">
<child>
Before element is <strong>showing</strong>
</child>
</div>
<style>
#id.class>child:before {
content: 'before'!important;
border: 1px solid red;
}
</style>
</html>
<img> is a replaced element and using :before or :after pseudo-elements on it works if the image fails to load and otherwise it does not work. If you intend to have a fallback in case of image load failure, the following css useful:
img{
position: relative;
}
img:after{
position: absolute;
content: "Any allowed type of content including a fallback image";
left: 0;
}
For a good example, please refer to https://css-tricks.com/7-practical-uses-for-the-before-and-after-pseudo-elements-in-css/
Elements that doesn't have closing tag are void elements and they can't display content inside them:
https://www.w3.org/TR/html5/syntax.html#void-elements
All Blink, Webkit and Quantum browsers allow you to create pseudo elements only on checkboxes but this is controversial since no spec allow this behavior.
Here an example:
https://codepen.io/equinusocio/pen/BOBaEM/
input[type="checkbox"] {
appearance: none;
color: #000;
width: 42px;
height: 24px;
border: 1px solid currentColor;
border-radius: 100px;
cursor: pointer;
transition: all 100ms;
background-size: 30%;
outline: none;
position: relative;
box-sizing: border-box;
background-color: #eee;
transition: background-color 200ms;
&::before {
content: '';
position: absolute;
left: 2px;
top: 2px;
bottom: 2px;
height: 18px;
width: 18px;
border-radius: 50%;
background-color: currentColor;
will-change: transform;
transition: transform 200ms cubic-bezier(.01,.65,.23,1);
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
&:checked {
background-color: aquamarine;
&::before {
transform: translateX(100%);
}
}
}
I'm re-asking this question because its answers didn't work in my case.
In my stylesheet for printed media I want to append the url after every link using the :after pseudo-class.
a:after {
content: " <" attr(href) ">";
text-decoration: none;
color: #000000;
}
In Firefox (and probably Chrome but not IE8), text-decoration: none is ignored, and the underline stretches unattractively across the bottom of the url. The color however is correctly set to black for the url. Is there a way to make the text-decoration work?
The original question appended fixed size images instead of variable width text. Its answers use padding and background images to avoid having to use the text-decoration property. I'm still looking for a solution when the content is variable width text.
If you use display: inline-block on the :after pseudo, the text-decoration declaration will work.
Tested in Chrome 25, Firefox 19
IE8's implementation of the :before and :after pseudo-elements is incorrect. Firefox, Chrome and Safari all implement it according to the CSS 2.1 specification.
5.12.3 The :before and :after pseudo-elements
The ':before' and ':after'
pseudo-elements can be used to insert
generated content before or after an
element's content. They are explained
in the section on generated text.
...
Cascading Style Sheets Level 2 Revision 1 (CSS 2.1) Specification
The specification indicates that the content should be inserted before or after the element's content, not the element (i.e. <element>content:before content content:after</element>). Thus in Firefox and Chrome the text-decoration you're encountering is not on the inserted content but rather on the parent anchor element that contains the inserted content.
I think your options are going to be using the background-image/padding technique suggested in your previous question or possibly wrapping your anchor elements in span elements and applying the pseudo-elements to the span elements instead.
I had the same problem and my solution was to set height and overflow:hidden
http://jsfiddle.net/r45L7/
a {
text-decoration: underline;
}
a:after {
content: "»";
display: inline-block;
text-decoration: none;
height:16px;
overflow: hidden;
padding-left: 10px;
}
It works on IE, FF, Chrome.
As an alternative, you can use a bottom border rather than a text-decoration.
This assumes that you know the color of the background
a {
text-decoration: none;
border-bottom: 1px solid blue;
}
a:after {
content: "foo";
border-bottom: 1px solid white; /* same color as the background */
}
1)
:after{
position: absolute;
}
is not perfect, because element content will not wrap
2)
:after{
display: inline-block;
}
is not perfect, because sometimes we wish after content should always wrap with last word of element content.
For now, I could not find find a perfect solution fits all 3 conditions(1. content could auto-wrap if it's too long 2.after content should wrap with element content, which means after content should not occupy single by it self. 3.text-decoration should only apply on element condition not apply to after content.)
I thoughts for now is using other way to mimic text-decoration.
What I do is I add a span inside the a element, like this :
<span>link text</span>
Then in your CSS file :
a::after{
content:" <" attr(href) "> ";
color: #000000;
}
a {
text-decoration:none;
}
a span {
text-decoration: underline;
}
The only thing that worked for me was declaring a separate repeated selector with the same text-decoration property that it was inheriting from its parent, then in the main selector, setting text-decoration to none.
IE apparently does not know what to do when you set text-decoration: none on a pseudo element without that element having the text-decoration property declared (which by default, it has nothing declared by default). This makes little sense because it is obviously being inherited from the parent, but alas, now we have modern browsers.
span.my-text {
color: black;
font-size: 12px;
text-decoration: underline;
}
span.my-text:after {
text-decoration: underline; // Have to set text-decoration here so IE knows it can be overwritten below
}
span.my-text:after {
color: red;
text-decoration: none; // In the same repeated selector, we can now overwrite text-decoration in our pseudo element.
}
I realise this isn't answering the question you're asking, but is there a reason you can't use the following (background-based approach):
a.file_pdf {
background-image: url(images/pdf.png);
background-position: center right;
background-repeat: no-repeat;
padding-right: 15px; /* or whatever size your .png image is plus a small margin */
}
As far as I know, the Firefox implementation of :after observes the property of the selector's class, not the psuedo-class. It might be worth experimenting with different doctypes, though? The transitional, rather than strict, sometimes allows for different results (albeit not always better results...).
Edit:
It appears that using
a:after {
content: " <" attr(href) ">";
text-decoration: none;
color: #000000;
background-color: #fff; /* or whatever colour you prefer */
}
overrides, or at least hides, the text-decoration. This doesn't really provide any kind of answer, but at least offers a workaround of sorts.
You can autoselect links to pdf-files by:
a[href$=".pdf"]:after { content: ... }
IE less than 8 can be enabled to work properly by implementing this link in the head of the html-file:
<!--[if lt IE 8]><script src="http://ie7-js.googlecode.com/svn/version/2.0(beta3)/IE8.js" type="text/javascript"></script><![endif]-->
It works also very good in al IE versions when you use the after-before-content-thing for dosplaying quotation marks.
Position the content absolutely as follow:
a {
position: relative;
margin: 0 .5em;
font-weight: bold;
color: #c00;
}
a:before,
a:after {
position: absolute;
color: #000;
}
a:before {
content: '<';
left: -.5em;
}
a:after {
content: '>';
right: -.5em;
}
This works for me in Firefox 3.6, not tested in any other browsers though, best of luck!
Hi I was also having trouble with this as well and happened to stumble across a workaround.
To get around it, I wrapped the URL in div and used something like this.
.next_page:before {
content: '(';
}
.next_page:after {
content: ')';
}