Andrew
Andrew

Reputation: 343

How to style nested elements based on parent class using Tailwind CSS?

Let's say I want all the links inside white card to be black, and all the links inside orange cards to be white. I can easily do in pure CSS:

.card--primary {
  background-color: white;

  a {
    color: black
  }
}

.card--danger {
  background-color: orange;
  
  a {
    color: white;
  }
}

But how can I achieve similar behaviour using Tailwind (or other CSS utility frameworks)?

Upvotes: 32

Views: 56639

Answers (6)

any_h
any_h

Reputation: 568

Nowadays Tailwind has arbitrary variants:

<div className="[&_a]:text-blue-500">
  <a href="#">Foo</a>
</div>

Related: starting from v3.4, * can be used to style child elements:

<div className="*:text-red-500">
  <a href="#">Foo</a>
  <a href="#">Bar</a>
  <a href="#">Baz</a>
</div>

Upvotes: 2

Zmyślny
Zmyślny

Reputation: 321

In case of Tailwind CSS

Read the descriptive and a very brief documentation entry here: Using arbitrary variants.

As I can see you need to change the color of all the <a> links no matter how deeply they reside in the <cards>. Use an underscore between & and a selectors - [&_a]:text-black. This translates to:

.card--primary {
      
  /* arbitrarily nested <a> links */
  a {
    color: black
  }
}

On the other hand the Tailwind directive with > between & and a => [&>a]:text-black would result in this css (only the direct child <a> nodes would be styled):

.card--primary {
      
  /* direct-child <a> links */
  > a {
    color: black
  }
}

Recap: the resulting Tailwind HTML for your case:

<div className="card--primary [&_a]:text-black" >
  <a></a> !-- will be black
  <div>
    <a></a> !-- will be black
  </div>
<div/>

<div className="card--danger [&_a]:text-white" >
  <a></a> !-- will be white
  <div>
    <a></a> !-- will be white
  </div>
<div/>

That's it. I hope it is helpful.

Upvotes: 29

Jeff Landfried
Jeff Landfried

Reputation: 101

In tailwind v3 you can have arbitrary group selectors. This allows you to specify a how a certain element behaves when nested beneath a parent class.

This is useful when you have a templated element needs to appear different under certain scenarios, but doesn't know anything about its parent context.

It requires the addition of the .group class, but then you can do something like this:

<div class="card">
  <a href="#" class="text-black group-[.card--danger]:text-white">
    Normal Card
  </a>
</div>
<div class="card group card--danger bg-orange-600">
  <a href="#" class="text-black group-[.card--danger]:text-white">Danger Card</a>
</div>

Here's an example on Tailwind's playground: https://play.tailwindcss.com/IQ4W4BVdjw

Upvotes: 10

Sam Britt
Sam Britt

Reputation: 9

I see where each of you are coming from, but if you are asking how to do it strictly in Tailwind:

<div class="bg-white text-black">
  <a></a>
  <a></a>
</div>
<div class="bg-black text-white">
  <a></a>
  <a></a>
</div>

Everyone else's answer seemed a little bloated.

Upvotes: 0

MagnusEffect
MagnusEffect

Reputation: 3905

YOu can do this way

<script src="https://cdn.tailwindcss.com"></script>
<div class="relative bg-slate-100 flex min-h-screen flex-col justify-center overflow-hidden bg-gray-50 py-6 sm:py-12 space-y-9">
<div class="relative bg-white px-6 pt-10 pb-8 shadow-xl ring-1 ring-gray-900/5 sm:mx-auto sm:max-w-lg sm:rounded-lg sm:px-10">
    <div class="mx-auto max-w-md">
      
      <div class="divide-y divide-gray-300/50">
        <div class="space-y-6 py-8 text-base">
          <p>White Card with all black links:</p>
          <ul class="space-y-4">
            <li class="flex items-center">
              
              <a href="https://tailwindcss.com"> First Link</a>
            </li>
            <li class="flex items-center">
              
               <a href="https://tailwindcss.com"> Second Link</a>
            </li>
            <li class="flex items-center">
              
               <a href="https://tailwindcss.com"> Third Link</a>
            </li>
          </ul>
          </div>
       
      </div>
    </div>
  </div>


  <div class="relative bg-orange-700 px-6 pt-10 pb-8 shadow-xl ring-1 ring-gray-900/5 sm:mx-auto sm:max-w-lg sm:rounded-lg sm:px-10">
    <div class="mx-auto max-w-md">
      
      <div class="divide-y divide-gray-300/50">
        <div class="space-y-6 py-8 text-base text-white">
          <p>Orange Card with all white links:</p>
          <ul class="space-y-4">
            <li class="flex items-center">
              
              <a href="https://tailwindcss.com"> First Link</a>
            </li>
            <li class="flex items-center">
              
               <a href="https://tailwindcss.com"> Second Link</a>
            </li>
            <li class="flex items-center">
              
               <a href="https://tailwindcss.com"> Third Link</a>
            </li>
          </ul>
          </div>
       
      </div>
    </div>
  </div>
</div>

Upvotes: 0

OneTuskedMario
OneTuskedMario

Reputation: 538

This is possible in tailwind 3.1 with the addition of the arbitrary variants feature. The way you would do this is by using a selector on the parent div:

<div className="card--primary bg-white [&>a]:text-black" >
  <a/>
  <a/>
<div/>

<div className="card--danger bg-orange [&>a]:text-white" >
  <a/>
  <a/>
<div/>

Upvotes: 43

Related Questions