Cuando utilizo SASS, ¿cómo puedo importar un archivo desde un directorio diferente?

93

En SASS, ¿es posible importar un archivo desde otro directorio? Por ejemplo, si tuviera una estructura como esta:

- root_directory
    - sub_directory_a
        - _common.scss
        - template.scss
    - sub_directory_b
        - more_styles.scss

template.scss podría importar _common.scss usando, @import "common"pero ¿es posible que more_styles.scss importe _common.scss? Probé algunas cosas diferentes, incluidas @import "../sub_directory_a/common"y @import "../sub_directory_a/_common.scss"pero nada parece funcionar.

spaaarky21
fuente

Respuestas:

69

Parece que algunos cambios en SASS han hecho posible lo que inicialmente intentó hacer:

@import "../subdir/common";

Incluso hicimos que esto funcionara para una carpeta totalmente no relacionada ubicada en c:\projects\sass:

@import "../../../../../../../../../../projects/sass/common";

Solo agregue lo suficiente ../para asegurarse de que terminará en la raíz de la unidad y estará listo para comenzar.

Por supuesto, esta solución está lejos de ser bonita, pero no pude obtener una importación de una carpeta totalmente diferente para que funcione, ni usar I c:\projects\sassni configurar la variable de entorno SASS_PATH(de :: referencia de load_paths ) en ese mismo valor.

Oliver
fuente
9
¡Está "lejos de ser bonito"! Pero esta respuesta está recibiendo muchos votos a favor. ¿Se considera esto realmente una práctica mejor que -I? Si ese nombre de ruta cambia, habrá muchas búsquedas y reemplazos; y requiere la misma estructura de carpetas locales de cualquiera que comparta el .scss
WiseOldDuck
14
"Solo agregue lo suficiente ../ para asegurarse de que terminará en la raíz de la unidad y estará listo para comenzar". Jajaja que me alegró el día.
Steve Harrison
4
Aconsejo ignorar esta respuesta por completo. Desafortunadamente, es una de las muchas preguntas SO, que se responden incorrectamente con votos a favor. Si desea que su código se rompa fácilmente, utilícelo. Si desea una solución sólida, consulte mi respuesta a continuación.
adi518
2
@ adi518: Podría discutir sobre su declaración "Si desea que su código se rompa fácilmente, úselo". La solución dada ha estado funcionando para nosotros desde entonces (casi 4 años ahora) y no ha roto nada. Siento que esta es una de esas soluciones que pueden ser algo sucias, pero hacen el trabajo rápidamente y sin profundizar demasiado en los aspectos internos de algunas de las herramientas involucradas.
Oliver
2
En serio, no hagas esto.
shinzou
34

Puede usar el -Iinterruptor de línea de comando o la :load_pathsopción del código Ruby para agregarlo sub_directory_aa la ruta de carga de Sass. Entonces, si está ejecutando Sass desde root_directory, haga algo como esto:

sass -I sub_directory_a --watch sub_directory_b:sub_directory_b

Entonces simplemente puede usar @import "common"en more_styles.scss.

Miikka
fuente
1
Excelente. Eso es exactamente lo que quería saber. Y creo que MisterJack también está en algo, pero parece que Compass solo tiene una carpeta que ya está en el camino.
spaaarky21
3
-I Banderas de cadena para incluir más de un directorio, por ejemplosass -I sub_directory_a -I sub_directory_c --watch sub_directory_b:sub_directory_b
bob esponja
20

Usando webpack con sass-loader puedo usar ~para referirme a la ruta raíz del proyecto. Por ejemplo, asumiendo la estructura de carpetas de OP y que está en un archivo dentro de sub_directory_b:

@import "~sub_directory_a/_common";

Documentación: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules

