Is it possible to import a whole directory in sass using @import?
Asked Answered
D

13

247

I'm modularizing my stylesheets with SASS partials like so:

@import partials/header
@import partials/viewport
@import partials/footer
@import partials/forms
@import partials/list_container
@import partials/info_container
@import partials/notifications
@import partials/queues

Is there any way to include the whole partials directory(it's a directory full of SASS-partials) like @import compass or something?

Declinature answered 24/1, 2011 at 4:25 Comment(1)
Not the answer but useful: SASS can import multiple files in one import, like @import 'partials/header', 'partials/viewport', 'partials/footer';.Overfill
F
228

If you are using Sass in a Rails project, the sass-rails gem, https://github.com/rails/sass-rails, features glob importing.

@import "foo/*"     // import all the files in the foo folder
@import "bar/**/*"  // import all the files in the bar tree

To answer the concern in another answer "If you import a directory, how can you determine import order? There's no way that doesn't introduce some new level of complexity."

Some would argue that organizing your files into directories can REDUCE complexity.

My organization's project is a rather complex app. There are 119 Sass files in 17 directories. These correspond roughly to our views and are mainly used for adjustments, with the heavy lifting being handled by our custom framework. To me, a few lines of imported directories is a tad less complex than 119 lines of imported filenames.

To address load order, we place files that need to load first – mixins, variables, etc. — in an early-loading directory. Otherwise, load order is and should be irrelevant... if we are doing things properly.

Faught answered 15/5, 2013 at 21:35 Comment(7)
or add @import "*" (in application.css.scss) if your controller css/scss files are in the "app/assets/stylesheets" folder together with application.css.scss.Denominative
this "gem" is buggy and does not work on windows, see this issue which has been open for a long time and essentially means it is completely broken github.com/chriseppstein/sass-globbing/issues/3Tyratyrannical
You're talking about Chris Eppstein's sass-globbing gem. My answer uses the sass-rails gem, which is different I think. I'm not on Windows, but I don't see any issues related to the sass-rails gem.Faught
This didn't work for me - The globbing were broken down in to individual vanilla css @import lines of individual files. Which nastily, worked in dev, but not production (as there's only the one root asset path of application.css in production)Dropsical
@PeterEhrlich Not sure exactly what's happening in your case, but, to take a wild stab, I'd suggest making sure your "application.scss" only has "@imports" and not "requires" or "includes" (can't remember what comes in a stock rails application.scss but that won't work.)Faught
Worked great for me, thanks for this tip. I'm pleasantly surprised that saying @import "*" in application.scss includes all other files present in the same directory but doesn't re-include application.scss... I expected to get an infinite looping bug.Grappa
Is it then possible to exclude a certain sub-sub-section? i.e. like in gulpfiles !src/**/thatOneOddFileFromPackae.cssCentesimal
E
107

This feature will never be part of Sass. One major reason is import order. In CSS, the files imported last can override the styles stated before. If you import a directory, how can you determine import order? There's no way that doesn't introduce some new level of complexity. By keeping a list of imports (as you did in your example), you're being explicit with import order. This is essential if you want to be able to confidently override styles that are defined in another file or write mixins in one file and use them in another.

For a more thorough discussion, view this closed feature request here:

