pseudo selector for second child exact like first-child - css

Is there a identical psuedo selector that acts like :first-child but with second child of a parent element?
I used
:nth-child(2) but is that the only equivalent it seems it resolves slightly differently when styles are applied. I also like the legibility of :first-child
If that is the equivalent why use :first-child and not :nth-child(1) what is correct selectors with most support for accessing first and second child elements of div container?

No, there is no such selector. You should use :nth-child(2).
And :first-child is older browser compatible than :nth-child(1) so we use :first-child
And if you're using :nth-child(2), you shouldn't be confusing to use :nth-child(1) in your own.

In addition to :nth-child(2), you can use the combined selector
:first-child + *
which refers to the same elements, since it denotes any element that is the next sibling for any first child. More normally, you would be using something like p:nth-child(2), and then the equivalent selector is
:first-child + p
“Equivalence” means here that the selectors denotes the same sets of elements. They are different in specificity, so care needs to be taken when this matters.
The combined selector is slightly more cross-browser, since the constructs involved are supported by IE 8, which does not support :nth-child(2).
Example:
<style>
:first-child + p {
outline: solid red;
}
p:nth-child(2) {
background: gray;
}
</style>
<div>
<p>foo
<p>bar
<p>more
</div>

Related

Understanding the :not selector css

I'm trying to get my head around the not selector is css. I'm trying to hide a div called "InfoRow" if the page doesn't have a class of 'home'
My first stab at this:
:not(body.home #InfoRow) {
display:none;
}
From MDN:
The :not() CSS pseudo-class represents elements that do not match a list of selectors. Since it prevents specific items from being selected, it is known as the negation pseudo-class.
:not(.foo) will match anything that isn't .foo, including <html> and <body>
As the class .home would be set on the <body> tag, and #InfoRow is a child of <body>, you'd have to write it like this:
body:not(.home) #InfoRow {
display: none;
}

Two classes in :not() doesn't seem to work in Safari, but it works in Firefox and Chrome

I'm using this snippet and it works in Firefox and Chrome, but not in Safari. Why?
.column:not(.custom.no-edit)
If I change it to this it seems to work, but that doesn't give the same effect does it? If I'm thinking correctly the first one will give true if both classes are present while the second will give true if any of the classes are present?
.column:not(.custom):not(.no-edit)
Consider the following HTML fragment:
<div class="column"></div>
<div class="column custom"></div>
<div class="column no-edit"></div>
<div class="column custom no-edit"></div>
The selector
.column:not(.custom.no-edit)
is level 4 syntax that matches .column elements that don't have both "custom" and "no-edit" in their class attributes. This means that .column elements that have either one or the other will match. All of the first three elements in the fragment will match — only the fourth will not.
In level 3 implementations, the syntax is considered invalid and gets ignored, resulting in none of the elements in the fragment matching the selector.
The level 3 equivalent that's understood by Firefox and Chrome is
.column:not(.custom), .column:not(.no-edit)
The selector
.column:not(.custom):not(.no-edit)
is level 3 syntax that matches .column elements that don't have either "custom" or "no-edit" in their class attributes. Only the first element in the fragment will match this selector. The level 4 equivalent is
.column:not(.custom, .no-edit)
Hopefully this helps you understand the results you expect and the results you actually get.
See also:
Why is my jQuery :not() selector not working in CSS?
:not() selector not behaving the same between Safari and Chrome/Firefox
Are you sure .column:not(.custom.no-edit) worked in chrome and FF but not safari ?
That is a CSS level 4 syntax. However Safari is known to support it.
Let's take a look at the spec.
CSS level 3
The The negation pseudo-class, :not(X), is a functional notation taking a simple selector (excluding the negation pseudo-class itself) as an argument. It represents an element that is not represented by its argument.
A simple selector is either a type selector, universal selector, attribute selector, class selector, ID selector, or pseudo-class.
Something that is not mentioned in the spec, :not() does not accept compound Selectors
A compound selector is a sequence of simple selectors that are not separated by a combinator, and represents a set of simultaneous conditions on a single element.
Basically chaining classes and types etc.., Example:
.class1.class2.class3
#myId.MyClass
div.MyClass#yourId
CSS level 4
The The negation pseudo-class, :not(), is a functional pseudo-class taking a selector list as an argument. It represents an element that is not represented by its argument.
In CSS level 4 it will become free for all.
Is div:not(.a):not(.b) equal to div:not(.a.b)
div {
display: inline-block;
width: 80px;
height: 80px;
border: 4px solid black;
}
div:not(.a.b) {
background-color: green;
}
<h3>div { ... }: select all divs</h3>
<h3>.a.b { ... }: select all elements with both classes .a and.b </h3>
<h3>If we combine the two using :not() The first two boxes should be green</h3>
<div class="a"></div>
<div class="b"></div>
<div class="a b"></div>
If the above selector were to work it will select everything except those elements that have both classes a and b
Which means it is not equivalent to div:not(.a):not(.b) as this will ignore all elements that have both classes or either one, And we only want to ignore elements that have both.
Solution
We can make use of attribute selectors until css level 4 drops in, if you don't mind a bit of care.
div:not([class^="a b"])
This will select all div elements except those that begin with both classes a and b other classes can be applied to the element so styling will be normal.
Your classes must always be preceded by the string a b in order for this to work, same goes the opposite selector [attr$=value]
div {
display: inline-block;
width: 80px;
height: 80px;
border: 4px solid black;
}
div:not([class^="a b"]) {
background-color: green;
}
<div class="a"></div>
<div class="b"></div>
<div class="a b some other classes"></div>
Most browsers support attribute selectors, so support won't be a problem.

