::first-letter pseudo-element not working in firefox - css

I cannot for the life of me figure this one out. I just want to style the dollar sign to be a different color and I would like to avoid using another element around the dollar sign.
<ul>
<li><strong>John Dow</strong> <div>$5,849,487<sup>84</sup></div></li>
<li><strong>David Jones</strong> <div>$5,498,364<sup>01</sup></div></li>
<li><strong>Susie Smith</strong> <div>$5,098,276<sup>35</sup></div></li>
</ul>
And this CSS:
li::first-letter {
color: blue;
}
li div::first-letter {
color: red;
}​​
The blue works, the red does not.
http://jsfiddle.net/ryanwheale/KUzUp/

It seems to be due to the $ character not being interpreted as a letter character by Firefox, based on the discovery that replacing the $ with a letter character (A, B, C...) causes the demo to work:
<ul>
<li><strong>David Wilcox</strong> <div>A$5,849,487<sup>84</sup></div></li>
<li><strong>David Cowee</strong> <div>B$5,498,364<sup>01</sup></div></li>
<li><strong>D.J. Johnson</strong> <div>C$5,098,276<sup>35</sup></div></li>
</ul>​
JS Fiddle demo.
Revisiting this question, though, it's worth noting that now you could use CSS generated-content to both supply, and style, a first-character, using ::before:
li div::before {
content: '$';
color: red;
}
With the HTML:
<ul>
<li><strong>David Wilcox</strong>
<div>5,849,487<sup>84</sup>
</div>
</li>
<!-- siblings removed for brevity -->
</ul>
JS Fiddle demo.

Everything works as it should do: ::first-letter selects the first letter, but "$" is not a letter but a special character.

Others already explained why it doesn't work, so, a small fix for you to consider: give your money div a class, eg
<li><strong>David Wilcox</strong> <div class="money">5,849,487<sup>84</sup></div></li>
take out the literal $, and put it in :before content, eg:
.money:before {
content: '$';
...
}
Now you can style it however you like.

Related

CSS Precedence strange behaviour

I was researching precedence in CSS and reading some articles, including this: http://www.w3.org/TR/CSS2/cascade.html. According to him, attributes like classes have higher precedence over pseudo-elements. However, when I did a simple test, the opposite happened. Below, my code:
HTML:
<ul>
<li class="item">Item</li>
</ul>
CSS:
ul li.item { font-size: 12px; }
ul li:first-letter { font-size: 20px; }
See it here. Why the font-size of the first letter has 12 pixels instead of 20 pixels if the class has higher precedence than pseudo-elements? Thanks in advance.
I have just looked at your fiddle in Firefox, and you don't have a problem, it is working correctly. The font size of the word is 12px as asked for. But the first-letter pseudo element is all about identifying the first letter as a separate entitiy, and giving it a different style to that used for the rest of the word. As such, the specificity of the first letter is entirely separate from the specificity of the whole word; they do not override each other.
So your first letter in the fiddle is correctly 20px.

CSS :before and :first-child combined

