When using SASS how can I import a file from a different directory?
Asked Answered
H

14

106

In SASS, is it possible to import a file from another directory? For example, if I had a structure like this:

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

template.scss could import _common.scss using @import "common" but is it possible for more_styles.scss to import _common.scss? I tried a few different things including @import "../sub_directory_a/common" and @import "../sub_directory_a/_common.scss" but nothing seems to work.

Hyetal answered 28/6, 2011 at 6:12 Comment(1)
So people don't get too far and waste time, as @Oliver said below recent changes to SASS have made relative paths possible e.g. @import '../../css/functions'Fiscal
C
84

UPDATE: Please consider Mikka's answer first - it should work without flaw if you're only interested in including subdirectories. My answer is specific to including directories other than subdirectories, but works for those, too. But: It's not the idiomatic way to do it.


Looks like some changes to SASS have made possible what you've initially tried doing:

@import "../subdir/common";

We even got this to work for some totally unrelated folder located in c:\projects\sass:

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

Just add enough ../ to be sure you'll end up at the drive root and you're good to go.

Of course, this solution is far from pretty, but I couldn't get an import from a totally different folder to work, neither using I c:\projects\sass nor setting the environment variable SASS_PATH (from: :load_paths reference) to that same value.

Cottage answered 13/9, 2013 at 11:29 Comment(2)
It is "far from pretty"! But this answer is getting lots of upvotes. Is this really considered a better practice than -I? If that pathname changes there will be lots of searching and replacing; and it requires the same local folder structure of anyone sharing the .scssMariellamarielle
I advice ignoring this answer completely. Unfortunately it's one of many SO questions, which are answered incorrectly with up votes. If you want your code to break easily, use it. If you want a robust solution, see my answer below.Paxton
M
39

As per official docs, use the -I command line switch (abbreviated version of --load-path) or :load_paths option from Ruby code to add sub_directory_a to Sass's load path.

For example, if you're running Sass from root_directory, do something like this:

sass -I sub_directory_a --watch sub_directory_b:sub_directory_b

Then you can simply use @import "common" in more_styles.scss.

Note that it can be passed multiple times to provide multiple load paths e.g.

sass -I sub_directory_a -I sub_directory_b --watch sub_directory_b:sub_directory_b
Mccrory answered 2/7, 2011 at 7:53 Comment(1)
Chain -I flags to include more than one directory, e.g. sass -I sub_directory_a -I sub_directory_c --watch sub_directory_b:sub_directory_bNecrology
E
31

Using webpack with sass-loader I can use ~ to refer to the project root path. E.g assuming OPs folder structure and that you're in a file inside sub_directory_b:

@import "~sub_directory_a/_common";

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

2021 Edit: using ~ is now deprecated and the link above says:

Using ~ is deprecated and can be removed from your code (we recommend it), but we still support it for historical reasons. Why can you remove it? The loader will first try to resolve @import as a relative path. If it cannot be resolved, then the loader will try to resolve @import inside node_modules.

Excide answered 25/4, 2017 at 9:16 Comment(6)
This seems to import from node_modules/ and not from the root of the project.Nightwear
I had to add "sub_directory_a" to my includePaths and use the @import "common"; syntax when using the Angular CLI which includes sass-loader.Nightwear
Agree with Splaktar. From sass-loader docs: webpack provides an advanced mechanism to resolve files. The sass-loader uses Sass's custom importer feature to pass all queries to the webpack resolving engine. Thus you can import your Sass modules from node_modules. Just prepend them with a ~ to tell webpack that this is not a relative import... It's important to only prepend it with ~, because ~/ resolves to the home directory.Shing
Note that ~/ doesn't seem to refer to the home directory for me. Or any directory I have tried to test. Is there any way to actually try and figure out where this is referring to??Cauldron
In case you want to start from project root directory and not from node_modules, do ~/../<path_to_your_scss> instead of ~<path_to_your_scss>.Emylee
Warning: Using ~ is deprecated: github.com/webpack-contrib/…Laroy
D
10

Importing a .scss file that has a nested import with a different relative position won't work. the top proposed answer (using a lot of ../) is just a dirty hack that will work as long as you added enough ../ to reach the root of your project's deployment OS.

The proper way to do this is by following either of the following two options. I prefer the second one.

  1. Add the target SCSS path as a search target for the SCSS compiler: This can be achieved by adding the stylesheets folder into the SCSS config file, this is a function of the framework you are using,

use :load_paths at config.rd for compass-based frameworks (Ex. rails)

use the following code at scss-config.json for fourseven/meteor-scss

{
  "includePaths": [
    "{}/node_modules/ionicons/dist/scss/"
  ]
}
  1. [Recommended] Use absolute path reference (vs. relative paths).

Example, with fourseven/meteor-scss, you can use {} to highlight top-level of your project as per the following example

@import "{}/node_modules/module-name/stylesheet";
Default answered 5/1, 2018 at 6:24 Comment(0)
C
5

