Ao usar o SASS, como posso importar um arquivo de um diretório diferente?

89

No SASS, é possível importar um arquivo de outro diretório? Por exemplo, se eu tivesse uma estrutura como esta:

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

template.scss poderia importar _common.scss usando, @import "common"mas é possível para more_styles.scss importar _common.scss? Tentei algumas coisas diferentes, incluindo @import "../sub_directory_a/common"e, @import "../sub_directory_a/_common.scss"mas nada parece funcionar.

spaaarky21
fonte

Respostas:

69

Parece que algumas mudanças no SASS tornaram possível o que você tentou fazer inicialmente:

@import "../subdir/common";

Nós até fizemos isso funcionar para uma pasta totalmente não relacionada localizada em c:\projects\sass:

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

Basta adicionar o suficiente ../para ter certeza de que você acabará na raiz da unidade e estará pronto para prosseguir.

Claro, essa solução está longe de ser bonita, mas não consegui fazer uma importação de uma pasta totalmente diferente funcionar, nem usando I c:\projects\sassnem definindo a variável de ambiente SASS_PATH(de :: referência load_paths ) para o mesmo valor.

Oliver
fonte
9
Está "longe de ser bonito"! Mas essa resposta está recebendo muitos votos positivos. Isso é realmente considerado uma prática melhor do que -I? Se o nome do caminho mudar, haverá muitas pesquisas e substituições; e requer a mesma estrutura de pasta local de qualquer pessoa que compartilhe o .scss
WiseOldDuck
14
"Basta adicionar o suficiente ../ para ter certeza de que você acabará na raiz da unidade e estará pronto para prosseguir." Hahaha isso fez o meu dia.
Steve Harrison
4
Aconselho ignorar esta resposta completamente. Infelizmente, é uma das muitas perguntas do SO, que são respondidas incorretamente com votos positivos. Se você quiser que seu código seja corrompido facilmente, use-o. Se você quiser uma solução robusta, veja minha resposta abaixo.
adi518
2
@ adi518: Eu poderia argumentar sobre sua declaração "Se você deseja que seu código seja corrompido facilmente, use-o." A solução fornecida tem funcionado para nós desde então (quase 4 anos agora) e não quebrou nada. Eu sinto que esta é uma daquelas soluções que podem ser um tanto sujas, mas fazem o trabalho rapidamente e sem ir muito fundo nas partes internas de algumas das ferramentas envolvidas.
Oliver
2
Sério, não faça isso.
shinzou de
34

Você pode usar a opção de -Ilinha de comando ou :load_pathsopção do código Ruby para adicionarsub_directory_a ao caminho de carregamento do Sass. Então, se você está fugindo do Sass root_directory, faça algo assim:

sass -I sub_directory_a --watch sub_directory_b:sub_directory_b

Então você pode simplesmente usar @import "common"em more_styles.scss.

Miikka
fonte
1
Ótimo. Isso é exatamente o que eu queria saber. E eu acho que MisterJack também está no caminho certo, mas parece que o Compass só tem uma pasta que já está no caminho.
spaaarky21
3
-I Sinalizadores de cadeia para incluir mais de um diretório, por exemplosass -I sub_directory_a -I sub_directory_c --watch sub_directory_b:sub_directory_b
bob esponja
19

Usando o webpack com o sass-loader, posso usar ~para me referir ao caminho da raiz do projeto. Por exemplo, assumindo a estrutura da pasta OPs e que você está em um arquivo dentro de sub_directory_b:

@import "~sub_directory_a/_common";

Documentação: https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules

Sammi
fonte
8
Isso parece importar de node_modules/e não da raiz do projeto.
Splaktar
Eu tive que adicionar "sub_directory_a"ao meu includePathse usar a @import "common";sintaxe ao usar a CLI Angular, que inclui o sass-loader.
Splaktar
Esta deve ser a resposta aprovada.
shinzou de
3
Concordo com Splaktar. Do sass-loader docs: webpack fornece um mecanismo avançado para resolver arquivos. O sass-loader usa o recurso de importador personalizado do Sass para passar todas as consultas para o mecanismo de resolução do webpack. Assim, você pode importar seus módulos Sass de node_modules. Apenas prefixe-os com ~ para informar ao webpack que esta não é uma importação relativa ... É importante apenas acrescentar ~, porque ~ / resolve para o diretório inicial.
Anthony
Observe que ~/não parece se referir ao diretório inicial para mim. Ou qualquer diretório que tentei testar. Existe alguma maneira de realmente tentar descobrir a que isso se refere ??
Douglas Gaskell
8

Importar um .scssarquivo que possui uma importação aninhada com uma posição relativa diferente não funcionará. a principal resposta proposta (usando muito ../) é apenas um hack sujo que funcionará desde que você tenha adicionado o suficiente ../para alcançar a raiz do sistema operacional de implantação do seu projeto.

  1. Adicione o caminho SCSS de destino como um destino de pesquisa para o compilador SCSS. Isso pode ser conseguido adicionando a pasta de folhas de estilo ao arquivo de configuração scss, esta é uma função da estrutura que você está usando,

use :load_pathsem config.rdpara estruturas baseadas em bússola (ex. trilhos)

use o seguinte código em scss-config.jsonparafourseven/meteor-scss

{
  "includePaths": [
    "{}/node_modules/ionicons/dist/scss/"
  ]
}
  1. Use caminhos absolutos (vs. caminhos relativos).

Exemplo, com fourseven/meteor-scss, você pode usar {}para destacar o nível superior do seu projeto de acordo com o seguinte exemplo

@import "{}/node_modules/module-name/stylesheet";
código de ajuda
fonte
Nada específico para meteor, foi apenas um exemplo.
código de ajuda
4