Eastereasterday answered 24/1, 2011 at 6:56 Comment(14)
for well structured css files, order of inclusion should not matterUnbridled
@MilovanZogovic Relying heavily on overrides has a code smell, but there's nothing improper about using the cascade. It's how the language was designed.Eastereasterday
@BrandonMathis I understand the theoretical purity here, but in an implementation (mine and I assume corroded's) you may choose to write your CSS in such a way that the different files have no impact on each other. I have a directory called "modules" with files that each contain a different css class rule. I want all files in that directory to be included, and their order is not, and by design will never be, important. It's a pain having to update the list every time I add a new one.Blastocyst
If I have a directory that's filled with non-applicable css, %rules, functions etc there is no risk involved and the opposite (not allowing) just leads to useless tedium and long "import headers" in files instead of what could just be a single line of @import "/functions" or @import "partials/".Inherent
I name my files like _00_base.scss, _01_mixins.scss anyways, so importing the whole dir would save time for me.Jandel
One usecase is importing modules, where order isn't important and styles may be namespaced... I would like to see this function - though agree it would have to be used wisely...Hindustan
Ya, if you're following smacss and using separate modules for styling you could have a huge folder of files that could be imported regardless of priority.Martimartial
css resets will always need to be first. How does that needing to be first mean it's not well-structured css?Debi
-​1 for being false. Firstly, the reasoning is faulty because in many cases (e.g. importing mixin or function libraries; importing page-specific scoped stylesheets) the order truly does not matter. Sometimes it matters, but that doesn't mean you can't give the user the power they want and warn them that it's dangerous if abused. Secondly, the feature now exists.Darin
-1 because the import order is not always relevant. @Debi you could just include the reset/normalize before the automatic imports.Helsell
@Debi It would be nice to get feedback on why the downvote. Believe it or not, CSS load order is NOT always relevant.Helsell
These comments are hilarious. Order (the cascade) is an integral basis of CSS. If it appears to be irrelevant, that means you aren't currently using the cascading aspect. However, the cascade should never be ignored or assumed it won't come into play in your project. Your next _middle-of-the-folder.scss could always potentially throw off the cascade, especially if you use--or begin to use--helpful Sass features like placeholders If you're writing CSS without the cascade, I would never want to work with you.Zlatoust
^ and note that @MarkAmery's link is a gem, not part of SassWhiteeye
the amount of time you save having an auto-import of a directory is probably like 1h of your time for a giant, giant project. it means you don't have to type out a list of css files. it means you don't have to write tests (UI or otherwise) checking that you're including what you need. n.b. i like meta-programming. a lot. i like automation. i like to keep it DRY... but auto importing css/scss is not a good idea.Gerlac
H
42

Check out the sass-globbing project.

Hildegardhildegarde answered 7/4, 2012 at 6:20 Comment(1)
my comment is out of date by a few years, but.... the sass-globbing project has some seriously slow progress, and only a single developer that isn't overly fussed about making things work on Windows. We are just starting make a new one that works across Linux, Mac, and WIndowsTruax
M
36

I create a file named __partials__.scss in the same directory of partials

|- __partials__.scss
|- /partials
   |- __header__.scss
   |- __viewport__.scss
   |- ....

In __partials__.scss, I wrote these:

@import "partials/header";
@import "partials/viewport";
@import "partials/footer";
@import "partials/forms";
....

So, when I want import the whole partials, just write @import "partials". If I want import any of them, I can also write @import "partials/header".

Monition answered 18/10, 2012 at 1:53 Comment(7)
That's a pretty good solution. It's what compass does to simplify their inclusion +1Mishmash
This is basically the same as the OP setup. He would like to import the files without manually adding the @import 'partials/xyz' statements each time a new partial is created.Helsell
Downvoters+Upvoters: can you please explain how this answer is different from the OP setup?Helsell
That's solving nothing.Flection
@Monition where is this documented? That's actually what I'd need :)Defaulter
@Helsell It doesn't help the OP if they only have one directory of partials, but it does help people with multiple directories of partials. If I have forms and widgets directories, I can @import "forms"; @import "widgets" in the main CSS file for a page, and only worry about all the individual partials (@import forms/text; @import forms/button...) inside forms.scss and widgets.scss.Vermiculite
More importantly, that does not answer the question which is a specific technical question about SASS’ features, not one about fairly obvious workarounds.Indiscriminate
L
10

It might be an old question, but still relevant in 2020, so I might post some update. Since Octobers'19 update we generally should use @use instead of @import, but that's only a remark. Solution to this question is use index files to simplify including whole folders. Example below.

// foundation/_code.scss
code {
  padding: .25em;
  line-height: 0;
}

// foundation/_lists.scss
ul, ol {
  text-align: left;

  & & {
    padding: {
      bottom: 0;
      left: 0;
    }
  }
}

// foundation/_index.scss
@use 'code';
@use 'lists';

// style.scss
@use 'foundation';

https://sass-lang.com/documentation/at-rules/use#index-files

Lineberry answered 20/1, 2020 at 22:9 Comment(3)
I think you want to use @forward in your _index.scss instead of @useMinnick
Much better/recommended approach IMHO.Wardmote
But that still would require you to add a new file to the _index.scss every time you create one. Is there really no way of doin @import foobar/**/* with @use or ` @forward`?Querist
M
4

You could use a bit of workaround by placing a sass file in folder what you would like to import and import all files in that file like this:

file path:main/current/_current.scss

@import "placeholders"; @import "colors";

and in next dir level file you just use import for file what imported all files from that dir:

file path:main/main.scss

@import "EricMeyerResetCSSv20"; @import "clearfix"; @import "current";

That way you have same number of files, like you are importing the whole dir. Beware of order, file that comes last will override the matching stiles.

Metzgar answered 26/5, 2014 at 18:33 Comment(0)
V
4

You might want to retain source order then you can just use this.

@import
  'foo',
  'bar';

I prefer this.

Vilipend answered 21/10, 2016 at 16:23 Comment(0)
A
3

