246

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?

Asef Hossini
  • 655
  • 8
  • 11
corroded
  • 21,406
  • 19
  • 83
  • 132
  • 7
    Not the answer but useful: [SASS](http://sass-lang.com/documentation/file.SASS_REFERENCE.html#import) can import multiple files in one import, like `@import 'partials/header', 'partials/viewport', 'partials/footer';`. – llobet May 16 '17 at 09:31

13 Answers13

227

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.

Dennis Best
  • 3,614
  • 3
  • 20
  • 31
  • 8
    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. – Magne Sep 26 '13 at 14:19
  • 1
    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 https://github.com/chriseppstein/sass-globbing/issues/3 – pilavdzice Sep 17 '14 at 21:12
  • 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. – Dennis Best Oct 09 '14 at 18:03
  • 1
    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) – Peter Ehrlich Jan 14 '15 at 04:16
  • @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.) – Dennis Best Jan 14 '15 at 20:57
  • 5
    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. – Topher Hunt Feb 07 '15 at 14:01
  • Is it then possible to exclude a certain sub-sub-section? i.e. like in gulpfiles `!src/**/thatOneOddFileFromPackae.css` – Frank N Mar 17 '17 at 09:02
105

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:

Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166
Brandon Mathis
  • 1,536
  • 1
  • 10
  • 6
  • 291
    for well structured css files, order of inclusion should not matter – Milovan Zogovic Feb 01 '12 at 13:29
  • 66
    @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. – Brandon Mathis Feb 19 '12 at 19:58
  • 39
    @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. – Robin Winslow Jan 04 '13 at 09:30
  • 6
    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/"`. – srcspider Jul 29 '13 at 09:22
  • I name my files like `_00_base.scss`, `_01_mixins.scss` anyways, so importing the whole dir would save time for me. – Dmitri Pisarev Jul 10 '14 at 06:45
  • 5
    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... – Will Hancock Aug 22 '14 at 10:31
  • 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. – BJ McDuck Sep 04 '14 at 17:20
  • css resets will always need to be first. How does that needing to be first mean it's not well-structured css? – ahnbizcad Nov 03 '14 at 05:05
  • 2
    -​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](https://github.com/chriseppstein/sass-globbing). – Mark Amery Dec 01 '14 at 16:38
  • -1 because the import order is not always relevant. @ahnbizcad you could just include the reset/normalize before the automatic imports. – gyo Apr 17 '15 at 16:54
  • @ahnbizcad It would be nice to get feedback on why the downvote. Believe it or not, CSS load order is NOT always relevant. – gyo Aug 21 '15 at 09:41
  • 3
    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](http://thesassway.com/intermediate/understanding-placeholder-selectors) If you're writing CSS without the cascade, I would never want to work with you. – Jason Sep 14 '16 at 16:43
  • ^ and note that @MarkAmery's link is a gem, not part of Sass – henry Oct 05 '16 at 18:11
  • 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. – spnkr Dec 30 '18 at 09:36
42

Check out the sass-globbing project.

Drew Dara-Abrams
  • 8,016
  • 11
  • 40
  • 48
Akshay Rawat
  • 4,714
  • 5
  • 40
  • 65
  • 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 WIndows – Stuart May 12 '16 at 11:57
37

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".

fen
  • 1,109
  • 9
  • 25
  • 2
    That's a pretty good solution. It's what compass does to simplify their inclusion +1 – Jethro Larson Apr 10 '13 at 20:20
  • 8
    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. – gyo Apr 20 '15 at 09:42
  • 1
    Downvoters+Upvoters: can you please explain how this answer is different from the OP setup? – gyo Sep 19 '15 at 12:51
  • 4
    That's solving nothing. – oligofren Jun 01 '16 at 14:55
  • @fen where is this documented? That's actually what I'd need :) – Jaffa Mar 09 '17 at 17:14
  • 2
    @gyo 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`. – ttotherat Jun 14 '18 at 16:36
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

Thinker
  • 14,234
  • 9
  • 40
  • 55
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.

IGRACH
  • 3,506
  • 6
  • 33
  • 48
4

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

@import
  'foo',
  'bar';

I prefer this.

Emile Bergeron
  • 17,074
  • 5
  • 83
  • 129
dewwwald
  • 287
  • 4
  • 14
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';
Sens4
  • 605
  • 1
  • 11
  • 29
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.

xaxxon
  • 19,189
  • 5
  • 50
  • 80
  • yeah saw the documentation, just checked if anyone knew a trick or hoping it was just undocumented lol. Thanks for the suggestion though – corroded Jan 24 '11 at 04:46
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.

BRN
  • 151
  • 1
  • 4
  • If you use an approach like RSCSS, then the specificity is equal, and each component only applies where it needs to with no conflicts. – RWDJ Aug 01 '19 at 19:58
  • 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. – BRN Jun 15 '21 at 17:06
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
]
-1

this worked fine for me

@import 'folder/*';
Siddhartha Mukherjee
  • 6,138
  • 3
  • 23
  • 11
  • 8
    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. – Morteza May 06 '14 at 15:31
-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.

Nesha Zoric
  • 6,218
  • 42
  • 34