stylesheets rails primary instalar color change bootstrap css variables twitter-bootstrap-3 sass override

css - rails - Bootstrap SASS variable anula desafío



instalar bootstrap sass (4)

EDITAR: Esta pregunta se marcó como un duplicado de esta , pero consulte el apéndice al final de esta respuesta para ver qué pregunta no hace y qué respuesta no responde.

Estoy trabajando en una aplicación web que usa Bootstrap 3. Tengo una arquitectura básica de anulación de 3 capas, donde 1) _variables.scss de Bootstrap contiene las variables principales, 2) _app-variables.scss contiene las variables de la aplicación base que anulan las de Bootstrap _variables.scss y 3) _client-variables.scss contiene personalizaciones específicas del cliente que anulan _app-variables.scss. Ya sea # 2 o # 3 (o ambos) pueden ser archivos en blanco. Así que aquí está el orden de anulación:

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

Lo suficientemente simple en teoría, pero surge un problema debido a lo que llamaré "dependencias de variables", donde las variables se definen como otras variables. Por ejemplo:

$brand: blue; $text: $brand;

Ahora, digamos que las variables anteriores están definidas en _variables.scss. Entonces, digamos en _app-variables.scss, solo anulo la variable $ brand para que sea roja: $brand: red . Como SASS interpreta el código línea por línea secuencialmente, primero establecerá $ brand en azul, luego establecerá $ text en azul (porque $ brand es azul en ese punto), y finalmente establecerá $ brand en rojo. Por lo tanto, el resultado final es que cambiar $ brand después no afecta a ninguna variable basada en el valor anterior de $ 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.

Pero obviamente eso no es lo que quiero, quiero que mi cambio de $ $ afecte a todo lo que dependa de él. Para anular correctamente las variables, actualmente solo estoy haciendo una copia completa de _variables.scss en _app-variables.scss, y luego hago modificaciones dentro de _app-variables desde ese punto. Y de manera similar estoy haciendo una copia completa de _app-variables.scss en _client-variables.scss y luego haciendo modificaciones dentro de _client-variables.scss en ese punto. Obviamente, esto es menos que ideal (subestimación) desde el punto de vista del mantenimiento: cada vez que hago una modificación a _variables.scss (en el caso de una actualización de Bootstrap) o _app-variables.scss, tengo que hacer un seguimiento manual de los cambios en el archivo anular la pila. Y además, tengo que redeclarar una tonelada de variables que ni siquiera estoy anulando.

Descubrí que LESS tiene lo que llaman "carga lenta" ( http://lesscss.org/features/#variables-feature-lazy-loading ), donde la última definición de variable se utiliza en todas partes, incluso antes de la última definición . Creo que esto resolvería mi problema. Pero, ¿alguien sabe una solución adecuada de anulación de variables utilizando SASS?

APÉNDICE:
Aquí hay una técnica que ya he pensado: incluir los archivos en orden inverso, utilizando !default para todas las variables (esta técnica también se sugirió en la respuesta a esta pregunta ). Entonces, así es como se desarrollaría esto:

_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)

Entonces esa solución es casi perfecta. Sin embargo , ahora en mis archivos de anulación, no tengo acceso a las variables definidas en _variables.scss de Bootstrap, que necesitaría si quisiera definir mis reemplazos de variables (o mis propias variables personalizadas adicionales) usando otras variables de Bootstrap. Por ejemplo, podría querer hacer: $custom-var: $grid-gutter-width / 2;


Resuelto, pero no sé de qué versión funciona esto. Creo que la solución podría haber estado siempre disponible. Probado en:

> sassc --version sassc: 3.2.1 libsass: 3.2.5 sass2scss: 1.0.3

Vamos a utilizar un entorno simplificado, por lo que los nombres de archivo no coinciden con los de Bootstrap.

Reto

Dado un marco que no controlamos (por ejemplo, instalado solo en el entorno de integración continua y no disponible en nuestras máquinas) que expresa las variables SCSS de la siguiente manera:

// bootstrap/_variables.scss $brand-primary: #f00 !default; $brand-warning: #f50 !default; $link-color: $brand-primary !default;

Y dado un archivo en ese mismo marco que usa las variables:

// boostrap/main.scss a:link, a:visited { color: $link-color; }

El desafío es:

Incluya el marco en el SCSS de su propia aplicación de tal forma que

  1. las dependencias de variables en el marco se preservan y honran;
  2. puede confiar en los valores predeterminados pero aún así poder cambiar los resultados en las dependencias de framework.

Más precisamente:

Incluya el marco en el SCSS de su aplicación de tal manera que $brand-color sea ​​siempre el inverso de $brand-warning , cualquiera sea su valor en el marco.

Solución

El archivo principal se vería así:

// application.scss @import "variables"; @import "bootstrap/variables"; @import "bootstrap/main";

Y su archivo de variables se vería así:

// _variables.scss %scope { @import "boostrap/variables"; $brand-primary: invert($brand-warning) !global; }

Resultados:

> sassc main.scss a { color: blue; }

Explicación

La parte %scope no es algo mágico de SCSS, es simplemente una clase oculta con el scope del nombre, disponible exclusivamente para extensiones posteriores con @extend . Lo estamos usando solo para crear un alcance variable (de ahí el nombre).

Dentro del alcance, @import las variables del marco. Debido a que en este momento no hay ningún valor para cada variable, cada variable se crea y se le asigna su valor !default .

Pero aquí está el truco. Las variables no son globales , sino locales . Podemos acceder a ellos, pero no van a contaminar el alcance global, el que más tarde se utilizará para derivar variables dentro del marco.

De hecho, cuando queremos definir nuestras variables, queremos que sean globales, y de hecho usamos la palabra clave !global para indicarle a SCSS que las almacene en el ámbito global.

Advertencias

Hay una advertencia importante: no puedes usar tus propias variables mientras las defines .

Eso significa que en este archivo

%scope { @import "boostrap/variables"; $brand-primary: black !global; @debug $brand-primary; }

La instrucción @debug imprimirá el valor predeterminado definido en boostrap / _variables.scss , no en black .

Solución

Dividir variables en dos partes:

%scope { @import "boostrap/variables"; $brand-primary: black !global; @debug $brand-primary; } @debug $brand-primary;

El segundo @debug imprimirá correctamente en black .


Con Bootstrap 4 o bootstrap-sass, todas las variables se establecen en _variables.scss con el indicador! Predeterminado.

Por lo tanto, si establece una variable antes de que se incluya _variables.scss de bootstrap, cuando se incluya, se ignorará el valor de _variables.scss.

Así que mi archivo de entrada sass podría verse así ...

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


En alpha 6 de Bootstrap 4, todas las variables en _variables.scss pueden anularse en _custom.scss, de la manera que describe mryarbles. Sin embargo, las anulaciones no se conectan en cascada a otros elementos, porque el orden de inclusión es:

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

Cuando cambio esto a

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

funciona como se esperaba


El archivo _custom.scss en la rama de desarrollo BS4 ha sido eliminado. Intente reordenar sus importaciones con este orden:

Preparar

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

Asegúrese de copiar el contenido del archivo variable de boostrap _variables.scss en app-variables client-variables . Deje el! Predeterminado junto a cada variable para permitir una mayor anulación.

Explicación

Todas las variables de arranque se declaran con !default . De la referencia de Sass:

Puede asignar variables si aún no están asignadas al agregar el indicador! Predeterminado al final del valor. Esto significa que si la variable ya se ha asignado, no se volverá a asignar, pero si aún no tiene un valor, se le asignará uno.

  • Bootstrap respetará todas las variables ya definidas en la parte superior haciendo que la app_variables con mayor prioridad y las client_variables con la más alta prioridad.
  • _variables copiar todas las declaraciones de variables de bootstrap _variables en app-variables client-variables para que pueda tener una variable personalizada como desee. (La desventaja es que es más difícil de mantener en cada actualización de arranque)
  • Todas las variables están ahora disponibles en tu app-mixins y client-mixins