Material: colors and hues should be available everywhere.

Created on 23 Jan 2015  Â·  77Comments  Â·  Source: angular/material

I created this sample on plunker to demonstrate a few issues I'm having with forms.

If you look at like 24 of index.html in my sample, you see there is a heading there. This heading is not visible in the page, because I don't know how to set the background color according to the current selected theme/colorpallete. I added an md-hue-1 to the class-list as well as an attribute, but it is not giving the result I need.

This is also mentioned in #537, but I still could not find a solution to it.

internal contributor fixed build enhancement feature

Most helpful comment

@homerjam you can have this feature in 1.1.0-rc3

All 77 comments

I took my solution from #537. and rewrote it a bit so it will work with the new $mdThemingProvider.
For anybody that need something similar, have a look at my mdColors module. It's available in this plunker

This will serve my needs for now, but it still feels awkward that I have to go trough those lengths just to be able to get my hands on the selected color palette.
I still feel like I somehow miss the obvious!

Sander, I share your feelings, your concerns... and your solution !

Thanks a lot

@iRouge I began to believe I was to only one ;)

@SanderElias - I think we should include a version of your colors.js and publish a service $mdColors service for easy color lookups.
@rschmukler - thoughts ?

@ThomasBurleson I would like that! Should I add support for md-hue-x and so on too?

@SanderElias - let's start with a simple, clean API for the initial work.
Can you create the $mdColors service and submit a PR ? Thx is advance.

I believe I have a pretty solution for color lookups: checkout my plunkr: http://plnkr.co/edit/gBDV2ABghTMqqs5YaElB?p=preview

@marcysutton I'm preparing an PR, as it looks now, I will be done by the end of the day.

@marcysutton I created a new branch, its in PR #1599. Somehow it would not let me update my other PR

This is awesome! +1

Although, even with this in place, there is still no way to alter the color swatch assignments of a directive and it's generated elements (in the CSS). For instance, the mdToast background is set to {{foreground-1}}. Haven't found a particular way to change that without using a custom template or overridden CSS.

Definitely a step in the right direction to be able to use theme colors anywhere!

@SanderElias finally got to reviewing the PR. I want to move it back a bit as I want to extend the API to make the following possible:

  • ability to lookup a color for a theme. eg. $mdColors.getTheme('default').primary.['hue-1']. This might get moved into $mdColors.getColor('default', 'primary', 'hue-1'). This would return an object with properties expressing the color and the contrast in rgba, {value: 'rgba(...)', contrast: 'rgba(...)'}. Specifically this will help with #2118
  • ability to dynamically generate stylesheets for more than one palette, and follow the .md-THEME_NAME-theme .md-primary-default-fg for selectors. This feels more consistent with how the framework on the whole works, and ideally we would allow for loading multiple themes at the same time. eg. $mdColors.generateColorCssForTheme('myOtherTheme').
  • Consider moving it all into $mdTheming as otherwise the distinction might be confusing / lots of shared logic.
  • Add proper tests for everything mentioned above

I apologize on the massive delay on this. I don't think I will have time to do all of this until after 0.10.0 ships.

@rschmukler. I agree that solving #2118 will make color handling a lot easier. It is the sole reason for the whole copying and parsing that I do in the config function.

If you like, I can switch the whole thing over to keep/utilize rgba color/colorcontrast pairs.
Also, the possibility to generate more then 1 palette is something I can create easily. It isn't in because @ThomasBurleson asked me to keep it simple.

I agree that this service should merge with $mdTheming, I kept it separate so I could work on it without messing up existing stuff ;) We can merge it into $mdTheming as soon as we have an complete solution.

@rschmukler Have been thinking about the css. I assume you only want the colors of the active theme generated? (otherwise it might be a _lot_ of css to generate!)
To keep the usage simple I would generate the colors like (sass-like nested sample)

md-primary {
   md-color-fg-400: rgba(1,2,3,.8)
   md-color-bg-400: rgba(1,2,3,.8)
   ...
}
md-accent {
   md-color-fg-400: rgba(1,2,3,.8)
   md-color-bg-400: rgba(1,2,3,.8)
   ...
}

