0

I am learning about parent and child elements and I am trying to figure out how to select/style a grandchild element that is nested inside 3 div's without adding additional classes, ID's, or !important to resolve it. The parent div has a class of "grandchild" and there are two other div's that share the same class. I need to style only "Aaron" without selecting the other p tags associated with same class "grandchild".

<div class="parent">
  <!-- red -->
  <p>Jane</p>

  <div class="child">
    <!-- blue -->
    <p>Jim</p>

    <div class="grandchild">
      <!-- green -->
      <p>Aaron</p> <!--------------------Style ONLY this one----->

      <div class="greatgrandchild"> 
        <!-- pink -->
        <p>Victoria</p>
      </div>

      <div class="greatgrandchild greatgrandchild2">
        <!-- purple -->
        <p>Devin</p>
      </div>
      <!-- grandchild2 -->
    </div>
    <!-- grandchild -->
  </div>
  <!-- child -->

  <div class="child child2">
    <!-- coral -->
    <p>Susan</p>

    <div class="grandchild">
      <!-- aqua -->
      <p>George</p>

      <div class="greatgrandchild">
        <!-- rosybrown -->
        <p>Julie</p>
      </div>
    </div>

    <div class="grandchild grandchild2">
      <!-- sienna -->
      <p>Nancy</p>

      <div class="greatgrandchild">
        <!-- tomato -->
        <p>Bob</p>
      </div>
    </div>
    <!-- grandchild -->
  </div>
</div>
<!-- parent -->

I have reviewed other answers on Stack Overflow but couldn't find my situation. Below shows the routes to tried and solve it in CSS.

/*styles Aaron & George*/
.parent > .child > div:first-of-type > p:nth-child(1) {
  color: green;
}

/*Styles Aaron & George*/
div[class="grandchild"] > p {
  color:green;
}
<div class="parent">
  <!-- red -->
  <p>Jane</p>

  <div class="child">
    <!-- blue -->
    <p>Jim</p>

    <div class="grandchild">
      <!-- green -->
      <p>Aaron</p> <!--------------------Style ONLY this one----->

      <div class="greatgrandchild"> 
        <!-- pink -->
        <p>Victoria</p>
      </div>

      <div class="greatgrandchild greatgrandchild2">
        <!-- purple -->
        <p>Devin</p>
      </div>
      <!-- grandchild2 -->
    </div>
    <!-- grandchild -->
  </div>
  <!-- child -->

  <div class="child child2">
    <!-- coral -->
    <p>Susan</p>

    <div class="grandchild">
      <!-- aqua -->
      <p>George</p>

      <div class="greatgrandchild">
        <!-- rosybrown -->
        <p>Julie</p>
      </div>
    </div>

    <div class="grandchild grandchild2">
      <!-- sienna -->
      <p>Nancy</p>

      <div class="greatgrandchild">
        <!-- tomato -->
        <p>Bob</p>
      </div>
    </div>
    <!-- grandchild -->
  </div>
</div>
<!-- parent -->

I have tried a couple hours on this and just can't wrap my head around how to do it.

isherwood
  • 58,414
  • 16
  • 114
  • 157
TinaDev
  • 25
  • 3

3 Answers3

0

It's a bit fragile, but...

.parent .child:not(.child2) > .grandchild > p {
  border: 2px solid green
}
<div class="parent">
  <!-- red -->
  <p>Jane</p>

  <div class="child">
    <!-- blue -->
    <p>Jim</p>

    <div class="grandchild">
      <!-- green -->
      <p>Aaron</p>
      <!--------------------Style ONLY this one----->

      <div class="greatgrandchild">
        <!-- pink -->
        <p>Victoria</p>
      </div>

      <div class="greatgrandchild greatgrandchild2">
        <!-- purple -->
        <p>Devin</p>
      </div>
      <!-- grandchild2 -->
    </div>
    <!-- grandchild -->
  </div>
  <!-- child -->

  <div class="child child2">
    <!-- coral -->
    <p>Susan</p>

    <div class="grandchild">
      <!-- aqua -->
      <p>George</p>

      <div class="greatgrandchild">
        <!-- rosybrown -->
        <p>Julie</p>
      </div>
    </div>

    <div class="grandchild grandchild2">
      <!-- sienna -->
      <p>Nancy</p>

      <div class="greatgrandchild">
        <!-- tomato -->
        <p>Bob</p>
      </div>
    </div>
    <!-- grandchild -->
  </div>