A resposta selecionada não oferece uma solução viável.

A prática de OP parece irregular. Um arquivo compartilhado / comum normalmente reside em partialsum diretório clichê padrão. Você deve então adicionar o partialsdiretório aos seus caminhos de importação de configuração para resolver parciais em qualquer lugar do seu código.

Quando encontrei esse problema pela primeira vez, percebi que o SASS provavelmente fornece uma variável global semelhante à do Node __dirname, que mantém um caminho absoluto para o diretório de trabalho atual ( cwd). Infelizmente, isso não acontece e o motivo é porque a interpolação em um@import diretiva não é possível, portanto, você não pode fazer um caminho de importação dinâmico.

De acordo com os documentos SASS .

Você precisa definir :load_pathsem sua configuração Sass. Como o OP usa o Compass, seguirei de acordo com a documentação aqui .

Você pode escolher a solução CLI conforme o propósito, mas por quê? é muito mais conveniente adicioná-lo config.rb. Faria sentido usar CLI para substituirconfig.rb (por exemplo, diferentes cenários de construção).

Portanto, supondo que você config.rbesteja na raiz do projeto, basta adicionar a seguinte linha: add_import_path 'sub_directory_a'

E agora @import 'common';vai funcionar bem em qualquer lugar.

Embora isso responda a OP, há mais.

Apêndice

É provável que você encontre casos em que deseja importar um arquivo CSS de uma maneira incorporada, ou seja, não por meio da @importdiretiva básica que o CSS fornece fora da caixa, mas uma mesclagem real do conteúdo de um arquivo CSS com o seu SASS. Há outra pergunta , que foi respondida de forma inconclusiva (a solução não funciona em ambientes diferentes). A solução, então, é usar esta extensão SASS.

Depois de instalado, adicione a seguinte linha à sua configuração: require 'sass-css-importer'e, a seguir, em algum lugar do seu código:@import 'CSS:myCssFile';

Observe que a extensão deve ser omitida para que isso funcione.

No entanto, teremos o mesmo problema ao tentar importar um arquivo CSS de um caminho não padrão e add_import_pathnão respeitar os arquivos CSS. Então, para resolver isso, você precisa adicionar mais uma linha em sua configuração, que é naturalmente semelhante:

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

Agora tudo funcionará bem.

PS, notei que a sass-css-importerdocumentação indica que um CSS:prefixo é necessário, além de omitir a .cssextensão. Eu descobri que funciona de qualquer maneira. Alguém iniciou um problema , que permaneceu sem resposta até agora.

adi518
fonte
2

O Gulp fará o trabalho de observar seus arquivos sass e também adicionará caminhos de outros arquivos com includePaths. exemplo:

gulp.task('sass', function() {
  return gulp.src('scss/app.scss')
    .pipe($.sass({
      includePaths: sassPaths
    })
    .pipe(gulp.dest('css'));
});
Oshry Levy
fonte
7
Você entende que includePaths está apenas usando a -Iopção da linha de comando, certo?
cimmanon
2

node-sass(o wrapper oficial do SASS para node.js) fornece uma opção de linha de comando --include-pathpara ajudar com esses requisitos.

Exemplo:

Em package.json:

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

Agora, se você tem um arquivo src/styles/common.scssem seu projeto, pode importá-lo com@import 'styles/common'; qualquer lugar em seu projeto.

Consulte https://github.com/sass/node-sass#usage-1 para obter mais detalhes.

Vijay Aggarwal
fonte
1

Para definir o arquivo a importar é possível utilizar todas as definições comuns de pastas. Você apenas tem que estar ciente de que é relativo ao arquivo que você está definindo. Mais sobre a opção de importação com exemplos que você pode verificar aqui .

Nesha Zoric
fonte
1

Se estiver usando o Web Compiler no Visual Studio, você pode adicionar o caminho includePathem compilerconfig.json.defaults. Então, não há necessidade de algum número de../ pois o compilador usará includePath como local para procurar a importação.

Por exemplo:

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

Esta é uma meia resposta.

Confira o Compass , com ele você pode colocar seu arquivo _common.scssdentro de uma partialspasta, e depois importar com ele @import common, mas funciona em todos os arquivos.

Alessandro Vendruscolo
fonte
Acho que a resposta de Miikka foi realmente o que eu queria, mas agora também estou curioso sobre o Compass. O diretório partials é de alguma forma específico para um projeto particular? Ou os arquivos colocados no diretório partials estariam disponíveis "globalmente", onde quer que o Compass fosse usado?
spaaarky21
4
Isso não responde à pergunta de forma alguma.
cimmanon
0

Eu tive o mesmo problema. Da minha solução cheguei a isso. Então, aqui está o seu código:

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

Até onde eu sei se você quer importar um scss para outro tem que ser parcial. Quando estiver importando de um diretório diferente, nomeie seu more_styles.scsspara _more_styles.scss. Em seguida, importe-o para o seu template.scss@import ../sub_directory_b/_more_styles.scss. Funcionou para mim Mas como você mencionou ../sub_directory_a/_common.scssnão está funcionando. Esse é o mesmo diretório do template.scss. É por isso que não vai funcionar.

Sajidur Rahman
fonte
0

A melhor maneira é usar o sass-loader. Ele está disponível como pacote npm. Ele resolve todos os problemas relacionados ao caminho e o torna muito fácil.

Rut Shah
fonte
-6

Eu estava tendo o mesmo problema e encontrei a solução adicionando um caminho para o arquivo como:

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

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

Netix
fonte
1
Embora uma resposta semelhante tenha sido dada anteriormente, o caminho absoluto é bit a específico para o servidor como uma resposta geral (você disse “curtir”, é claro).
dakab de