简体   繁体   English

使用 CSS 变量创建角度材质主题

[英]Create angular material theme with CSS variables

I'm working on a project that requires to be themeable at runtime.我正在开发一个需要在运行时可以主题化的项目。 So I created a theme system that combines SCSS variable with CSS Variables.所以我创建了一个主题系统,将 SCSS 变量与 CSS 变量相结合。 This is how it looks.这是它的样子。

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


// Primary
$primary-100: hsl(var(--primary-color), 90%, 98%);
$primary-400: hsl(var(--primary-color), 90%, 65%);
$primary-main: hsl(var(--primary-color), 90%, 50%);
$primary-700: hsl(var(--primary-color), 90%, 30%);
$primary-900: hsl(var(--primary-color), 90%, 10%);

While this works amazingly with my custom components, I'm having a hard time making it work with the Material design theme system.虽然这对我的自定义组件非常有效,但我很难让它与 Material design 主题系统一起工作。

My thinking was that I will create the theme as explained in the Angular material docs, and instead of using static colors, I will use my SCSS variables.我的想法是我将按照 Angular 材料文档中的说明创建主题,而不是使用静态颜色,我将使用我的 SCSS 变量。 this is how my theme.scss file looks like.这就是我的 theme.scss 文件的样子。

@import '~@angular/material/theming';
@import 'var.scss';

@include mat-core();

$shop-primary: (
  50: $primary-100,
  100: $primary-100,
  200: $primary-200,
  300: $primary-300,
  400: $primary-400,
 // ..... all other colors
  contrast: (
    50: $black-87-opacity,
    100: $black-87-opacity,
    200: $black-87-opacity,
     // ..... all other colors
  )
);


$shop-app-primary: mat-palette($shop-primary);
$shop-app-accent:  mat-palette($shop-primary);
$shop-app-warn: mat-palette($shop-primary);


$shop-app-theme: mat-light-theme($shop-app-primary, $shop-app-accent, $shop-app-warn);

@include angular-material-theme($shop-app-theme);

And I'm getting an error:我收到一个错误:

 Argument `$color` of `rgba($color, $alpha)` must be a color

Presumingly because the Angular Material mixin is expecting a color and not a hsl() value.推测是因为 Angular Material mixin 需要color而不是hsl()值。

So my question is how would I be able to create a custom material theme with runtime CSS variables?所以我的问题是如何使用运行时 CSS 变量创建自定义材质主题?

I created a little library to make this a little easier.我创建了一个小库,使这更容易一些。

You can use it like so:你可以像这样使用它:

  1. Install:安装:

     npm i angular-material-css-vars -S
  2. Then remove any existing @import '~@angular/material/theming';然后删除任何现有的@import '~@angular/material/theming'; from your main stylesheet file.从您的主样式表文件。

  3. Add this to your main stylesheet instead:将此添加到您的主样式表中:

     @import '~angular-material-css-vars/main'; @include initMaterialCssVars();
  4. Change the main theme color like so:像这样更改主题颜色:

     import {MaterialCssVarsService} from 'angular-material-css-vars'; export class SomeComponentOrService { constructor(public materialCssVarsService: MaterialCssVarsService) { const hex = '#3f51b5'; this.materialCssVarsService.changePrimaryColor(hex); } }

If you upgrade to @angular/material 7.3.4 CSS Variables will mostly work.如果您升级到 @angular/material 7.3.4 CSS 变量将主要工作。 Only riples and other stuff that uses opacity will need a little fix.只有涟漪和其他使用不透明度的东西需要一些修复。 I use rgba() for my project, but it should also work for hsla()我的项目使用 rgba(),但它也适用于 hsla()

Include this:包括这个:

