Diego Eis
Diego Eis

Reputation: 23

SASS Color Theme without repeat elements

I need to create themes with many colors using sass, but all examples I saw I have to replicate blocks of CSS using different variable names. What I want is use same name variables on different classes colors.

What I have in my mind is something like this.

//
// My regular CSS
//
.header
    background-color: $color1
    border-color: $color2

.menu
    background-color: $color2
    border-color: $color1


//
// My colors.sass could be like this
//
.color-green
  $color1: green
  $color2: red

.color-blue
  $color1: blue
  $color2: orange

What I think the compile would give me:

.color-green .header
    background-color: green
    border-color: red

.color-blue .header
    background-color: blue
    border-color: orange

.color-green .menu
    background-color: red
    border-color: green

.color-green .menu
    background-color: orange
    border-color: blue

Is this possible?

Upvotes: 2

Views: 2517

Answers (5)

赵渊源
赵渊源

Reputation: 11

I had the same need too, then i write a loader for webpack to resolve such problem, you could check out the DEMO to see how it works, just like you expect .

This loader compile sass with different theme variables, you can register theme by sass files and javascript.

you'd create a theme folder like this:

  • themes
    • theme-a.scss
    • theme-b.scss
    • theme-c.scss

and set webpack config:

// webpack1
module: {
  loaders: [
    {
      test: /\.scss$/,
      loader: 'vue-style-loader!css-loader!sass-loader!sass-themes-loader'
    }
  ]
},
'sassThemes': {
  themePath: "absolute path of theme folder",
  //defaultTheme: "default theme name",
  //excludeTheme: ["themeName", "themeName"],
  //only: ["path of sass file"]
}

and then if you import a sass file,it will automatic themed:

div {
  color: $text-color;
  font-size: 14px;
}

will be:

div {
  color: $text-color;
  font-size: 14px;
}
.theme-a div {
  color: 'color-a'
}
.theme-b div {
  color: 'color-b'
}
.theme-c div {
  color: 'color-c'
}

for more usage,you should check out DEMO

Upvotes: 1

Diego Eis
Diego Eis

Reputation: 23

I can't run of duplicate some code. Here is the Github with the code: https://github.com/locaweb/locawebstyle/tree/v2/source/assets/stylesheets/locastyle/layout/colors

Here is the solution explained:

I create a shared.sass, where I put all elements that I need to change the colors, example:

shared.sass

#{$theme-color}

    body {
      background-color: $color2;
    }

    p {
      color: $color1;
    }

And I create other files with the name of colours that I apply. This files will have the pallete of colors in variables, like this:

green.sass

$theme-color: ".color-green"

$color1: #000
$color2: #FFF
...

@import "shared"

And a colors.sass importing all files:

@import "green"
@import "shared"

What you think guys?

Upvotes: 0

Renato Carvalho
Renato Carvalho

Reputation: 451

I had the same need a few days ago. And I found out that in Sass, you can have a multidimensional list, so instead of constructing individual variables, you'd create one variable to hold them all, then loop over them:

$themes: news #f44f74 #f497ac, sports #5cbb00 #b2e581, entertainment #00afc4 #92d3db 

@each $theme in $themes
  $area: nth($theme, 1)
  $colorA: nth($theme, 2)
  $colorB: nth($theme, 3)

  //you can use apply a class to the body so you can customize everything else easily
  div.#{$area}
    h1
      color: $colorA
      border-bottom: 2px solid $colorB
    p
      color: desaturate($colorA, 60%)

Have a look on this example I prepared on Codepen: http://codepen.io/renatocarvalho/pen/CxcEJ

Upvotes: 1

Adam Wolski
Adam Wolski

Reputation: 5656

I think sass mixins are the answer here.

Imo, the best way to do this is to create mixin called ex. generate_theme, and pass color as a parameter.

Something like this: [note: I use scss syntax]

@mixin generate_theme ($name: 'green', $color: green) { // pass as many colors you need...
    .color-#{$name} .header {
        background-color: $color;
    }
    .color-#{$name} .menu {
        background-color: $color;
    }
}

So this mixin has two parameters, but it could have more (like color palette I think?), and it has some default values (green). Parameter $name can be useful if you want to use hex values (classes like .color-#000322 wouldn't be very maintainable).

So then you just have to include your mixin like this:

@include generate_theme; // default colors
@include generate_theme('oceanlike', #000000); 

so output will be:

.color-green .header {
  background-color: green;
}

.color-green .menu {
  background-color: green;
}

.color-oceanlike .header {
  background-color: black;
}

.color-oceanlike .menu {
  background-color: black;
}

Upvotes: 0

Fabrizio Calderan
Fabrizio Calderan

Reputation: 123397

You could make a different assignment to the same variables ($color1 and $color2) with a simple if statement, checking the value of an extra variable, e.g.

$theme: light;

  @if $theme == light {

    $color1: green;
    $color2: red;

  } 
  @else if $type == dark {

    $color1: blue;
    $color2: orange;

  } 
  @else {
     /* fallback values */
  }

and for scalability I just suggest to wrap this code in a themes.scss file, and to include it at the beginning of your main sass file. When you want to change theme, just change the value of your $theme variable.

You can find further info about the @if directive on the official site

Upvotes: 0

Related Questions