skip to Main Content

I have a .card component with two variants:

.card {
  padding: 2rem;
  border: 2px solid black;
  &.is-dark {
    background: #151515;
    p {
      color: white;
    }
  }
  &.is-light {
    background: #fcfcfd;
    p {
      color: #111;
    }
  }
}
<div class="card is-light">
  <p>Some content</p>
  <div class="card is-dark">
    <p>Some sub-content</p>
  </div>
</div>
<hr />
<div class="card is-dark">
  <p>Some content</p>
  <div class="card is-light">
    <p>Some sub-content</p>
  </div>
</div>

But as visible in the snippet, for both <p>, the matching selectors are .card.is-dark p and .card.is-light p and the second wins as it is the last, while I’d expect text to be white in the .card.is-light .card.is-dark p case.

screenshot

Is there any chance I could tell my CSS to match the deepest in DOM in priority?

I thought of

.card {
  &.is-dark {
    &, :not(.is-light) {
    }
  }
}

but it wouldn’t work since it would be the is-dark that would apply while I’d expect the .is-light (in the case of .is-light within .is-dark).

3

Answers


  1. If you limit your css so that it just targets the direct children then your approach works.

    Obviously this has to be adapted, depending on how your actual card HTML will look like, I assume this is a dumbed down version of it. Maybe you can work with an additional wrapper to specify the content of a card for CSS selectors.

    .card {
      padding: 2rem;
      border: 2px solid black;
      &.is-dark {
        background: #151515;
        > p {
          color: white;
        }
      }
      &.is-light {
        background: #fcfcfd;
        > p {
          color: #111;
        }
      }
    }
    <div class="card is-light">
      <p>Some content</p>
      <div class="card is-dark">
        <p>Some sub-content</p>
      </div>
    </div>
    <hr />
    <div class="card is-dark">
      <p>Some content</p>
      <div class="card is-light">
        <p>Some sub-content</p>
      </div>
    </div>
    Login or Signup to reply.
  2. Use CSS variables and inheritance will do the right job for you.

    .card {
      padding: 2rem;
      border: 2px solid black;
      &.is-dark {
        background: #151515;
        --color: white;
      }
      &.is-light {
        background: #fcfcfd;
        --color: #111;
      }
      p {
        color: var(--color);
      }
    }
    <div class="card is-light">
      <p>Some content</p>
      <div class="card is-dark">
        <p>Some sub-content</p>
      </div>
    </div>
    <hr />
    <div class="card is-dark">
      <p>Some content</p>
      <div class="card is-light">
        <p>Some sub-content</p>
      </div>
    </div>

    Actually you don’t really need variables

    .card {
      padding: 2rem;
      border: 2px solid black;
      &.is-dark {
        background: #151515;
        color: white;
      }
      &.is-light {
        background: #fcfcfd;
        color: #111;
      }
    }
    <div class="card is-light">
      <p>Some content</p>
      <div class="card is-dark">
        <p>Some sub-content</p>
      </div>
    </div>
    <hr />
    <div class="card is-dark">
      <p>Some content</p>
      <div class="card is-light">
        <p>Some sub-content</p>
      </div>
    </div>
    Login or Signup to reply.
  3. You can fix that by using > p, but CSS custom properties can become really handy for such situations and result in a – imho – cleaner solution.

    For .card.is-dark and .card.is-light, you can specify what values the properties should have, and you can then just use those on the elements you want to use.

    .card.is-dark {
      --background-color: #151515;
      --text-color: white;
    }
    
    .card.is-light {
      --background-color: #fcfcfd;
      --text-color: 111;
    }
    
    .card {
      padding: 2rem;
      border: 2px solid black;
      background: var(--background-color);
      
      p {
        color: var(--text-color);
      }
    }
    <div class="card is-light">
      <p>Some content</p>
      <div class="card is-dark">
        <p>Some sub-content</p>
      </div>
    </div>
    <hr />
    <div class="card is-dark">
      <p>Some content</p>
      <div class="card is-light">
        <p>Some sub-content</p>
      </div>
    </div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search