csscss-cascade

CSS: deepest in DOM priority


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).


Solution

  • 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>