Задача переопределения переменной Bootstrap Sass

EDIT: этот вопрос был отмечен как дубликат этот, но см. добавление в конце этого ответа, чтобы увидеть, что этот вопрос не задает, и что ответ не отвечает.

Я работаю над веб-приложением, которое использует Bootstrap 3. У меня есть базовая 3-слойная архитектура переопределения, где 1) _variables Bootstrap.scss содержит основные переменные, 2) _app-переменные.scss содержит базовые переменные приложения, которые переопределяют Bootstrap _переменные параметры.scss и 3) _client-переменные.scss содержит клиентские настройки, которые переопределяют _app-переменные.scss. Либо #2, либо #3 (или оба) могут быть пустыми файлами. Итак, вот порядок переопределения:

_variables.scss // Bootstrap's core
_app-variables.scss // App base
_client-variables.scss // Client-specific

достаточно просто в теории, но проблема возникает из-за того, что я назову "зависимости переменных" - где переменные определяются как другие переменные. Например:

$brand: blue;
$text: $brand;

теперь предположим, что вышеуказанные переменные определены в _variables.scss. Тогда давай скажем: _app-переменные.scss, я переопределяю только переменную $ brand, чтобы сделать ее красной:$brand: red. Поскольку SASS интерпретирует код строка за строкой последовательно, он сначала установит $brand на синий, затем он установит $text на синий (потому что $brand синий в этот момент), и, наконец, он установит $brand на красный. Таким образом, конечный результат заключается в том, что изменение $brand впоследствии не влияет на переменные, основанные на старом значении $brand:

_variables.scss
---------------------
$brand: blue;
$text: $brand; // $text = blue
.
.
.

_app-variables.scss
---------------------
$brand: red; // this does not affect $text, b/c $text was already set to blue above.

но, очевидно, это не то, что я хочу - я хочу свою смену $ бренд влияет на все, что от него зависит. Чтобы правильно переопределить переменные, я в настоящее время просто делаю полную копию _variables.scss в _app-переменные.scss, а затем внесение изменений в _app-переменные с этой точки. И точно так же я делаю полную копию _app-переменные.scss в _client-переменные.scss, а затем внесение изменений в _client-переменные.scss в этот момент. Очевидно, что это меньше, чем идеально (преуменьшение) с точки зрения обслуживания - каждый раз, когда я делаю модификацию _variables.scss(в случае обновления начальной загрузки) или _app-переменные.scss, я должен вручную просачивать изменения в стек переопределения файлов. И плюс мне нужно переопределить тонну переменных, которые я, возможно, даже не переопределяю.