</div>
<!-- parent -->

I would recommend adding some more robust tagging (attributes, IDs, etc) if possible.

Phix
  • 9,364
  • 4
  • 35
  • 62
0

Just use CSS Pseudo-classes Worked for me

.child:first-of-type .grandchild > p {
    color: green;
}

W3 School CSS Pseudo-classes

borko_24
  • 24
  • 3
  • @TinaDev CSS selectors are very powerful and this is not the only option, but I can't say whether there is a simpler one. Nevertheless, I highly recommend you to read about Pseudo-classes as it will be quite useful in styling and later in JS/JQuery DOM Manipulation. – borko_24 Apr 28 '20 at 19:23
0

First thing to explain is that my solution uses no references to attributes (ex. id, class, name, etc.) only tagName and :nth-of-type pseudo-classes and child combinators >. The reason why is because of the nature of the question. If the structure and classes were assigned in a minimal way, there probably wouldn't even be a question in the first place. That's why I avoid using <div> for every block level element. I use alternating tags for each level:

<body>          root
  <main>        1st
    <section>   2nd
      <article> 3rd
        <aside> 4th </aside>
      </article>
    </section>
  </main>
</body>

By maintaining a structure like above, and using the CSS pseudo-class :nth-of-type, we can reference the levels accurately. :nth-of-type references parent to child hierarchies like its cousin nth-child but what makes it superior to nth-child is that it references the type of tag as well. Although using nth-of-type on the same tags may seem redundant, we can still get accurate results if we reference <body> since it is unique, is the ancestor of almost every tag, and has no sibling tags.

body > div > div:first-of-type > div:first-of-type > p {
 color: green
}
  1. body anchors the first reference which cannot be inferred to be anything but what it is. As long as each segment of the selector establishes a solid reference from its parent, there is less of a chance that any ambiguities muck everything up. The only child body has is div.parent so > div is sufficient.

  2. > a direct descendant (or child) combinator narrows down possibilities to two div.child.

  3. :first-of-type pseudo-class narrows down the possibility to only the first div.child. Moreover, if first-child were to be used, then the <p> would be targeted instead.

  4. Another > div:first-of-type brings us to the first div.grandchild

  5. > p narrows down to <p>Aaron</p>.

  6. Note that the child combinator > plays a very important part. If we had neglected it on the final stage, div:first-of-type p would've grabbed all descendant <p> -- which would mean <p>Victoria</p> and <p>Devin</p> would also be green.

  7. One more thing to remember is that even the most succinct selectors (such as the one I have provided) may still bleed over its styles over to its descendants. If your CSS exhibits that particular behavior, it's most likely due to inheritance. That can only be addressed on a case-by-case basis unfortunately.


Demo

body > div > div:first-of-type > div:first-of-type > p {
 color: green
}
<div class="parent">
  <!-- red -->
  <p>Jane</p>

  <div class="child">
    <!-- blue -->
    <p>Jim</p>

    <div class="grandchild">
      <!-- green -->
      <p>Aaron</p>
      <!--------------------Style ONLY this one----->

      <div class="greatgrandchild">
        <!-- pink -->
        <p>Victoria</p>
      </div>

      <div class="greatgrandchild greatgrandchild2">
        <!-- purple -->
        <p>Devin</p>
      </div>
      <!-- grandchild2 -->
    </div>
    <!-- grandchild -->
  </div>
  <!-- child -->

  <div class="child child2">
    <!-- coral -->
    <p>Susan</p>

    <div class="grandchild">
      <!-- aqua -->
      <p>George</p>

      <div class="greatgrandchild">
        <!-- rosybrown -->
        <p>Julie</p>
      </div>
    </div>

    <div class="grandchild grandchild2">
      <!-- sienna -->
      <p>Nancy</p>

      <div class="greatgrandchild">
        <!-- tomato -->
        <p>Bob</p>
      </div>
    </div>
    <!-- grandchild -->
  </div>
</div>
<!-- parent -->
Community
  • 1
  • 1
zer00ne
  • 41,936
  • 6
  • 41
  • 68