that way it's easy to use every available color, and keep the length of the classnames a bit more in control.
But I'm open for suggestions.

Keep in mind that multiple themes can be "active" at a time.

@galpak, Are you sure? As far as I see it, the $mdTheming provider can provide just 1 theme. A theme consists out of 4 color palettes (primary,accent,warn and background). It support for loading your own colors into the palettes, and you can even provide your own palettes, but there is only 1 theme active at a time. All this can only be done during config, so there isn't much change that it's changing during runtime. It can be that I missed something, would you then be so kind to point me to it? Nevermind, You are right. there is a possibility to activate multiple themes.

As @gkalpak pointed out, there can be multiple themes active at 1 time. I can add support for this, and generate the needed CSS. However, I would suggest that if you want multiple themes, you kick off generating the css for each extra theme by hand. Each theme will add quite some CSS rules, and changes are, you won't need those for the added themes. So it will be lighter for memory and runtime if we only generate this stuff on request.
Awaiting your comments..

@SanderElias agreed that kicking off CSS generation should be done on a per-theme basis. I would even consider making that the case for the default theme since, ideally, $mdColor could also be used to just get colors.

Regarding the SCSS syntax, I'm not sure I follow your example.

Something like:

<p class="md-primary md-color-fg-50">Hello world</p>

The p would presumably be nested in a themable element, or have a theme set on it directly, making the selector as follows:

