0

I have a variable called --primary-color defined at root like this:

:root {
  --primary-color: red;
}

In a small section in my site I want to change the primary-color for all nested elements. I currently change the primary color like this:

<button class="PrimaryButton">red</button>

<div style="--primary-color: purple">
  <button class="PrimaryButton">purple</button>
</div>

However notice i had to put the purple style on a div. This changes layout. Is there some element or someway I can change the variable without using a layout element like a div? I can't use as that affects global.

Here is example:

:root {
  --primary-color: red;
}

.PrimaryButton {
  background-color: var(--primary-color);
  width: 100px;
  height: 40px;
}
<button class="PrimaryButton">red</button>

<div style="--primary-color: purple">
  <button class="PrimaryButton">purple</button>
</div>

Thank you!

4
  • whats exactly the issue with having another css variable? Commented Feb 17, 2022 at 16:29
  • Thanks for asking @D.B.K - the <button> component is reusable component. If I introduce a new variable, I cannot reuse that <button> component which is tied to that variable of --primary-color. I would have to make a new button respecting new variable. Commented Feb 17, 2022 at 17:50
  • 1
    ohkay. Are you restricted in terms of frameworks/libraries that you can use? I guess you would benefit from CSS-in-JS libs like emotion and styled components Commented Feb 17, 2022 at 18:52
  • Thanks for that question @D.B.K - I'm trying to use plain CSS, intalling a lib will require some detailed approval process. But maybe I can replicate what that lib is doing to encapsulate the style, do you know what they do? Commented Feb 18, 2022 at 0:09

1 Answer 1

2

Solution #1. If I understood your question correctly, you can keep a div in the structure, but make it not affect the layout too much with display: contents;. I've extended your example (with a CSS grid and a couple of elements added for clarity) so you can see that the div with display: content; has no effect on the structure:

:root {
  --primary-color: red;
}

.PrimaryButton {
  background-color: var(--primary-color);
  width: 100px;
  height: 40px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}
<section class="grid">

  <button class="PrimaryButton">red 1</button>

  <div style="--primary-color: purple; display: contents;">
    <button class="PrimaryButton">purple 1</button>
    <button class="PrimaryButton">purple 2</button>
  </div>

  <div style="--primary-color: aquamarine; display: contents;">
    <button class="PrimaryButton">aquamarine 1</button>
    <button class="PrimaryButton">aquamarine 2</button>
  </div>

  <div style="--primary-color: pink; display: contents;">
    <button class="PrimaryButton">pink 1</button>
  </div>

</section>

Solution #2.. If you need to support older browsers, then CSS Combinators such as ~ or + (+ display:none for third-party elements) can help you. Example below:

:root {
  --primary-color: red;
}

.PrimaryButton {
  background-color: var(--primary-color);
  width: 100px;
  height: 40px;
}

.grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
}

.primary-color-changer,
.primary-color-only-one {
  display: none;
}

.primary-color-only-one.purple+.PrimaryButton,
.primary-color-changer.purple~.PrimaryButton {
  --primary-color: purple;
}

.primary-color-only-one.aquamarine+.PrimaryButton,
.primary-color-changer.aquamarine~.PrimaryButton {
  --primary-color: aquamarine;
}

.primary-color-only-one.pink+.PrimaryButton,
.primary-color-changer.pink~.PrimaryButton {
  --primary-color: pink;
}

.primary-color-only-one.green+.PrimaryButton,
.primary-color-changer.green~.PrimaryButton {
  --primary-color: green;
}

.primary-color-only-one.color-default+.PrimaryButton,
.primary-color-changer.color-default~.PrimaryButton {
  --primary-color: inherit;
}
<section class="grid">
  <button class="PrimaryButton">red 1 (default)</button>

  <div class="primary-color-only-one green"></div>
  <button class="PrimaryButton">green 1(only one)</button>

  <div class="primary-color-changer purple"></div>
  <button class="PrimaryButton">purple 1</button>
  <button class="PrimaryButton">purple 2</button>

  <div class="primary-color-changer aquamarine"></div>
  <button class="PrimaryButton">aquamarine 1</button>
  <button class="PrimaryButton">aquamarine 2</button>

  <div class="primary-color-changer pink"></div>
  <button class="PrimaryButton">pink 1</button>

  <div class="primary-color-changer color-default"></div>
  <button class="PrimaryButton">red 2 (default)</button>
  <button class="PrimaryButton">red 3 (default)</button>
</section>

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you this is super cool! Thanks also for sharing the browser support table. The support is very recent for this, all in 2021. Is there any other ideas you have for this too? Thanks very much again for your awesome post. I will definitely move to this in the future. Upvoted.
@Noitidart, I updated the answer for you and added a second version of the solution, which has a lot more code, but has been supported for a long time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.