Is there a third pseudo element, like after and before - css

I need something like third pseudo element for .foo.bar.
.foo.bar:before { content: "x "; }
.foo.bar:after { content: " x"; }
.foo.bar:before:before { content: "bad "; color: red; }
<div class="foo">apple</div>
<div class="foo bar">orange</div>
<div class="foo">chainsaw</div>

No. It's not possible (using CSS) to prepend to ::before or ::after's content:, or in other words — make a content:"x"; become bad x cause any defined rule will overwrite the old one, and there's no third to ::before and ::after pseudo elements.

Related

CSS: How do I select an element that is the first-of-type of one of the ancestors(not direct parent)? [duplicate]

How can I specify :first-of-type of the entire document?
I want to style the first <p> of the HTML, no mater where it is located (I don't want to write section p:first-of-type because it may be located elsewhere in a different HTML document).
p {
background:red;
}
p:first-of-type {
background:pink;
}
p:last-of-type {
background:yellow;
}
<body>
<section>
<p>111</p>
<p>222</p>
<p>333</p>
</section>
<p>444</p>
<p>555</p>
</body>
With CSS alone this unfortunately isn't possible. The documentation for the :first-of-type pseudo-class states:
The :first-of-type pseudo-class represents an element that is the first sibling of its type in the list of children of its parent element.
This means that :first-of-type is applied to the first element of its type relative to its parent and not the document's root (or the body element, in this case).
JavaScript solutions
:first-of-type
We can achieve this by introducing some JavaScript. All we need for this is JavaScript's querySelector() method, which pulls the first matching element from the selector specified.
In this example I've altered your :first-of-type pseudo-class to instead be a class of "first-of-type", then used JavaScript to add this class to the element returned when using querySelector('p'):
document.querySelector('p').className += ' first-of-type';
p {
background:red;
}
p.first-of-type {
background: pink;
}
<body>
<section>
<p>111</p>
<p>222</p>
<p>333</p>
</section>
<p>444</p>
<p>555</p>
</body>
:nth-child and :last-of-type
As for :nth-child and :last-of-type, we can instead make use of a similar method JavaScript gives us: querySelectorAll(). This method pulls all matching elements into a NodeList (which is similar to an array), which we can then iterate through or select specific elements from within through the index:
var elems = document.querySelectorAll('p');
// nth-of-type = NodeList[n - 1]
// e.g. to select the 3rd p element ("333"):
if (elems.length >= 2)
elems[2].className += ' nth-of-type';
// last-of-type = NodeList length - 1
if (elems.length)
elems[elems.length - 1].className += ' last-of-type';
p {
background:red;
}
p.nth-of-type {
background: pink;
}
p.last-of-type {
background: yellow;
}
<body>
<section>
<p>111</p>
<p>222</p>
<p>333</p>
</section>
<p>444</p>
<p>555</p>
</body>
Note that I've included if statements around both selectors to ensure the elems NodeList has enough elements, otherwise an error will be thrown.

Style span only on the first line of div

I have the following html:
<div class="pp">TWO <span>WORDS</span>
</div>
And I want to separate them by "#" for example, but only if they are on the same line.
I don't want to use any JS, only CSS.
This is not working:
.pp{
width:20%;
}
.pp::first-line span:before{
content: " # "
}
And I couldn't come up with another idea.
Note that I want one and the same element to either have or not # depending on if it appears on the same lane. E.g.
TWO # WORDS
But
TWO
WORDS
Depending on the size of the window when the 20% can't fit the TWO # WORDS, the WORDS gets on a second line, and then I want the "#" to disappear
The most obvious solution would be to use two spans (text should in text tags anyway and not text nodes).
Then you can target the second child and use :before.
.pp {
width: 20%;
}
.pp span:nth-child(2):before {
content: '#';
}
<div class="pp">
<span>TWO</span>
<span>WORDS</span>
</div>
<div class="pp">
<span>ONE</span>
</div>

CSS regex selector match one OR another condition?

I'd like to match when /(\sclassName|^className)/ is satisfied, but when selecting css. Hypothetically I would use like:
[class(^|\s)='className'] {
font-size: 5000px;
}
I've found this resource, which is very nice: The Skinny on CSS Attribute Selectors, but it doesn't mention this use case.
I just want to match "icon-" in the following 2 examples, but not the 3rd.
Here, this can be achieved with [class^='icon-]
<div class='icon-something another-class'>
Here, this can be achieved with [class~='icon-'], but this does not match when 'icon-' is at the very beginning of the class string:
<div class='another-class icon-something'>
I do not want to match this, with -icon in the middle of a string. I believe *= will match this one, as will |= :
<div class='another-icon-class another-class'>
You'll need to use two separate selectors with the same rule. CSS selectors don't really support alternation.
[class^='icon-'], [class*=' icon-'] {
/* ... */
}
div {
color: red;
}
[class^='icon-'], [class*=' icon-'] {
color: green;
}
<div class='icon-something another-class'>should match</div>
<div class='another-class icon-something'>should match</div>
<div class='another-icon-class another-class'>should not match</div>
You can use the following selectors to select any element whose class either starts with "icon-" or contains " icon-" (note the space at the start):
[class^="icon-"], [class*=" icon-"] { ... }
JSFiddle demo.

Append content via multiple CSS :after classes

Given the following HTML:
<div class="required">required only</div>
<div class="note">note only</div>
<div class="required note">required and note</div>
<div class="note required">note and required</div>
And CSS:
.required:after { content: " *"; color: red; }
.note:after { content: " +"; color: red; }
The result in Firefox 11 is:
required only *
note only +
required and note +
note and required +
Where more than one class is supplied (.required and .note) I would like to have both "*" and "+" appended to the element such that:
required and note *+
note and required +*
Is this possible using pure CSS, and if so, how?
Edit: Here's a link to jsfiddle for this example: http://jsfiddle.net/xpZST/
You'll need additional rules for this to work.
Given that the ordering of classes matters (when normally it shouldn't!), you'll need to use attribute selectors instead of class selectors, and you'll need to create two rules:
[class="required note"]:after { content: " *+"; color: red; }
[class="note required"]:after { content: " +*"; color: red; }
Simply add these rules after the ones you have and it should work, as attribute and class selectors are equally specific.
jsFiddle preview
By the way, if you have common styles you can keep your code DRY by isolating them in another rule. For example, you can select each class and give them both color: red:
.required:after, .note:after { color: red; }
jsFiddle preview

first-child not working

Should this work am I going crazy?
.project.work:first-child:before {
content: 'Projects';
}
.project.research:first-child:before {
content: 'Research';
}
<div class="project work">
<p>abcdef</p>
</div>
<div class="project work">
<p>abcdef</p>
</div>
<div class="project work">
<p>abcdef</p>
</div>
<div class="project research">
<p>abcdef</p>
</div>
projects:first-child works fine, research:first-child doesn't stick. Any ideas?
Demo It doesn't work, but whats the best way to achieve this?
:first-child only selects the first child of its parent. Nothing else.
As mentioned in a few of my other answers on the site (1 2 3 4), there is no :first-of-class pseudo-class. If you are looking to apply styles to the first of each class of your div elements, a solution is to apply the styles to all children of that class, and a general sibling selector to undo the styles from subsequent siblings.
Your CSS would then look like this:
.project.work:before {
content: 'Work';
}
.project.research:before {
content: 'Research';
}
.project.work ~ .project.work:before,
.project.research ~ .project.research:before {
content: none;
}
From the specification:
Same as :nth-child(1). The :first-child pseudo-class represents an element that is the first child of some other element.
.project.research is not the first child of its parent.
I believe you want this CSS:
.project.work p:first-child:before {content:'Projects';}
.project.research p:first-child:before {content:'Research';}
or
.project.work > p:first-child:before {content:'Projects';}
.project.research > p:first-child:before {content:'Research';}
Updated fiddle
That matches the first child of an element with the classes "project" and "work" (or "project" and "research"). You don't have to use p:first-child if it may not be a p element, you could use *:first-child instead.

Resources