Search code examples
csssassless

Is there a way to assign the same value to 2 css properties at once?


Using CSS, LESS, or Sass can you assign the same value to 2 css properties at once?

Just like:

.c1, c2 {sameValue}

But instead like this:

.c2 { background-color:, color: sameValue}

Solution

  • Update for LESS v3.0.0 and CSS Custom Properties

    CSS

    CSS variables are supported in all major browsers and most many browsers (ref: caniuse).

    See zzzzBov's answer for an example.

    Less v3+

    Since 2017, LESS can look up a property:

    .demo {
      background-color: red;
      color: $color;
    }
    

    See the docs for details.


    Original answer

    CSS

    You can't do this with CSS.

    LESS, Sass

    The easiest way to do this is use a variable. Here's how you'd do that in LESS

    @color: red;
    .demo {
      background-color: @color;
      color: @color;
    }
    

    and the same thing in Sass

    $color: red;
    .demo {
      background-color: $color;
      color: $color;
    }
    

    But you can also achieve the power you want. Here's one way you could do it in LESS:

    .properties(@properties, @value, @i: 0) when (@i < length(@properties)) {
      @property: extract(@properties, @i + 1);   // get the property
      @{property}: @value;                       // write the style
      .properties(@properties, @value, (@i + 1)) // loop
    }
    
    .demo {
      @props: background-color, color;
      .properties(@props, red)
    }
    

    will compile to your desired

    .demo {
      background-color: red;
      color: red;
    }
    

    How's it work?

    • .demo calls the .properties parametric LESS mixin, passing a list (sometimes called an array in other SO questions about CSS/etc) of properties (.properties's @properties parameter; in this example, @props) and the value to assign to all of them (.properties's @value parameter; in this example, red).
    • note that .properties has a counter parameter @i with a default value of 0.
    • .properties has a LESS CSS guard that checks to see if @i is less than the number of properties it was passed (held in @properties). It is! (@i is 0, and the properties' list is certain to be at least 1) Okay, so we're allowed past the guard.
    • Get the name of the property: use LESS's extract() on the first item in the list (we need to say @i + 1 because we started the @i counter at 0. we could have also started @i at 1, and guarded with when (@i < (length(@properties) + 1)) but that's harder to read)
    • At last: write the style. interpolate the variable holding the property name (@property) as a string (@{property}), and give it the value we originally passed to .properties in .demo (@value)
    • LESS loop! Run .properties again, but advance the counter @i one: .properties(staysTheSame, staysTheSame, (@i + 1))
    • .properties will run until it's looped through all the items in its @properties list. After that, @i will equal length(@properties), so we won't pass the when (@i < length(@properties)) guard.

    Note that @props could be defined within .test, as above, or anywhere where .test will have access to it, and same for the value. You might end up with

    @props: background-color, color;
    @val: red;
    @val2: green;
    .properties {...}
    .demo {
      border-color: @val2;
      .properties(@props, @val)
    }
    .demo2 {
      .properties(@props, @val2)
    }