Sammi
fuente
8
Esto parece importar desde node_modules/y no desde la raíz del proyecto.
Splaktar
Tuve que agregar "sub_directory_a"a mi includePathsy usar la @import "common";sintaxis cuando usaba Angular CLI, que incluye sass-loader.
Splaktar
Esta debería ser la respuesta aprobada.
shinzou
4
De acuerdo con Splaktar. De sass-loader docs: webpack proporciona un mecanismo avanzado para resolver archivos. Sass-loader utiliza la función de importación personalizada de Sass para pasar todas las consultas al motor de resolución del paquete web. Por lo tanto, puede importar sus módulos Sass desde node_modules. Simplemente anteponga ~ para decirle al paquete web que esta no es una importación relativa ... Es importante anteponerlo solo con ~, porque ~ / se resuelve en el directorio de inicio.
Anthony
Tenga en cuenta que ~/no parece referirse al directorio de inicio para mí. O cualquier directorio que haya intentado probar. ¿Hay alguna forma de intentar averiguar a dónde se refiere esto?
Douglas Gaskell
8

Importar un .scssarchivo que tiene una importación anidada con una posición relativa diferente no funcionará. La respuesta principal propuesta (usando mucho ../) es solo un truco sucio que funcionará siempre que agregue lo suficiente ../para llegar a la raíz del sistema operativo de implementación de su proyecto.

  1. Agregue la ruta de destino SCSS como destino de búsqueda para el compilador SCSS. Esto se puede lograr agregando la carpeta de hojas de estilo en el archivo de configuración scss, esta es una función del marco que está utilizando,

usar :load_pathsen config.rdpara marcos basados en brújula (por ejemplo, rieles)

use el siguiente código en scss-config.jsonparafourseven/meteor-scss

{
  "includePaths": [
    "{}/node_modules/ionicons/dist/scss/"
  ]
}
  1. Utilice rutas absolutas (frente a rutas relativas).

Ejemplo, con fourseven/meteor-scss, puede utilizar {}para resaltar el nivel superior de su proyecto según el siguiente ejemplo

@import "{}/node_modules/module-name/stylesheet";
helcode
fuente
Nada específico de meteor, fue solo un ejemplo.
helcode
4

La respuesta seleccionada no ofrece una solución viable.

La práctica de OP parece irregular. Un archivo compartido / común normalmente se encuentra debajo de partialsun directorio repetitivo estándar. Luego debe agregar un partialsdirectorio a sus rutas de importación de configuración para resolver parciales en cualquier lugar de su código.

Cuando encontré este problema por primera vez, pensé que SASS probablemente le brinda una variable global similar a la de Node __dirname, que mantiene una ruta absoluta al directorio de trabajo actual ( cwd). Desafortunadamente, no es así y la razón es porque la interpolación en una @importdirectiva no es posible, por lo tanto, no puede hacer una ruta de importación dinámica.

Según los documentos de SASS .

Necesita establecer :load_pathssu configuración de Sass. Dado que OP usa Compass, lo seguiré de acuerdo con la documentación aquí .

Puede optar por la solución CLI según lo previsto, pero ¿por qué? es mucho más conveniente agregarlo config.rb. Tendría sentido usar CLI para anular config.rb(por ejemplo, diferentes escenarios de compilación).

Entonces, asumiendo que config.rbestá bajo la raíz del proyecto, simplemente agregue la siguiente línea: add_import_path 'sub_directory_a'

Y ahora @import 'common';funcionará bien en cualquier lugar.

Si bien esto responde a OP, hay más.

Apéndice

Es probable que se encuentre con casos en los que desee importar un archivo CSS de forma incrustada, es decir, no a través de la @importdirectiva básica que CSS proporciona de fábrica, sino una combinación real del contenido de un archivo CSS con su SASS. Hay otra pregunta , que no se responde de manera concluyente (la solución no funciona en varios entornos). Entonces, la solución es utilizar esta extensión SASS.

Una vez instalado, agregue la siguiente línea a su configuración: require 'sass-css-importer'y luego, en algún lugar de su código:@import 'CSS:myCssFile';

Tenga en cuenta que la extensión debe omitirse para que esto funcione.

Sin embargo, nos encontraremos con el mismo problema al intentar importar un archivo CSS desde una ruta no predeterminada y add_import_pathno respeta los archivos CSS. Entonces, para resolver eso, debe agregar otra línea en su configuración, que es naturalmente similar:

add_import_path Sass::CssImporter::Importer.new('sub_directory_a')

Ahora todo funcionará bien.

PD: noté que la sass-css-importerdocumentación indica CSS:que se requiere un prefijo además de omitir la .cssextensión. Descubrí que funciona independientemente. Alguien inició un problema , que hasta ahora no ha recibido respuesta.

adi518
fuente
2

Gulp hará el trabajo para ver sus archivos sass y también agregar rutas de otros archivos con includePaths. ejemplo:

gulp.task('sass', function() {
  return gulp.src('scss/app.scss')
    .pipe($.sass({
      includePaths: sassPaths
    })
    .pipe(gulp.dest('css'));
});
oshry levy
fuente
7
Entiende que includePaths solo usa la -Iopción de la línea de comando, ¿verdad?
cimmanon
2

node-sass(el contenedor oficial de SASS para node.js) proporciona una opción de línea de comandos --include-pathpara ayudar con dichos requisitos.

Ejemplo:

En package.json:

"scripts": {
    "build-css": "node-sass src/ -o src/ --include-path src/",
}

Ahora, si tiene un archivo src/styles/common.scssen su proyecto, puede importarlo en @import 'styles/common';cualquier lugar de su proyecto.

Consulte https://github.com/sass/node-sass#usage-1 para obtener más detalles.

Vijay Aggarwal
fuente
1

Para definir el archivo a importar, es posible utilizar todas las definiciones comunes de carpetas. Solo debe tener en cuenta que es relativo al archivo que lo está definiendo. Puede consultar más sobre la opción de importación con ejemplos aquí .

Nesha Zoric
fuente
1

Si usa Web Compiler en Visual Studio, puede agregar la ruta includePathen compilerconfig.json.defaults. Entonces no hay necesidad de algunos, ../ya que el compilador usará includePath como ubicación para buscar la importación.

Por ejemplo:

"includePath": "node_modules/foundation-sites/scss",
DavGarcia
fuente
0

Esta es una respuesta a medias.

Eche un vistazo a Compass , con él puede colocarlo _common.scssdentro de una partialscarpeta y luego importarlo @import common, pero funciona en todos los archivos.

Alessandro Vendruscolo
fuente
Creo que la respuesta de Miikka fue realmente lo que estaba buscando, pero ahora también siento curiosidad por Compass. ¿El directorio de parciales es de alguna manera específico para un proyecto en particular? ¿O los archivos colocados en el directorio de parciales estarán disponibles "globalmente", dondequiera que se use Compass?
spaaarky21
4
Esto no responde la pregunta en absoluto.
cimmanon
0

Tuve el mismo problema. De mi solución llegué a esto. Así que aquí está tu código:

- root_directory
    - sub_directory_a
        - _common.scss
        - template.scss
    - sub_directory_b
        - more_styles.scss

Por lo que sé, si desea importar un scss a otro, debe ser parcial. Al importar de directorio diferente nombre su more_styles.scssa _more_styles.scss. Luego impórtelo a su template.scss@import ../sub_directory_b/_more_styles.scss. Funcionó para mí. Pero como mencionaste ../sub_directory_a/_common.scssno funciona. Ese es el mismo directorio del template.scss. Por eso no funcionará.

Sajidur Rahman
fuente
0

La mejor manera es utilizar sass-loader. Está disponible como paquete npm. Resuelve todos los problemas relacionados con la ruta y lo hace muy fácil.

Rut Shah
fuente
-6

Tenía el mismo problema y encontré una solución agregando una ruta al archivo como:

@importar "C: / xampp / htdocs / Scss_addons / Bootstrap / bootstrap";

@importar "C: / xampp / htdocs / Scss_addons / Compass / compass";

Netix
fuente
1
Si bien se ha dado una respuesta similar anteriormente, la ruta absoluta es un poco específica del servidor como respuesta general (usted dijo "me gusta", por supuesto).
dakab