I'm using the following code to add separators between my menu items:
#navigation_center li:before {
content: "| ";
color: #fff;
}
Now I want the first item not to have a separator in front of it, so I figured out the following code:
#navigation_center li:before:first-child {
content: none;
}
but that's not doing anything. Is it possible to combine :before and :first-child?
Try
#navigation_center li:first-child:before {
content: '';
}
Edit: I wanted to expand on this answer with comments made by FelipeAls. The original question used :first which is not a valid CSS selector. Instead, use :first-child. Also the order of the pseudo-selectors is important. The first child selector must come first.
I tend to think of :before as a kind of modifier to a selector. It does not actually select an element only the space just before the selected element.
Although hradac's answer should do the trick i thought it would be best to run through some possible permutations to help newcommers.
.works:first-child:before
{
color: green;
content: 'working ';
}
.works:not(:first-child):after
{
color: green;
content: ' is working';
}
.broken:before:first-child
{
color: red;
content: 'this will never show up';
}
.broken:after:not(:first-child)
{
color: red;
content: 'and this will not show up either';
}
works:
<div>
<div class='works'>
something
</div>
<div class='works'>
something
</div>
<div class='works'>
something
</div>
</div>
<hr/>
broken:
<div>
<div class='broken'>
something
</div>
<div class='broken'>
something
</div>
<div class='broken'>
something
</div>
</div>
Let's take this apart:
Three div.works are inside a div
Three div.broken are also inside a div
The first rule of CSS adds a green text "working " before. It does so by selecting the first-child and then selecting the empty space right before it.
The second rule adds " is working" after each block that comes after first, by analogy it first selects each block that doesn't fall under the first-child definition, and then selects the empty space before them.
The following two rules, will not find a block to attach themselves to. The :before:first-child attempts to select an empty space, but then tests if it is a first-child and it is not (since technically it's not yet in the DOM tree), the similar problem is with :not(:first-child).

Is it possible to chain :not() then :last-child?

I need to style (CSS only) the last child element while excluding those with a specific class.
For example, I want to style
<ul>
<li>Bar</li>
<li>Bar</li>
<li>Bar</li>
<li>Should have a green background</li>
<li class='foo'>Bar</li>
</ul>
The last li without class 'foo' should be green. I tried
li:not(.foo):last-child {
background-color: green;
}​
or
li:not(.foo):last-of-type {
background-color: green;
}​
but it doesn't works.
See http://jsfiddle.net/gentooboontoo/V7rab/2/
The answer to your question Is it possible to chain :not() then :last-child? (or, more simply, can pseudo-classes be chained?) is very much a yes. But as others have pointed out, if an li:last-child has an id="foo" then nothing will be selected. As a demonstration, a similar expression
li:not(.bar):last-child {
background-color: green;
}​
works just fine. The problem is that successive selectors all apply to the entire context, not to a subset specified by previous expressions so li:not(.foo):last-child is identical to li:last-child:not(.foo), which is clearly not what is required.
I don't think that will work (it doesn't work, but I don't think it should work anyway)
The selector is working, but the second-to-last li is never going to be the :last-child because it isn't the last-child...
It isn't like jQuery's not() method which actually removes the specified element from the selection. The CSS :not selector/filter will ignore the element, but not remove it from the page
There is only one last child inside any element. In your example, it's <li class='foo'>Bar</li>. If you have exact number of children though, you could use adjacent-sibling combinator:
LI:first-child + LI + LI + LI {/* here are declarations for 4th LI. */}
Applying 'last-child' will give browser issue. so I tried in Jquery.
If you need use this code.
var a = 0
$('ul li').each(function() {
$(this).attr("id",a);
a++;
});
var b = a-1;
$('#'+b).attr('style','background-color:green');​

css or html5 for first and last elements

Users can enter descriptions which may include paragraphs or lists. Or they may just enter text without any enclosing <p> or <ul> elements. What I need to do is remove most of the padding and margin above the first element and below the last element so that the user entered content has a nice tight border around it. So I could do one of the following:
Use a css rule I was unaware of to target only the first and last elements
Use css3 or html5 (I assume there's something within these to easily do what I want) and hope everyone upgrades their browsers asap while the older browsers just get a slightly uglier version of the page
Find the first and last elements with Javascript and modify accordingly
Modify the html to add a class like <p class="first">
Ideally the 1st solution exists, does it? I'm ok with the 2nd solution though if not, does it exist? The last 2 I don't care for...
UPDATE: don't care about IE6. But I do need to deal with the situation that if there's just text to begin with, without any <p> or <ul> or other elements, then actually nothing special needs to be done for the top margin/padding.
Use :first-child and :last-child like this. Note that > and :first-child (CSS2) doesn't work in IE6 and below, and :last-child (CSS3) doesn't work in IE8 and below. The only real workaround to both is to use a .first and .last class respectively (you can add them dynamically with JavaScript as Phrogz says).
.description > p, .description > ul {
margin: 1.5em 0;
}
.description > :first-child {
margin-top: 0;
}
.description > :last-child {
margin-bottom: 0;
}
I added the > combinator to prevent elements like strong or li getting selected. What does it mean?
Something like this?
.container * + p, .container * + ul
{
margin: 1em 0 0;
}
.container p, .container ul
{
margin: 0;
}
BoltClock's answer works great in most cases, but IE8 and earlier ignores the :...-child pseudo-selectors.
You can use jQuery to accomplish the same thing, while targetting more browsers.
//On ready...
$(function(){
//Update styles dynamically
$('ul:last').css({'margin-bottom':0,'padding-bottom':0});
$('ul:first').css({'margin-top':0,'padding-top':0});
});
Have you considered wrapping the content in a container with a negative margin? It requires the content to at least be wrapped in a single p element (not hard to test/add melodramatically).
CSS:
.container {border:1px solid black;}
.container .subcontainer {margin:-1em 0;}
.container p {margin:1em 0;}
HTML:
<div class="container"><div class="subcontainer">
<p>My first paragraph.</p>
<p>My second paragraph.</p>
</div></div>

Cancel a CSS declaration

Is it possible to have a CSS rule which basically "undoes" a prior rule?
An example:
<blockquote>
some text <em>more text</em> other text
</blockquote>
and let's say there's this CSS:
blockquote {
color: red;
}
...but I want the <em> to remain the normal text color (which you may not necessarily know).
Basically, would there be a way to do something like this?
blockquote em {
color: inherit-from-blockquote's-parent
}
Edit: The code I'm actually trying to get this to work on is actually a bit more complicated. Maybe this would explain it better:
This text should be *some unknown colour*
<ul>
<li>This text should be BLUE
<ul>
<li>Same as outside the UL</li>
<li>Same as outside the UL</li>
</ul>
</li>
</ul>
ul {
color: blue;
}
ul ul {
color: ???;
}
With CSS alone, you can't refer to a parent's parent.
The thing you can do is try a mix of specific CSS selectors and markup so that the desired effect appears.
<td>
This is the enclosing element.
<ul>
<li>This is the first level UL, direct child of TD
<ul>
<li>This is the second level UL</li>
<li>Same as outside the UL</li>
</ul>
</li>
</ul>
</td>
CSS:
td > ul
color: blue; /* this affects the "direct child" UL only */
}
You would limit the depth of style inheritance to one level, consequently the inner UL is unstyled in regard to color and gets its setup from the enclosing text.
Read more on the CSS Child Selector, and be aware that older browsers may have their quirks with them.
EDIT
For Internet Explorer 6, the child selector can be faked to some extend. Be sure to fasten seat belts (conditional comments or the like) before using this:
td ul {
color: expression(/TD/.test(this.parentNode.tagName)? "blue" : "black");
}
This assumes "black" as the outer color. If this color value is subject to change, your are out of luck, I'm afraid. Unless you can define an expression() that is able to get the color value from the context (e.g. checking some other properties of parent elements). Or you give up and use a JS framework, as someone else has already suggested.
The wimpy solution without having to use JS would of course be:
td ul.first {
color: blue;
}
But I can see why you want to avoid that.
Use this to make sure the inherit overrides whatever else might have been setting the color:
blockquote em {
color: inherit !important;
}
Give up and use a snippet of javascript to detect the style of the parent and set it? :)
Rather than trying to force a selector to inherit font colour from its grandparent, I would suggest that you give the selector and its grandparent a shared declaration for the font colour.
Taking the blockquote example, assuming that body is the grandparent:
body, blockquote em {
color:[whatever];
}
blockquote {
color:red;
}
And in the case of the unordered lists, it would be:
body, ul ul {
color:[whatever];
}
ul {
color:blue;
}
My CSS is a bit rusty, but this should work:
blockquote {
color: red;
}
blockquote em {
color: inherit;
}
You are setting blockquotes to red, but all <em>'s that are contained in a blockquote should inherit... hmmm, should they inherit from the surrounding text, or from the blockquote?
If the above does not work as you want, then there is no way to do it with the current markup, I think. You would have to work with additional markup, or set the colour explicitltly, e.g.
blockquote em {
color: Purple;
}
Ok, the additional text with example clarifies the question a lot. And I'm affraid that what you want is not possible.
If you know the "unknown colour" you can of course repeat the color. But I think CSS needs some mechanism to add variables or references.
So you have to stick to the cumbersome:
ul {
color: blue;
}
li ul {
color: sameenvironment; /* Sorry but you have to add the specific colour here */
}
If you can change your html you could try
<li><span>This text should be BLUE</span>
<ul>
<li>Same as outside the UL</li>
<li>Same as outside the UL</li>
</ul>
</li>
and the style
li span{
color: blue;
}
EDIT
another way to accomplish this without the extra span tag:
If we assume that we have a style class (or any other selector) that defines to parent of the outer ul. We can modify the css like this:
.parentStyle,
.parentStyle li li{
color:red;
}
li{
color:blue;
}
I too had this question but after I glanced at the other answers it hit me,
body {
color : initial;
}
IE doesn't support this currently and Gecko requires a -moz-initial I believe..
body {
color : unset;
}
This one isn't quite as supported right now. I just thought I'd share my answer to this for anyone else who thinks about this.

Resources