я узнал, что меньше имеет то, что они называют "ленивой загрузкой" (http://lesscss.org/features/#variables-feature-lazy-loading), где последнее определение переменной используется везде, даже до последнее определение. Думаю, это решит мою проблему. Но кто-нибудь знает правильное решение для переопределения переменных с помощью SASS?

дополнение:
Вот один метод, который я уже продумал: включите файлы в обратном порядке, используя !default для всех переменных (этот метод также был предложен в ответ на этот вопрос). Итак, вот как это будет выглядеть:

_app-variables.scss
---------------------
$brand: red !default; // $brand is set to red here, overriding _variables.scss's blue.
.
.
.


_variables.scss
---------------------
$brand: blue !default; // brand already set in _app-variables.scss, so not overridden here.
$text: $brand !default; // $text = red (desired behavior)

так что решение почти идеальный. , теперь в моих файлах переопределения у меня нет доступа к переменным, определенным в _variables Bootstrap.scss, который мне понадобится, если я хочу определить переопределения переменных (или мои собственные дополнительные пользовательские переменные), используя другие переменные Bootstrap. Например, я мог бы сделать:$custom-var: $grid-gutter-width / 2;

4 ответов


решена, но я не знаю с какой версии это работает. Я!--21-->верить решение th могло быть всегда доступно. Проверено на:

> sassc --version

sassc: 3.2.1
libsass: 3.2.5
sass2scss: 1.0.3

мы будем использовать упрощенную среду, поэтому имена файлов не совпадают с Bootstrap.


вызов

учитывая структуру, которую мы не контролируем (например, установленную только в среде непрерывной интеграции и недоступную на наших машинах), которая выражает SCSS переменные следующим образом:

// bootstrap/_variables.scss

$brand-primary: #f00 !default;
$brand-warning: #f50 !default;

$link-color: $brand-primary !default;

и задан файл в той же структуре, которая использует переменные:

// boostrap/main.scss

a:link, a:visited {
  color: $link-color;
}

задача:

включите фреймворк в SCSS вашего собственного приложения таким образом, чтобы

    переменные’в рамках сохраняются и почести;
  1. вы можете зависеть от значений по умолчанию, но все равно сможете изменить результаты о зависимостях фреймворка.

более точно:

включите фреймворк в SCSS вашего приложения таким образом, чтобы $brand-color всегда будет обратным $brand-warning, независимо от его стоимости в рамках.

решение

основной файл будет выглядеть так:

// application.scss

@import "variables";
@import "bootstrap/variables";
@import "bootstrap/main";

и ваш файл переменных будет выглядеть это:

// _variables.scss

%scope {
  @import "boostrap/variables";

  $brand-primary: invert($brand-warning) !global;
}

результаты:

> sassc main.scss

a {
  color: blue; }

объяснение

на %scope часть не является чем-то волшебным SCSS, это просто скрытый класс с именем scope, доступно исключительно для более поздних расширений с @extend. Мы используем его только для создания области переменных (отсюда и название).

внутри области мы @import переменные среды. Потому что в этот момент нет значения для каждой переменной, каждая переменная создается и назначил его !default значение.

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

на самом деле, когда мы хотим определить наши переменные, мы хотим, чтобы они были глобальными, и действительно мы используем !global ключевое слово для сигнала SCSS для хранения их в глобальная область.


предостережения

есть одно важное предостережение:вы не можете использовать свои собственные переменные при определении их.

это означает, что в этом файле

%scope {
  @import "boostrap/variables";

  $brand-primary: black !global;

  @debug $brand-primary;
}

на @debug заявление для печати значение по умолчанию определена в boostrap/_variables.scss, а не black.

решение

разделить переменные на две части:

%scope {
  @import "boostrap/variables";

  $brand-primary: black !global;

  @debug $brand-primary;
}

@debug $brand-primary;

в второй @debug действительно правильно печатать black.


С Bootstrap 4 или bootstrap-sass все переменные, установленные в _variables.СКС с !флаг по умолчанию.

поэтому, если вы установили переменную перед _variables bootstrap.scss включен, когда он включен, значение из _variables.scss будет проигнорирован.

таким образом, мой файл записи sass может выглядеть так ...

@import "bootstrap-overrides"; @import "bootstrap/scss/bootstrap-flex"; @import "mixins/module";


в alpha 6 Bootstrap 4 все переменные в _variables.scss можно переопределить в _custom.scss, как описывает мриарблес. Однако переопределения не каскадируются с другими элементами, поскольку порядок включения:

@import "variables";
@import "mixins";
@import "custom";

когда я изменяю это на

@import "custom";
@import "variables";
@import "mixins";

он работает так, как ожидалось.


на _custom.scss файл в BS4 dev ветка была удалена. Попробуйте изменить порядок импорта в следующем порядке:

настройка

@import "client-variables";
@import "app-variables";
@import "boostrap";
@import "app-mixins";
@import "client-mixins";

обязательно скопируйте содержимое файла переменной boostrap _variables.scss to app-variables и client-variables. Оставь !default рядом с каждой переменной, чтобы разрешить дальнейшее переопределение.

объяснение

все переменные начальной загрузки объявляются с помощью !default. От Sass ссылка:

вы можете назначить переменные, если они еще не назначены, добавив !флаг по умолчанию до конца значения. Это означает,что если переменная уже назначена, она не будет повторно назначена, но если она еще не имеет значения, ей будет дано одно.

  • Bootstrap будет уважать все переменные, уже определенные сверху, делая app_variables С более высоким приоритетом и client_variables с высшим приоритет.
  • вам нужно скопировать все объявления переменных из bootstrap _variables на app-variables и client-variables так что вы можете иметь пользовательскую переменную, как вы хотели. (Недостатком является то, что его сложнее поддерживать при каждом обновлении начальной загрузки)
  • все переменные теперь доступны в свой app-mixins и client-mixins