Skip to content

How to override theme colors now? #23112

Closed

Description

@martinbean

I’ve noticed in _variables.scss that the brand colours have been moved to a nested object.

Up to now, I‘ve been specifying variable overrides in a _custom.scss in my projects like this:

@import "custom";
@import "node_modules/bootstrap/scss/bootstrap";

I’d then override the variables I wanted in my _custom.scss file like this:

$brand-primary: #fc0;

$font-family-sans-serif: "Open Sans", sans-serif;

How do I override values on a per-variable basis now that they’re inside an object? For example, I have a project where I want the brand’s primary color to be green and not blue.

Sorry if this a n00b question, but I’m under the impression that object members like $theme-colors[primary] aren’t overridable in Sass without overriding the whole object, in which case these seriously reduces the configurability of Bootstrap in version 4.

If I’m doing something wrong, or I can override specific members of objects in Sass, then please let me know.

Activity

  1. bkdotcom commented on Jul 17, 2017

    @bkdotcom
    Contributor
  2. mdo commented on Jul 17, 2017

    @mdo
    Member

    While it does appear you cannot override part of the Sass maps, much like our variables, they do have the !default flag. See this example for how you can change the variable or Sass map. IMO this is a fine approach as it maps to variables—copy, paste, and change the value.

    How do I override values on a per-variable basis now that they’re inside an object?

    We also still have all the regular color variables, so you can customize the Sass map or you can change the base variables. See the variables file:

    $blue:    #007bff !default;
    $indigo:  #6610f2 !default;
    $purple:  #6f42c1 !default;
    $pink:    #e83e8c !default;
    $red:     #dc3545 !default;
    $orange:  #fd7e14 !default;
    $yellow:  #ffc107 !default;
    $green:   #28a745 !default;
    $teal:    #20c997 !default;
    $cyan:    #17a2b8 !default;
    
    $colors: (
      blue: $blue,
      indigo: $indigo,
      purple: $purple,
      pink: $pink,
      red: $red,
      orange: $orange,
      yellow: $yellow,
      green: $green,
      teal: $teal,
      cyan: $cyan,
      white: $white,
      gray: $gray-600,
      gray-dark: $gray-800
    ) !default;
    
    $theme-colors: (
      primary: $blue,
      secondary: $gray-600,
      success: $green,
      info: $cyan,
      warning: $yellow,
      danger: $red,
      light: $gray-100,
      dark: $gray-800
    ) !default;
  3. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @mdo I get that the theme colours have been mapped to “named” colour variables, but if I want my theme to be primarily green, I don’t want to be changing the value of $blue to be a green since $theme-colors[primary] is mapped to $blue.

    I’m not liking the fact I have to copy-and-paste and override X, Y and Z just to change one setting. What happens if the keys in the map change? My theme’s going to break. Why do I have all these dependencies just to change one single colour in Bootstrap?

  4. dushkostanoeski commented on Jul 18, 2017

    @dushkostanoeski

    @martinbean you don't need to change the value of $blue to green, you only have to change the primary color to $green in $theme-colors

  5. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @dushkostanoeski But I have to copy the whole of $theme-colors map into my _custom.scss file, and then also also the individual colour variables ($blue etc) because they’re referenced in the map.

    All that, just to change one colour!

  6. houfio commented on Jul 18, 2017

    @houfio

    You don't have to import the color variables if you import the _variables.scss file in your custom.scss file

  7. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @houfio That defeats the point of them having the !default flag if I just have to import them and override them any way?

  8. houfio commented on Jul 18, 2017

    @houfio

    I guess so. Are you sure you have to copy them if you don't reference the file? It should work fine, because the bootstrap base file imports it too.

  9. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @houfio Did you take a look at my original post? I define custom variable values in a _custom.scss file that‘s included before Bootstrap. It’s in fact, what the comments say to do in the _variables.scss file: https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss#L3-L4

    However, with colours now being nested in a map, it’s created this awkward scenario where I need to copy whole blocks of variable definitions and hope Bootstrap doesn’t change the name or “shape” of the map (which is has been known to do in the past); or include its variables files before mine, making the point specifying values to override the defaults pointless.

  10. houfio commented on Jul 18, 2017

    @houfio

    I know it it included before bootstrap, but because of the !default, it doesn't reassign the variable and uses the one in your _custom.scss file. Your _custom.scss file can't find the color variables, but iirc that shouldn't be a problem, since the map gets accessed in files where the colors are imported (unless I'm missing another problem)

  11. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @houfio My problem is, I just want to set the primary brand colour to be something other than blue. Before, I could have a _custom.scss file with this in:

    $brand-primary: #006400;

    That was it. Everything the “primary” colour (buttons etc) would then be a dark green when Bootstrap was compiled.

    Now I can’t do that as that variable’s been removed and instead the theme colours folded into a map.

  12. houfio commented on Jul 18, 2017

    @houfio

    If you don't need any of the other colors you can just do

    $theme-colors: (
      primary: #006400
    )

    since all the calls to the map are loops.

  13. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @houfio I do want the other colours though! I just want to override one of the theme’s colours, and not have to copy a whole map to do so!

  14. houfio commented on Jul 18, 2017

    @houfio

    I suppose this change is good if you want much customization, but not so much if you just want to change one color. But copying a map isn't that bad, is it?

    You can also just import the variables file, which does defeat the point of the !default, but allows you to use the map_merge method.

  15. martinbean commented on Jul 18, 2017

    @martinbean
    ContributorAuthor

    @houfio My gripe with copying a whole map (and its dependent variables) is that, I’m then relying on Bootstrap not to change anything, which was the point of having a file of variable overrides in the first place. It just seems I have to go “too deep” into Bootstrap now to change one thing.

  16. fluke commented on Jul 20, 2017

    @fluke

    This change makes overriding not work. Coming from a Rails example. I too want to change my theme to green. The following doesn't work. And it's not feasible for me to go and change the variables.scss

    // Custom bootstrap variables must be set or imported *before* bootstrap.
    $green: #89B630;
    
    $theme-colors: (
      primary: $green
    );
    
    @import "bootstrap";

    Currently have to change $blue to get the correct result.

  17. cr101 commented on Jul 20, 2017

    @cr101

    @kartikluke Ideas in #22891 might help

  18. martinbean commented on Jul 20, 2017

    @martinbean
    ContributorAuthor

    @cr101 Doesn’t really help, as it seems to be people discussing the same issue as in here.

  19. mdo commented on Jul 20, 2017

    @mdo
    Member

    Bringing over the entire Sass map doesn't seem unreasonable to me... is the biggest concern that this feels heavy handed when compared to the old $brand-{color} variables?

  20. martinbean commented on Jul 20, 2017

    @martinbean
    ContributorAuthor

    is the biggest concern that this feels heavy handed when compared to the old $brand-{color} variables?

    @mdo Exactly that. When overriding a $brand-{color} variable, I’m overriding what I want, and only what I want. To copy over a whole Sass map just to change one colour in that map just seems overly cumbersome, especially when I also have to re-define the individual colour variables referenced in that map, i.e. $blue et al. So changing the primary color goes from this:

    $brand-primary: #006600;

    To this:

    $gray-100: #f8f9fa;
    $gray-600: #868e96;
    $gray-800: #343a40;
    
    $red: #dc3545;
    $yellow: #ffc107;
    $green: #006600; // This is the only variable I wanted to change
    $cyan: #17a2b8;
    
    $theme-colors: (
      primary: $green,
      secondary: $gray-600,
      success: $green,
      info: $cyan,
      warning: $yellow,
      danger: $red,
      light: $gray-100,
      dark: $gray-800
    );
  21. bkdotcom commented on Jul 20, 2017

    @bkdotcom
    Contributor

    @martinbean

    will this not work?

    $theme-colors = map_merge($theme-colors, {success: $green});
    
  22. martinbean commented on Jul 20, 2017

    @martinbean
    ContributorAuthor

    @bkdotcom Not unless I import the whole of _variables.scss first 😩

  23. fluke commented on Jul 21, 2017

    @fluke

    @martinbean @mdo The solution outlined here seems to be the best option. #22891 (comment)

    // In a custom variables file...
    $theme-colors: (
      primary: red
    );
    
    
    // In Bootstrap's _variables.scss file...
    $theme-colors: () !default;
    $theme-colors: map-merge((
      primary: $blue,
      secondary: $gray-600,
      success: $green,
      info: $cyan,
      warning: $yellow,
      danger: $red,
      light: $gray-100,
      dark: $gray-800
    ), $theme-colors);
    
  24. mdo commented on Jul 25, 2017

    @mdo
    Member

    @kartikluke Nice! That does work: https://codepen.io/anon/pen/XaJeVd. I'll see about a PR shortly.

  25. fluke commented on Jul 25, 2017

    @fluke

    @hokiecoder figured it out. This should make it much easier to work with the new maps.

  26. mdo commented on Aug 9, 2017

    @mdo
    Member

    Please see #23260 for @hokiecoder's suggestion that @kartikluke pointed out here. Any feedback is most definitely welcomed!

  27. aManNamedJed commented on Nov 12, 2017

    @aManNamedJed

    I understand the concern. I honestly like this map feature.

  28. locked and limited conversation to collaborators on Nov 12, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions