Создайте тему углового материала с переменными CSS

Я работаю над проектом, который требует наличия темы во время выполнения. Поэтому я создал систему тем, которая объединяет переменную SCSS с переменными CSS. Вот как это выглядит.

: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%);

Хотя это прекрасно работает с моими пользовательскими компонентами, мне трудно заставить его работать с системой тем дизайна материалов.

Я думал, что создам тему, как описано в документации по материалам Angular, и вместо статических цветов буду использовать переменные SCSS. вот как выглядит мой файл 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);

И я получаю сообщение об ошибке:

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

Предположительно потому, что миксин Angular Material ожидает значение color, а не значение hsl().

Итак, мой вопрос: как я могу создать пользовательскую тему материала с переменными CSS во время выполнения?

Я только что протестировал свой проект с помощью функции scss hsl(), и он работает правильно. Есть ли у вас свойство «stylePreprocessorOptions»: { «includePaths»: [ «src», «src/assets/scss»] } в вашем angular.json, чтобы ваш var.scss можно было получить глобально?

Budhead2004 08.02.2019 16:52

Вы уверены, что правильно используете mat-palette? я не могу найти пример, где передать ему массив

Dirk 08.02.2019 17:02

@Budhead2004 Budhead2004 Мой файл var.scss прекрасно включен. Я использую его повсеместно.

David Genger 08.02.2019 17:11

@ Budhead2004 Budhead2004 вы передали переменную CSS в функцию hsl?

David Genger 08.02.2019 17:12

Можете ли вы показать мне, какое содержимое $var вы передаете в функцию hsl()? @Dirk Он правильно использует функцию матовой палитры, именно так настроена моя пользовательская тема.

Budhead2004 08.02.2019 17:18

@Budhead2004 Да, это первый код, вырезанный на этой странице. Он находится в корневом каталоге `:root`

David Genger 08.02.2019 17:19

@Budhead2004 Budhead2004 Не могли бы вы показать мне свой фрагмент, который сработал?

David Genger 08.02.2019 17:20

Это не сработало с вашими входными данными, однако дальнейшее копание выявило проблему. github.com/sass/узел-sass/issues/2237 Хотя и говорится, что проблема решена...

Budhead2004 08.02.2019 17:28

@Budhead2004 Budhead2004 Эта проблема действительно решена, так как это не та ошибка, которая возникает у меня. Ошибка связана с дизайном материалов.

David Genger 10.02.2019 22:09
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
CSS: FlexBox
CSS: FlexBox
Ранее разработчики использовали макеты с помощью Position и Float. После появления flexbox сценарий полностью изменился.
12
9
6 673
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Оооо... переменные css - это время выполнения, а не время компиляции. SASS не знает, что с ними делать. Вы должны иметь возможность реорганизовать свои css-переменные, используя интерполяцию ${} SCSS, и все будет работать по-прежнему. 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%);

Мне не нужно, чтобы SCSS знал, что с ним делать, SCSS просто поместит его в назначенное значение, и браузер его интерпретирует. Во-вторых, причина, по которой я хочу этого, заключается в том, что я должен иметь возможность менять тему во время выполнения.

David Genger 10.02.2019 22:07

Если вы обновитесь до @angular/material 7.3.4, CSS-переменные в основном будут работать. Только рябь и другие вещи, использующие непрозрачность, нуждаются в небольшом исправлении. Я использую rgba() для своего проекта, но он также должен работать и для hsla().

Включите это:

@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));
}

сразу после:

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

и определите свои цвета следующим образом:

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

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

если вы определяете свои цвета на карте следующим образом:

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

затем вам нужно изменить str-index($color, ',') в функции sass на что-то, что находит последний ',' в строке. К сожалению, мои знания sass охватывают только самый минимум, и я не знаю, как это сделать :/

Вау! Звучит хорошо, у меня не было времени проверить это, но это кажется законным!

David Genger 25.03.2019 17:34

работает довольно хорошо вместе с @function colorToVariable($hexColor) { @return "#{red($hexColor)},#{green($hexColor)},#{blue($hexColor)}"; } и более поздними версиями --color-primary-lighter: #{colorToVariable(#ff0000)};, чтобы избежать ручного преобразования rgb

smnbbrv 01.07.2019 18:27
Ответ принят как подходящий

Я создал маленькая библиотека, чтобы сделать это немного проще.

Вы можете использовать его так:

  1. Установить:

    npm i angular-material-css-vars -S
    
  2. Затем удалите любой существующий @import '~@angular/material/theming'; из вашего основного файла таблицы стилей.

  3. Вместо этого добавьте это в свою основную таблицу стилей:

    @import '~angular-material-css-vars/main';
    @include initMaterialCssVars();
    
  4. Измените основной цвет темы следующим образом:

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

Привет, можем ли мы применить стили шрифтов с упомянутой вами библиотекой?

Nanda Kishore Allu 24.01.2021 15:17

Я создал небольшую библиотеку - material-theme-creator

Вы можете создать тему для своего углового приложения или использовать этот подход для создания тем.

НПМ: https://www.npmjs.com/package/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)
  )
);
 

Второй код темы:

.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%);
}

Вы можете использовать его с Angular Material, SCSS или чистым CSS.

Другие вопросы по теме