Selecting only first match with CSS [duplicate] - css

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.

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.

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.

CSS selector: first child of parent

I want to select the first element of a parent matching a specific type; the css equivalent of $(parent).children()[0]. For example, h1 tags that are the first child of a parent:
<div>
<h1 id="foo"></h1> // match
<div></div> // not match
…
</div>
<section>
<h1 id="bar"></h1> // match
<div></div> // not match
…
</section>
<div>
<div id="baz"></div> // not match
<h1 id="qux"></h1> // not match
…
</div>
jsfiddle
EDIT I am aware that there is no 'parent' selector.
I'd suggest, if you want to match the first h1 of a parent element (in compliant browsers) using :first-of-type:
h1:first-of-type {
/* CSS to style the first h1 of its parent element */
}
If, however, you want to style a h1 element only if it's the first child of its parent:
h1:first-child {
/* CSS to style the h1 only if it's the first-child of its parent element */
}

CSS event on one element, changing an other

How can i change an element with CSS with an event on another element?
E.g. <div id="one"> ....., <div id="two">....
<style>
#one:hover
{
changing the visibility of #two...
}
</style>
In your case, with the element you wish to change being after the element you hover, meaning that you have a structure like:
<div id="one"></div>
<!--you could have some elements between them-->
<div id="two"></div>
or like:
<div id="one">
<!--maybe some elements-->
<div id="two"></div>
<!---->
</div>
In the first case (#one and #two are siblings, that is they are on the same level = have the same parent), you use the general sibling combinator (~), like this:
#one:hover ~ #two { /* style changes */ }
DEMO for the case when #one and #two are siblings and #one is before #two in the HTML.
In the second case (#two is a descendant of #one), you use:
#one:hover #two { /* style changes */ }
DEMO for the case when #two is a descendant of #one.
However, if you wish to change an element that is before #one in the HTML, then that is currently (meaning that this could change in the future) impossible with CSS alone (if you would like to know why, then this article offers an explanation).
But in this case, when #two is before #one in the HTML, you can do it with JavaScript. For instance, if the opacity of #two is initially 0, then you could change it to 1 when hovering #one using:
var one = document.getElementById('one'),
two = document.getElementById('two');
one.addEventListener('mouseover', function(){
two.style.opacity = 1;
}, true);
one.addEventListener('mouseout', function(){
two.style.opacity = 0;
}, true);
DEMO
And if you're using a library like jQuery, then it gets even easier:
$('#one').hover(function(){
$('#two').css({'opacity': 1})},
function(){
$('#two').css({'opacity': 0})
});​​
DEMO
Use a combination of the :hover selector and the ~ General Sibling selector:
div.margin:hover ~.margin2
{
background: #00f;
}
Hover over div 2 and you'll see the other div change.
For this to work, the divs must be siblings (have the same parent element).
http://jsfiddle.net/Kyle_Sevenoaks/mmcRp/

How can I apply a css rule to all descendants of an elements

How can you redefine a class if its in another specific class?
div.cls {
color:blue;
}
div.tst > div.cls {
color:red;
}
<div class="cls">test</div> // text color = blue
<div class="tst">
<div class="cls">test</div> // text color = red
<div>
<div class="cls">test</div> // text color = blue
</div>
<div>
How to make the last one also red?
jsfiddle
http://jsfiddle.net/gpD7H/
I used this, it work for me:
.name-of-parent * { color: red; }
Use the descendant selector [W3C]: div.tst div.cls
> is the child selector [W3C] and will only match children of an element.
Exactly like that. However, your second division won't be red text because it's also contained within another division. The > selector only matches to the immediate children under the element matched before it, so it's looking inside div.tst at only one level. Try removing the > from the selector:
div.tst div.cls {
color:red;
}
Your updated jsFiddle

Resources