Are :before :after siblings?

The purpose of the question is to investigate the possibility of doings something like:
.element:before {
content: 'before';
color: orange;
}
.element:after {
content: 'after';
color: green;
}
.element:after:hover + .element:before {
color: red;
}
<div class='element'> </div>
Pseudo-elements cannot be targeted by sibling combinators because sibling combinators only represent element siblings, not pseudo-element siblings.
So, although the boxes generated by ::before and ::after are siblings of one another in terms of layout, for the purposes of sibling combinators they are not.
It is not possible to write a selector styling an element's ::before pseudo-element when its ::after pseudo-element is hovered. (For that matter, ::after:hover is not valid outside of Selectors 4 either, and no implementations exist.) There are hacks that make use of things like pointer-events but there is nothing that is guaranteed to work on all browsers.

Select recursive :last-child. Possible?

In CSS, is it possible to recursively select all :last-child from body?
Given this markup:
<body>
<div id="_1">
<div id="_2"></div>
</div>
<div id="_3">
<div id="_4">
<div id="_5"></div>
<div id="_6"></div>
</div>
</div>
</body>
I am looking for div no. 3, 4 and 6
Another way to put it is this:
body > :last-child,
body > :last-child > :last-child,
body > :last-child > :last-child > :last-child,
body > :last-child > :last-child > :last-child > :last-child {
/* My stuff here */
}
But obviously this is not a good approach.
No, unfortunately that's just about the only way to do it without modifying the HTML.
There has been at least one request for recursive versions of the :first-child and :last-child pseudo-classes, but it doesn't seem to have gained much favor. Notice it suggests nesting and repeating the pseudo-classes in the same way as in your question:
Currently, AFAIK, we can only match children up to some exact nesting level known in advance (3 in the example below):
.container > :first-child,
.container > :first-child > :first-child,
.container > :first-child > :first-child > :first-child {}
We cannot use just :first-child context selector since it would also select first children of blocks that are not first children themselves.
So we need a sort of recursive selector that matches not just first of last child, but recursively matches all first-most and last-most elements regardless of their nesting level.
body :last-child {
color:red;
}
body :not(:last-child) :last-child {
color:initial;
}
Any last-child element that's a descendant of one that's not a last-child will have the change reversed.
No need to chain all the way. It would be simply like this
div:last-child {
/* Your GREAT css */
}
Demo
Update: On that case, give the div2 a typical class and use :not() to push out of the selection
div:last-child:not(.nolist) {
border: 1px solid red;
}
Demo

style 2nd element on the page with same class

Hello is there a way with css to style the 2nd element on page with the same class slightly differently to the first.
For example I have two ul's on a page with a class of topbardropdownmenu. I want to give the 2nd ul a differen't background to the first. Is there a way to do this with out altering the html?
You can do it with the :nth-child() pseudo-selector. It is CSS3 though, and not supported in some browsers (e.g. <=IE8 & <=FF3.0 doesnt support it).
.topbardropdownmenu:nth-child(2) { background: #FF0000; }
You could do it with JavaScript in a cross-browser compatible way though, if that's an option for you.
What holds the <ul> elements? I'll assume a <div id = "lists">
/* First element */
div > ul.topbardropdownmenu:first-child{
}
/* Rest of the elements */
div > ul.topbardropdownmenu{
}
...alternatively
div > ul.topbardropdownmenu:not(:first-child)
It depends which browsers your users are using, you might be able to use the nth-of-type css pseudo-selector:
ul.topbardropdownmenu:nth-of-type(2) {
/* styles the second ul of class=topbardropdownmenu
}
If there's a particular pattern to the occurrence of these ul elements, you could use descendant and/or sibling selectors:
div > ul.topbardropdownmenu {
/* styles all ul.topbardropdownmenu that are the immediate descendants of a div */
}
p + ul.topbardropdownmenu {
/* styles all ul.topbardropdownmenu that immediately follow a p */
}
Look at the CSS3 nth-child() pseudo-class.
You can use :nth-child http://css-tricks.com/how-nth-child-works/ but IE may struggle with it. Consider this jQuery alternative:
$(".class").eq(1).css();
http://api.jquery.com/eq/

Resources