.md-default-theme .md-primary, .md-primary.md-default-theme {
  .md-color-fg-50 { color: #123456l }
  .md-color-bg-50 { background-color: #123456; }
}

Let me know if this makes sense / is what you were saying. If not, I'm definitely open to discussion... Just going off of what I'd intuit it to be.

@rschmukler I think we are (mostly) on the same page.
I think the 'default' theme can do without nesting. That would make more sense to me. Most users will go for 1 default theme, so why add the requirement of a nesting element just to set a default? Same goes for the primary color, that can be implied too.
I'll write out a small part of the actual css, to make sure we are talking the same language. (this is what needs to be generated anyway!)

/* default theme is implied*/
/* Primary is implied */
.md-color-fg-100 {color: #574EF5; }
.md-color-bg-100 {background-color: #574EF5; }

.md-warn .md-color-fg-100 ,.md-warn.md-color-fg-100 {color: #FC0366; }
.md-warn .md-color-bg-100 ,.md-warn.md-color-bg-100{background-color: #FC0366; }

/*for secondary themes */
.md-someName-theme .md-color-fg-100 {color: #03FC6B; }
.md-someName-theme .md-color-bg-100 {background-color: #03FC6B; }

.md-someName-theme .md-warn .md-color-fg-100,.md-someName-theme .md-warn.md-color-fg-100  {color: #ff0; }
.md-someName-theme .md-warn .md-color-bg-100,.md-someName-theme .md-warn.md-color-bg-100  {background-color: #ff0; }

In action in this plunk

Is that in line on how you where thinking? It also becomes clear why I don't want to generate the alternate theme's css by default. Those extra style-sheets will add quite some load.

While thinking about this, it seems to make sense to generate the default-primary palette css-rules on init, and the rest on request, or do you think that's confusing?

@SanderElias exactly! Your css look great to me.

Regarding the rules on init, I could argue either way. I think default on init seems fair. We'll just have to document that people will need to explicitly load the non-default themes. Thanks again for all of your contributions!

@rschmukler I think we a re both in a wait state now, is there any progress? I'm waiting to see what happens with #2118, if that clears, I can code this right away. If not, I can solve #2118 with an update of mdColors. But I can't decide what needs to be done there alone!

@SanderElias Quick question. I have a saas product that will allow customers to customize the colors on the site to match their own branding. Will the new functionality ($mdColors) allow me to change palettes within a theme, as well as colors within palettes at run-time rather than config time? Thanks for your work.

I doubt it will, but let's wait for @SanderElias to answer.

I have a similar use case; if the new functionality ($mdColors) does not provide this, this would be a good feature request in the form of a separate issue.

@ptrenery Not right now. Colors are extracted from the themes that are already available. There is no way to write those back.
However, you can modify the colors inside, and use those to display color swatches, up them, and write out a new theme as your are ready for it. Then you can load the custom theme at the next invcation of your app (themes are loaded during config)
Does that help a bit?

@ptrenery @Frank3K Would a palette editor do? so you can easily build your own themes?

That sounds pretty close. If you could build a theme dynamically and apply it to the page, that would be most of it. For my app at least, I only really need one theme at any one time and I'd prefer not to create the overhead of having lots of themes. I'd ideally like to be able to dynamically set palettes within the current theme or even create custom palettes entries on the fly, set them in the current theme then apply it to the page. Basically I'd like all the flexibility of $mdThemingProvider which can do all this but at run-time rather than config time. I know I'm not asking for much. :)

Well, I the building part is easy. Dynamically applying it to the page is
not so. Problem is, that MD itselfs get configured during the config phase.
MD parts are using those internal colors, and not the ones I generate CSS
for.
So, building a theme is easily possible, and displaying the new colors too,
however in the current situation I can't activate the new theme
dynamically, you need a page-refresh for that. (I can force the refresh
using code... hmmm)

A page refresh for a theme switch isn't a very big problem if you ask me.

The problem is that, since you need to choose a theme in the config part, you can not 'retrieve' the theme of the user using the $http service.

there are ways around that. I'll have dealt with those issues before.
Depends on what you need when too!

2015-04-10 18:52 GMT+02:00 Frank [email protected]:

A page refresh for a theme switch isn't a very big problem if you ask me.

The problem is that, since you need to choose a theme in the config part,
you can not 'retrieve' the theme of the user using the $http service.

—
Reply to this email directly or view it on GitHub
https://github.com/angular/material/issues/1269#issuecomment-91619449.

@Frank3K That's a good point Frank. In my implementation, I redirect to a page without material components using ui-router. I run the $http. I would then set up the theme, palettes, colors etc. Then go back to the original url. Assuming the $http request is relatively quick, it's an ok user experience.

@ptrenery, would in not be simpler to do an server side include of the
theme?

2015-04-10 18:57 GMT+02:00 ptrenery [email protected]:

@Frank3K https://github.com/Frank3K That's a good point Frank. In my
implementation, I redirect to a page without material components. I run the
$http. I would then set up the theme, palettes, colors etc. Then go back to
the original url. Assuming the $http request is relatively quick, it's an
ok user experience.

—
Reply to this email directly or view it on GitHub
https://github.com/angular/material/issues/1269#issuecomment-91621063.

@SanderElias Probably would be quicker. Not a bad idea. That would help with initialization for sure.

Lots of good discussion here. We're also building a SaaS product that needs to be able to change and apply themes on the fly. It sounds like we're getting there, unfortunate that it will be after 0.10.0.

I want to color a list item like this, will this WIP help me?

<md-list>
  <md-list-item
    class="md-1-line"
    ng-repeat="a in b"
    ng-class="{'md-primary': a._id == getGlobalSelectedId()}"
  >
    <span>{{a.name}}</span>
  </md-list-item
</md-list>

@plato: Well, if you replace md-primary with a hue or color out of the
palette it will!
md-primary does not mean anything on its own. (as a class name)

2015-05-26 17:31 GMT+02:00 plato [email protected]:

I want to color a list item like this, will this WIP help me?


class="md-1-line"
ng-repeat="a in b"
ng-class="{'md-primary': a._id == getGlobalSelectedId()}"

<span>{{a.name}}</span>

—
Reply to this email directly or view it on GitHub
https://github.com/angular/material/issues/1269#issuecomment-105568775.

@SanderElias Thanks for the comment. I was going by the demo for md-button on the theming documentation. I'm not sure what the correct "hue or color" class is, I tried md-color-bg-100 and md-color-fg-100 but the spans are still black and my inspector doesn't show any rules being applied.

  1. Does your solution work on current release?
  2. Are there existing classes I can use to style spans, if so can you give an example?

edit: Plunkr operational but I still havent managed to color the spans http://plnkr.co/edit/sv5Vh257HXKOjnFgYC89?p=preview

@plato-cambrian I don't see the colors.js script in your Plunker. I messed with this for a bit to try to get it working with 0.9.x, but didn't have any luck.

I've created a very simplistic shim that might help some people in the mean time, it's just got basic .md-fg and .md-bg that can be used like in the md-button. IE .md-primary.md-fg will apply the primary color to the foreground.

Here's the gist: https://gist.github.com/SimeonC/1f6b6e52c9b14c4c7b63

@SimeonC 's code not work for me ,
so i create a moudule

(function () {
    "use strict";
    angular
        .module('custiom.material', ['material.core'])
        .directive('cMdThemeFg', ["$mdTheming", function ($mdTheming) {
            return {
                restrict: 'A',
                link: postLink
            };
            function postLink(scope, element, attr) {
                $mdTheming(element);
                element.addClass('c-md-fg');
            }
        }])
        .directive('cMdThemeBg', ["$mdTheming", function ($mdTheming) {
            return {
                restrict: 'A',
                link: postLink
            };
            function postLink(scope, element, attr) {
                $mdTheming(element);
                element.addClass('c-md-bg');
            }
        }]);
})();

and append

.c-md-fg.md-THEME_NAME-theme.md-primary {    color: '{{primary-color}}'; }
.c-md-fg.md-THEME_NAME-theme.md-accent {    color: '{{accent-color}}'; } 
.c-md-fg.md-THEME_NAME-theme.md-warn {    color: '{{warn-color}}'; } 
.c-md-bg.md-THEME_NAME-theme.md-primary {    background-color: '{{primary-color}}'; } 
.c-md-bg.md-THEME_NAME-theme.md-accent {    background-color: '{{accent-color}}'; } 
.c-md-bg.md-THEME_NAME-theme.md-warn {    background-color: '{{warn-color}}'; }

into angular-material.js at 13783 line

angular.module("material.core").constant("......  HERE")

then i can simply apply c-md-theme-fg and/or c-md-theme-bg to element to apply theme colors
like

 <div c-md-theme-bg class="md-primary md-hue-3">dasdasdasd</div>
    <span c-md-theme-bg class="md-primary">test</span>

it work great,
but i don't really want to modify angular-material.js
anyone can help?

ps: sorry about english, come from Taiwan :)

I tried to overwrite the $MD_THEME_CSS constant of material.core module and just appending my rules. But no luck.

This works showing this rule with injected primary color. But ignores my theme colors.

var myrule = ".wu-fg.md-THEME_NAME-theme.md-primary {color: '{{primary-color}}'; }";
MyModule.constant('$MD_THEME_CSS', myrule);

This will result in the default theme used without my customization and without the added rule

var myrule = angular.injector(['ng', 'material.core']).get('$MD_THEME_CSS') + ".wu-fg.md-THEME_NAME-theme.md-primary {color: '{{primary-color}}'; }";
MyModule.constant('$MD_THEME_CSS', myrule);

At the moment I try to debug threw the material code but it takes lot of time.

When I copy the $MD_THEME_CSS string from angular-material.js into a file and add my rules it works

var myrule = require('./myfile-with-$MD_THEME_CSS');
MyModule.constant('$MD_THEME_CSS', myrule);

I fixed @SimeonC's code to get the theme colors working. Added code for border-color as well.
https://gist.github.com/senthilprabhut/dd2147ebabc89bf223e7

Decided to take a stab at it for some extra flexibility: https://gist.github.com/ThadeuLuz/b5978c412fe9eb8357b7
use it like...

<md-button md-style-color="{'background-color': 'hue-1'}">My Button</md-button>
<md-button md-style-color="{'background-color': '100'}">My Button</md-button>
<md-button md-style-color="{'background-color': 'warn.hue-3'}">My Button</md-button>
<md-button md-style-color="{'background-color': 'accent.400'}">My Button</md-button>
<md-button md-style-color="{'background-color': 'green.900'}">My Button</md-button>

...passing an object where keys will be css properties and values are strings as [palette].[hue]
Just don't do "green.hue-1" (mixing up color palette name and hue number). it will default to hue 500.
There's lots of room for improvement, like this and a better way to use $mdThemingProvider on a directive, but this will do the trick..

@TitForTat really nice approach. Very simple.

in addition to @TitForTat
in my use case i had a costume palette defined as the default theme
and that caused an exception, instead of using $mdColorPalette
I kept $mdThemingProvider._PALETTES which contains all the palettes including costume ones
,forked the gist and updated it
https://gist.github.com/dh94/517187e03fdde3c18103

usage stays the same as in @TitForTat post

Just use $mdColorPalette

I added it to my $rootScope for global use, but you can just reference it in the controllers you want.

.run(function ($rootScope, $mdColorPalette) {
    $rootScope.getMaterialColor = function (base, shade) {            
        var color = $mdColorPalette[base][shade].value;
        return 'rgb(' + color[0] + ',' + color[1] + ',' + color[2] + ')';
    };
});

You would call: getMaterialColor('blue',100)

It works on JS side and even on the angular HTML side.

You can also do something like

$scope.primaryColor = 'blue';

In your controller and then use:

getMaterialColor(primaryColor, 100)

On your HTML side.

@clshortfuse cool function, but i dont think it'll work with costume palettes because mdColorPalette is a constant that doesn't contain costume defined palettes

@ThadeuLuz 404 on the gist.. use gist from @dh94

@sovanna sorry about that. fixed.

@ThadeuLuz no worries ;) by the way, thank a lot for the gist, I use it in my module and it works perfectly ;)

This is unfortunately more work than we can address before 1.0. However we will continue the discussion.

The solution with $mdColorPalette works nicely!;) Hope to see it improved in the 1st beta.

I thought i would share my version of handling this here https://gist.github.com/BoLaMN/5d3543dc522b35f631de

generates inline styles for each theme and contrasting color as well to handle the background vs text color

how to use

<!-- Red Background, White Text -->
<md-button class="md-warn-default background">My Button</md-button>
<!-- Red Background With hue-2, White Text -->
<md-button class="md-warn-hue-2 background">My Button</md-button>
<!-- Pink Text -->
<md-button class="md-accent-default text">My Button</md-button>
<!-- Pink Background, White Text -->
<md-button class="md-accent-default background">My Button</md-button>

<!-- md-style type object -->
<md-button md-style="{'background-color': 'hue-1'}">My Button</md-button>
<md-button md-style="{'background-color': '100'}">My Button</md-button>
<md-button md-style="{'background-color': 'warn.hue-3'}">My Button</md-button>
<md-button md-style="{'background-color': 'accent.400'}">My Button</md-button>
<md-button md-style="{'background-color': 'green.900'}">My Button</md-button>

Yet another take, based on BoLaMN's & others examples. This only adds new classes: .text and .background corresponding to every intention, hue and theme combo, and including the appropriate contrast color when using .background.

Any news when or if this is going to be natively available?

Is $mdColor service coming to Angular Material?

+1

+1

+1

+1

+1

+1

+1

but palettes including custom are actually available at .config
$mdThemingProvider._PALETTES;
have a look http://codepen.io/beyondev/pen/dMvNZr i am just using a global variable, may be someone can improve the codepen?

+1

+1

+1

+1

+1

+1

+1

+1

@homerjam you can have this feature in 1.1.0-rc3

Thanks - just had to refresh the docs! 😊

The mdColors directive is listed in the documentation, but the $mdColors service isn't.

8036 :)

+1

@Rahul-Giri this is already in, check here

Was this page helpful?
0 / 5 - 0 ratings