@function mat-color($palette, $hue: default, $opacity: null) {
    @if type-of($hue) == number and $hue >= 0 and $hue <= 1 {
        @return mat-color($palette, default, $hue);
    }

    $color: map-get($palette, $hue);

    @if (type-of($color) != color) {
        @if ($opacity == null){
            @return $color;
        }

        // Here is the change from the original function:
        // If the $color resolved to something different from a color, we assume it is a CSS variable
        // in the form of rgba(var(--rgba-css-var),a) and replace the 'a' value.
        @return #{str-slice($color, 0, str-index($color, ',')) + $opacity + ')'};
    }

    @return rgba($color, if($opacity == null, opacity($color), $opacity));
}

directly after:直接在:

@import '~@angular/material/theming';

and define your colors like this:并像这样定义你的颜色:

--primary-color-50-parts: 0,158,224;
// ... all other colors

$color-primary: (
    50: rgba(var(--primary-color-50-parts), 1),
    // ... all other colors
);

if you define your colors in the map like this:如果您像这样在地图中定义颜色:

50: hsla(var(--primary-color), 90%, 98%, 1);

then you need to change str-index($color, ',') in the sass function to something that finds the last ',' in the string.那么您需要将 sass 函数中的 str-index($color, ',') 更改为找到字符串中最后一个 ',' 的内容。 Unfortunatelly my sass knowledge covers only the bare minimum and I don't know how to do that :/不幸的是,我的 sass 知识只涵盖了最低限度,我不知道该怎么做:/

I created a little library - material-theme-creator我创建了一个小库 - material-theme-creator

You can theming your angular-application or use this approach to create themes您可以为 angular 应用程序设置主题或使用这种方法来创建主题

NPM: https://www.npmjs.com/package/material-theme-creator NPM: https : //www.npmjs.com/package/material-theme-creator

DOCS: https://artik-man.github.io/material-theme-creator/文档: https : //artik-man.github.io/material-theme-creator/

npm i material-theme-creator

@import "~material-theme-creator/ngx-mtc";
@import '~@angular/material/theming';

@include mat-core();
@include ngx-mtc-init();

$primary-map: ngx-mtc-create-theme-map('primary');
$accent-map: ngx-mtc-create-theme-map('accent');
$warn-map: ngx-mtc-create-theme-map('warn');

:root {
  --is-dark-theme: 1; // Is dark theme? 1 or 0;
  @include ngx-mtc-theme-base(); // Creates base colors

  // Creates theme colors
  @include ngx-mtc-create-variables-from-color('primary', #009688, 38%);
  @include ngx-mtc-create-variables-from-color('accent', #2196f3, 57%);
  @include ngx-mtc-create-variables-from-color('warn', #f44336, 62%);
}

// Creates Angular Material Theme
@include angular-material-theme(
  ngx-mtc-custom-theme(
    mat-palette($primary-map),
    mat-palette($accent-map),
    mat-palette($warn-map)
  )
);
 

The second theme code:第二个主题代码:

.second-theme {
  --is-dark-theme: 0;
  @include ngx-mtc-update-theme('primary', #142148, 45%);
  @include ngx-mtc-update-theme('accent', #658e14, 50%);
  @include ngx-mtc-update-theme('warn', #750101, 50%);
}

You can use it with Angular Material or SCSS or pure CSS您可以将它与 Angular Material 或 SCSS 或纯 CSS 一起使用

Sooo... css variables are runtime, not compile time. Sooo... css 变量是运行时,而不是编译时。 SASS doesn't know what to do with them. SASS 不知道如何处理它们。 You should be able to refactor your css vars using the ${} interpolation of SCSS and have everything still work the same.您应该能够使用 SCSS 的 ${} 插值来重构您的 css 变量,并使一切仍然正常工作。 http://sass-lang.com/documentation/file.SASS_REFERENCE.html#interpolation_ http://sass-lang.com/documentation/file.SASS_REFERENCE.html#interpolation_

$primary-color: 196;

:root {
  --primary-color: #{$primary-color};
}

$primary-100: hsl($primary-color, 90%, 98%);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM