Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CSS :first-of-type isn't working [duplicate]

Can anyone tell me why the second row of my table doesn't get a grey background?

<!DOCTYPE html>
<html>
<head>
<style type="text/css">
.phone td {background:blue; color:white;}
.phone:first-of-type td {background:grey;}
</style>
</head>
<body>
<table>
<tbody>
    <tr class="email"><td>Row</td></tr>
    <tr class="phone"><td>Row</td></tr>
    <tr class="phone"><td>Row</td></tr>
</tbody>
</table>
</body>
</html>
like image 847
John Avatar asked Apr 19 '15 14:04

John


People also ask

What is not() in CSS?

:not() 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. /* Selects any element that is NOT a paragraph */ :not(p) { color: blue; }

How does nth of type work?

The :nth-of-type selector allows you select one or more elements based on their source order, according to a formula. It is defined in the CSS Selectors Level 3 spec as a “structural pseudo-class”, meaning it is used to style content based on its relationship with parent and sibling elements.

How do I target a sibling in CSS?

Adjacent Sibling Selector (+) The adjacent sibling selector is used to select an element that is directly after another specific element. Sibling elements must have the same parent element, and "adjacent" means "immediately following".


2 Answers

The first-of-type selectors work on the tags or elements and not on the classes or ids. So in your case the below selector would style the <td> children of the first element of every type which also happens to have the class='phone'.

.phone:first-of-type td {background:grey;}

In your code none of the elements which are the first of it's type have the class='phone'. The first tr has class='email'.

If your first tr had the class='phone' then the style would get applied as seen in the below snippet.

.phone td {
  background: blue;
  color: white;
}
.phone:first-of-type td {
  background: grey;
}
<table>
  <tr class="email"> <!-- will not be styled because it doesn't have phone class-->
    <td>Row</td>
  </tr>
  <tr class="phone"> <!-- will not be styled either because it is not first tr -->
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
</table>

<table>
  <tr class="phone"> <!-- will be styled because it is first tr and has phone class-->
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
</table>

For your case, you can try the below CSS. This sets the background of all td whose parent has the class='phone' to grey and then overrides it for all its siblings to blue.

You can use either the adjacent sibling selector or the general sibling selector depending on your choice. General Sibling selector is the best.

Note that the adjacent sibling selector won't work complex cases where you have elements with other classes in between elements with class='phone'.

.phone td {background:grey; color:white;}
.phone ~ .phone td { background: blue;}

.phone td {
  background: grey;
  color: white;
}
.phone ~ .phone td {
  background: blue;
}

/* Adding below just to show the difference between the two selectors */
.phone + .phone td {
  color: gold;
}
<table>
  <tr class="email">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
  <tr class="email">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>  
</table>
<hr>
<table>
  <tr class="phone">
    <td>Row</td>
  </tr>
  <tr class="email">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
  <tr class="phone">
    <td>Row</td>
  </tr>
</table>
like image 91
Harry Avatar answered Nov 10 '22 01:11

Harry


:first-of-type looks for elements (in the siblings list), not complex selectors. Here, neither of your .phone elements are the first sibling -- .email is.

As far as i know, there is no way to do this in pure CSS without changing your HTML layout.

like image 24
Scimonster Avatar answered Nov 10 '22 01:11

Scimonster