Gulp will do the job for watching your sass files and also adding paths of other file with includePaths. example:

gulp.task('sass', function() {
  return gulp.src('scss/app.scss')
    .pipe($.sass({
      includePaths: sassPaths
    })
    .pipe(gulp.dest('css'));
});
Conifer answered 15/3, 2016 at 21:53 Comment(0)
P
3

Selected answer does not offer a viable solution.

OP's practice seems irregular. A shared/common file normally lives under partials, a standard boilerplate directory. You should then add partials directory to your config import paths in order to resolve partials anywhere in your code.

When I encountered this issue for the first time, I figured SASS probably gives you a global variable similar to Node's __dirname, which keeps an absolute path to current working directory (cwd). Unfortunately, it does not and the reason why is because interpolation on an @import directive isn't possible, hence you cannot do a dynamic import path.

According to SASS docs.

You need to set :load_paths in your Sass config. Since OP uses Compass, I'll follow that with accordance to documentation here.

You can go with the CLI solution as purposed, but why? it's much more convenient to add it to config.rb. It'd make sense to use CLI for overriding config.rb (E.g., different build scenarios).

So, assuming your config.rb is under project root, simply add the following line: add_import_path 'sub_directory_a'

And now @import 'common'; will work just fine anywhere.

While this answers OP, there's more.

Appendix

You are likely to run into cases where you want to import a CSS file in an embedded manner, that is, not via the vanilla @import directive CSS provides out of the box, but an actual merge of a CSS file content with your SASS. There's another question, which is answered inconclusively (the solution does not work cross-environment). The solution then, is to use this SASS extension.

Once installed, add the following line to your config: require 'sass-css-importer' and then, somewhere in your code: @import 'CSS:myCssFile';

Notice the extension must be omitted for this to work.

However, we will run into the same issue when trying to import a CSS file from a non-default path and add_import_path does not respect CSS files. So to solve that, you need to add, yet another line in your config, which is naturally similar:

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

Now everything will work nicely.

P.S., I noticed sass-css-importer documentation indicates a CSS: prefix is required in addition to omitting the .css extension. I found out it works regardless. Someone started an issue, which remained unanswered thus far.

Paxton answered 29/4, 2017 at 19:48 Comment(0)
G
3

node-sass (the official SASS wrapper for node.js) provides a command line option --include-path to help with such requirements.

Example:

In package.json:

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

Now, if you have a file src/styles/common.scss in your project, you can import it with @import 'styles/common'; anywhere in your project.

Refer https://github.com/sass/node-sass#usage-1 for more details.

Gunshot answered 10/7, 2018 at 5:6 Comment(1)
just a word of warning as of 2022 node-sass is deprecated npmjs.com/package/node-sassRueful
R
1

To define the file to import it's possible to use all folders common definitions. You just have to be aware that it's relative to file you are defining it. More about import option with examples you can check here.

Racemic answered 8/3, 2018 at 10:49 Comment(0)
H
1

Look into using the includePaths parameter...

"The SASS compiler uses each path in loadPaths when resolving SASS @imports."

https://mcmap.net/q/205569/-what-does-gulp-39-s-includepaths-do

Hight answered 22/6, 2018 at 14:24 Comment(0)
L
1

If using Web Compiler in Visual Studio you can add the path to includePath in compilerconfig.json.defaults. Then there is no need for some number of ../ since the compiler will use includePath as a location to look for the import.

For example:

"includePath": "node_modules/foundation-sites/scss",
Laconism answered 9/7, 2019 at 22:4 Comment(0)
G
0

This is a half answer.

Check out Compass, with it you can place your _common.scss inside a partials folder, and then import it with @import common, but it works in every file.

Gnosticism answered 28/6, 2011 at 6:51 Comment(1)
I think Miikka's response was really what I was after but now I am curious about Compass too. Is the partials directory somehow specific to a particular project? Or would files put in the partials directory be available "globally," wherever Compass is used?Hyetal
M
0

I ran into the same problem. From my solution i came into this. So here is your code:

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

As far i know if you want to import one scss to another its has to be a partial. When you are importing from different directory name your more_styles.scss to _more_styles.scss. Then import it into your template.scss like this @import ../sub_directory_b/_more_styles.scss. It worked for me. But as you mentioned ../sub_directory_a/_common.scss not working. That's the same directory of the template.scss. That is why it wont work.

Millwater answered 28/11, 2016 at 21:2 Comment(0)
D
0

The best way is to user sass-loader. It is available as npm package. It resolves all path related issues and make it super easy.

Dieterich answered 23/8, 2019 at 6:11 Comment(0)
D
-7

I was have same problem and i found solution by adding path to file like:

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

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

Devitalize answered 20/8, 2015 at 18:37 Comment(1)
While a similar answer has been given earlier, absolute path are bit to specific to server as general answer (you did say “like”, of course).Cultivar

© 2022 - 2024 — McMap. All rights reserved.