http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import

doesn't look like it.

If any of these files always require the others, then have them import the other files and only import the top-level ones. If they're all standalone, then I think you're going to have to keep doing it like you are now.

Amatory answered 24/1, 2011 at 4:40 Comment(1)
yeah saw the documentation, just checked if anyone knew a trick or hoping it was just undocumented lol. Thanks for the suggestion thoughDeclinature
L
3

I also search for an answer to your question. Correspond to the answers the correct import all function does not exist.

Thats why I have written a python script which you need to place into the root of your scss folder like so:

- scss
  |- scss-crawler.py
  |- abstract
  |- base
  |- components
  |- layout
  |- themes
  |- vender

It will then walk through the tree and find all scss files. Once executed, it will create a scss file called main.scss

#python3
import os

valid_file_endings = ["scss"]

with open("main.scss", "w") as scssFile:
    for dirpath, dirs, files in os.walk("."):
        # ignore the current path where the script is placed
        if not dirpath == ".":
            # change the dir seperator
            dirpath = dirpath.replace("\\", "/")

            currentDir = dirpath.split("/")[-1]
            # filter out the valid ending scss
            commentPrinted = False
            for file in files:
                # if there is a file with more dots just focus on the last part
                fileEnding = file.split(".")[-1]
                if fileEnding in valid_file_endings:
                    if not commentPrinted:
                        print("/* {0} */".format(currentDir), file = scssFile)
                        commentPrinted = True
                    print("@import '{0}/{1}';".format(dirpath, file.split(".")[0][1:]), file = scssFile)

an example of an output file:

/* abstract */
@import './abstract/colors';
/* base */
@import './base/base';
/* components */
@import './components/audioPlayer';
@import './components/cardLayouter';
@import './components/content';
@import './components/logo';
@import './components/navbar';
@import './components/songCard';
@import './components/whoami';
/* layout */
@import './layout/body';
@import './layout/header';
Livvi answered 19/10, 2016 at 17:9 Comment(0)
N
2

The accepted answer by Dennis Best states that "Otherwise, load order is and should be irrelevant... if we are doing things properly." This is simply incorrect. If you are doing things properly, you make use of the css order to help you reduce specificity and keeping you css simple and clean.

What I do to organize imports is adding an _all.scss file in a directory, where I import all the relevant files in it, in the correct order. This way, my main import file will be simple and clean, like this:

// Import all scss in the project

// Utilities, mixins and placeholders
@import 'utils/_all';

// Styles
@import 'components/_all';
@import 'modules/_all';
@import 'templates/_all';

You could do this for sub-directories as well, if you need, but I don't think the structure of your css files should be too deep.

Though I use this approach, I still think a glob import should exist in sass, for situations where order does not matter, like a directory of mixins or even animations.

Nurmi answered 30/4, 2018 at 7:51 Comment(2)
If you use an approach like RSCSS, then the specificity is equal, and each component only applies where it needs to with no conflicts.Spoke
The approach to the specificity problem should be addressed in various ways. Order is one, simplicity of selectors is another. I think BEM is superior in this than RSCSS, because it uses simple selectors (like .block__module) instead of more complex ones (like .block > module). Check this one out. But there are always some situations that will require more complex selectors. Another good tool to avoid specificity problems are custom properties, that you can change for a specific context. This is also a good thing to check out.Nurmi
L
1

You can generate SASS file which imports everything automatically, I use this Gulp task:

concatFilenames = require('gulp-concat-filenames')

let concatFilenamesOptions = {
    root: './',
    prepend: "@import '",
    append: "'"
}
gulp.task('sass-import', () => {
    gulp.src(path_src_sass)
        .pipe(concatFilenames('app.sass', concatFilenamesOptions))
        .pipe(gulp.dest('./build'))
})

You can also control importing order by ordering the folders like this:

path_src_sass = [
    './style/**/*.sass', // mixins, variables - import first
    './components/**/*.sass', // singule components
    './pages/**/*.sass' // higher-level templates that could override components settings if necessary
]
Leatherleaf answered 11/4, 2019 at 11:10 Comment(0)
I
-1

this worked fine for me

@import 'folder/*';
Intractable answered 20/4, 2013 at 6:3 Comment(1)
I think this is because of ruby feature not SASS. Some compilers have problem with this way. For example i used this by gulp-ruby-sass and it worked but using gulp-sass it raised an error.Turtle
A
-4

With defining the file to import it's possible to use all folders common definitions.

So, @import "style/*" will compile all the files in the style folder.

More about import feature in Sass you can find here.

Adequate answered 8/3, 2018 at 10:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.