Skip to content
This repository

Add 'force' directive to SCSS @import #193

Closed
sean-lynch opened this Issue October 07, 2011 · 41 comments
Sean Lynch

Currently, SCSS extends the standard CSS function (described here http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#import) giving it different behavior depending on whether a CSS file or SCSS file is provided.

@import "other.scss"; <-- pulls the other.scss into this scss file completely, outputting a single resulting file. This == awesome

@import "other.css" <-- left alone because this is standard css markup.

It would be extremely useful if there was a way to @force-import "other.css" and have the file merged into this scss file. A work around is to rename other.css > other.scss but that's not ideal, or practical when trying to merge in css from other projects or frameworks.

Josiah

+1 I agree, this can be vital in reducing the number of http requests

Radosław Bułat

Any chance to add this feature?
+1

Chris Eppstein
Collaborator

The legacy handling and deciding on syntax etc is the hard part. Implementation is actually quite easy.

Sean Lynch

I'm naively assuming there shouldn't be any legacy issues if we decide on a new keyword where the semantics of that keyword is always to include the contents of the file.

Proposal:

Add a new @include keyword which always merges the css/scss file indicated. Given the confusing semantics of @import, you could also deprecate (but not remove) the scss import for clarity.

Martin Klepsch

I'd also like to see that change. I don't see a real reason why someone would complain that @import in a .scss file also pulls regular .css files, since minimizing the amount of HTTP-requests is a general best-practice.

Why not just changing it, testing it and look how people react?

Chris Eppstein
Collaborator

@mklappstuhl There are valid uses of browser-based imports. For example, reducing http requests overall might be better achieved in some websites by relying on browser caching of shared stylesheets. Or maybe reducing bandwidth is more important to them than reducing latency. It's not for Sass to just decide to enforce a best practice -- that is the job of the developer.

I'd like to hear what is the use case where simply renaming the file to have the .scss extension is markedly more inconvenient to justify this work.

Sean Lynch

@chriseppstein There's a number of cases, but the primary one for me is including third party modules and libraries which have their own css. I would like to use sass to process my own scss files and then compile all css into a single download to the browser.

Chris Eppstein
Collaborator

@sean-lynch Certainly, but is there something about this that makes process renaming the file onerous?

Sean Lynch

@chriseppstein Requiring me to rename files in separate modules breaks the benefits modularity. I know it seems minor, but it's one of those code smells I actively try to avoid if at all possible.

For example, when ever we need to update a third-party package, I'd have to make sure to rename the css files it provides to .scss. It's a small step, but just another thing that can be forgotten when doing upgrades or missing from a README file when distributing source to others. It's the same reason modifying libraries directly is frowned upon rather than monkey-patching them separately as part of the project source you control.

Chris Eppstein
Collaborator

@sean-lynch Ok. I agree and that is the same rationale I've been using in my own thought experiments. I think the best we can do is introduce a deprecation in 3.2 and then make the change in 4.0 But we have to know where we're heading, and we don't yet have that solved :(

Sean Lynch

Completely understand that it's not a quick change. How do you feel about the @include or similar keyword proposal for 3.2?

Chris Eppstein
Collaborator
Manuel Strehl

A useful name would be @embed:

@import "compass"; // embedded Sass
@embed "jquery-ui"; // embedded CSS
@import "module.css"; // not embedded

I'd also vote to have @embed act like @import in the case of Sass files.

Jason Roelofs

+1 on the @embed idea. I just got bit hard on this one, where what I thought was embedding was actually writing out a raw @import to the resulting CSS.

Maxime Fabre

I'm not sure I'm very fond of having two syntaxes that mean different things and then that mean even different things according to what filetype you feed it. It's very confusing for newcomers.
To me the move to make — but that would be very difficult — would just be to separate the meaning of the two syntaxes completely.

@import would just do what it says, import. In case of a CSS file, it would act like a normal @import, not embedding the file. In case of a SASS file, it would just @import the variables and mixins but then again, not embed any CSS.
@embed would actually embed the content (css, mixins and variables) of both CSS and SASS files.

But that would require to make a big warning to all sass users on the changing behavior of @import, but I think it's required for what I judge was a bad decision from the start to use an existing CSS method and then give it another behavior for sass files. In my mind that was misguided.

Manuel Strehl

I could live with that, too, but then again, my Sass codebase is quite manageable at the moment.

The advantage would be to move Sass yet a bit closer to vanilla CSS, after introducing SCSS. For newbies this would be the best solution.

alicexyl

Is there a problem with having @embed behave just like @import for scss files, but embed the file if it's a css file? That doesn't require changing @import behavior, and the new functionality is more flexible.

Victor Costan
pwnall commented July 05, 2012

@chriseppstein, how about the following?

@import "file.css"; embeds the input. Given the current behavior with SCSS files, I think that's what everyone expects.

@import url(file.css); does not embed the input. I think the syntax makes it obvious that no embedding will happen here.

Chris Eppstein
Collaborator

I suggested that to @nex3 and he had a good reason why that wouldn't work, but I've forgotten what it was.

Victor Costan
pwnall commented July 05, 2012

@chriseppstein Then how about this

@import "file.css"; implements the current behavior, and issues a warning recommending one of the two forms below:

@import url(file.css); CSS @import directive

@import file(file.css); embed the file; I'm not too attached to the file keyword, inline sounds just as fine to me.

Victor Costan
pwnall commented July 05, 2012

@chriseppstein Sorry for being brief earlier, I was putting out the fire that issue caused.

Here is the rationale behind my request for warnings: generating @import url directives with relative paths is dangerous, because Chrome and Firefox resolve the URLs relative to the CSS file that contains them, whereas Internet Explorer <= 9 resolves the URLs relative to the site root. (no clue what IE 10 does). So I consider that silently generating @import url() directives is an unpleasant surprise, and I hope SASS will do better.

Victor Costan
pwnall commented July 06, 2012

For developers reading this page because they've run into this issue and need a quick solution -- I have prepared two patches that implement the @import inline(file.css) variation on my last proposal above.

Patch for sass 3.2 (master branch): #441

Patch for sass 3.1.x (stable branch): #442

Nathan Weizenbaum
Owner
nex3 commented July 13, 2012

It's likely that when we work out the new semantics for the replacement to @import, we'll allow it to treat CSS files the same way it treats SCSS files. However, as long as we're using the old @import keyword, I don't think it's worthwhile to add an exception to make this work when it's entirely possible to just rename the CSS files.

Nathan Weizenbaum nex3 closed this July 13, 2012
Victor Costan
pwnall commented July 13, 2012

@nex3 thank you for thinking of a solution for this problem.

I think the @import treatment of .css files made sense when sass could only parse the indented syntax (.sass files), but is currently a nasty surprise. Sass is a really well thought-out and refined language, so I believe most folks were / will be rather surprised by @import's special casing of files that end in ".css".

I felt backstabbed, because emitting an "@import url()" directive based on what's likely to be a filesystem path will result in code doesn't work across browsers, and I'm used to having sass work on my side, and helping me write good CSS. I really think that only "@import url(x)" should emit a url directive.

Last, the requirement to rename files adds friction when dealing with 3rd party code -- I think it's not unreasonable for developers to aim to minimize the modifications to such code. Renaming can add extra hassle when merging in-house changes with upstream changes, and makes it harder to track a file's origin by googling its name.

One of the big benefits of sass is that it lets me organize my css as I wish on the server, and still serve a single file to browsers. The special handling of .css files breaks this promise a bit.

In closing, thank you very much for taking a look at @import. I've come to rely heavily on sass, and it broke my heart when it screwed me over and caused to me break a site. I look forward to seeing this wrinkle go away.

Nathan Weizenbaum
Owner
nex3 commented July 13, 2012

I think the @import treatment of .css files made sense when sass could only parse the indented syntax (.sass files), but is currently a nasty surprise. Sass is a really well thought-out and refined language, so I believe most folks were / will be rather surprised by @import's special casing of files that end in ".css".

It's very important that SCSS be a superset of plain CSS. As such, we're locked in to treating plain-CSS @import directives the same way they're treated in plain CSS. It's unfortunate that we decided to re-use the name @import, which is something that's on our roadmap to fix, but we can't change the semantics as long as we have the same name.

I felt backstabbed, because emitting an "@import url()" directive based on what's likely to be a filesystem path will result in code doesn't work across browsers, and I'm used to having sass work on my side, and helping me write good CSS. I really think that only "@import url(x)" should emit a url directive.

I hadn't realized that IE treated url() imports in a non-standard manner. In that case, it's definitely worth preserving the format that the user used originally, or possibly just never emitting url() for CSS imports.

Last, the requirement to rename files adds friction when dealing with 3rd party code -- I think it's not unreasonable for developers to aim to minimize the modifications to such code. Renaming can add extra hassle when merging in-house changes with upstream changes, and makes it harder to track a file's origin by googling its name.

I understand that there is a non-zero amount of effort involved in renaming files, which is why importing plain CSS is a use case we have in mind for the next-generation import mechanism. But it's not something we can afford to change for the current-generation @import.

Nicolas Gallagher necolas referenced this issue in necolas/normalize.css May 12, 2013
Closed

Converted normalize.css to SASS #9

Henrik Cederblad

TL:DR. Don't bother reading. I'm not sure anymore if this is an optimal idea. Especially if a next-generation @import is in the works.

How about adding a new type of file, similar to partials but prefixed with __ two underscores, e.g. __vendor.scss

Such file would function exactly the same way as you'd expect a normal _partial.scss to do, except for having a different @import mechanism, namely, embedding the contents of referenced CSS @imports.

Say you have a __vendor.scss file with some normal Sass styles and a couple of at-rules referencing CSS files from third parties. Then you have a main.scss file where you @import "vendor";: In the resulting main.css output, all Sass styles from __vendor.scss gets embedded, as well as styles from the sheets that was referenced by __vendor.scss.

This way you eliminate any confusion for those who'd expect nothing but the standard workings of CSS (@import resulting in multiple requests). While those looking for improved maintainability and speed can embed things however they want, just adding one extra underscore in partials.

loostro

This simply sucks that for 2 years there is no working solution for that problem. Force'ing developers to use dirty workaround modifying third-party libraries is not a solution. Sass is supposed to be developers remedy for common problems... yet here somehow it fails to deliver :-1:

MiguelMuller

This function is essential and the lack of it requires developers to have extra work.

Darren Haken

I read in the 3.2 documentation this is implemented but it doesn't seem to work!!
Can anyone explain if this is actually working or not?

I'm using Bower to pull in third party libraries so manually changing .css files to .scss is error prone and full of risk that css may be missed. Manual processes always lead to issues due to human error.

Using package managers such as Bower is very popular with front end technologies now so I will not be the only one facing this problem.

TAKEN FROM DOCUMENTATION:

http://sass-lang.com/documentation/file.SASS_CHANGELOG.html#css__directives

CSS @import Directives

Sass is now more intelligent about when to compile @import directives to plain CSS. Any of the following conditions will cause a literal CSS @import:

Importing a path with a .css extension (e.g. @import "foo.css").
Importing a path with a media type (e.g. @import "foo" screen;).
Importing an HTTP path (e.g. @import "http://foo.com/style.css").
Importing any URL (e.g. @import url(foo)).
The former two conditions always worked, but the latter two are new.

SingleSeeker

@pwnall still have no method to fix this solution?

Kevin Mårtensson kevva referenced this issue in gruntjs/grunt-contrib-compass February 18, 2014
Closed

is there a way when import a css file then just compile it #140

Victor Costan

@singleseeker Sorry, to the best of my knowledge there's still no way to force Sass to include the contents of a .css file instead of generating an @import CSS directive. In #442, I volunteered to implement the syntax that the Sass maintainers come up with. I'm afraid there's nothing else I can do to push this forward.

Chris Eppstein
Collaborator

Huh, I guess I forgot to mention on this thread (I searched the issues and commented on several others). But I made a sass importer for importing css files without renaming them some time ago: https://github.com/chriseppstein/sass-css-importer

It's a work-around until we have a way of doing this from Sass itself.

jookyboi jookyboi referenced this issue in Yesware/jquery-handsontable February 25, 2014
Merged

Added build step for SASS file. #2

loostro

@chriseppstein does it work with compass watch? there are some open issues which suggest it does not...

Chris Eppstein
Collaborator

@loostro I made some changes in Sass 3.3 that will enable making this work.

loostro

@chriseppstein great! i'll be testing it soon then :)

@chriseppstein Where can we see those changes, and what the syntax is? It's of interest since 3.3 is in RC now :)

Eugeny mahnunchik referenced this issue in nodeca/mincer March 03, 2014
Closed

Trouble using @import with css files #133

Chris Eppstein
Collaborator

@rawtaz The changes are in 0a8289f.

In Sass 3.3 I rewrote the Sass watcher. My plan is to remove Compass's watcher and instead, just configure Sass's watcher. But even without that, the fact that importers can declare where their files are and what should be watched is sufficiently abstract to make any importer and watcher work together.

Aeden Jameson aedenj referenced this issue in gruntjs/grunt-contrib-uglify March 03, 2014
Closed

Trouble using @import with css files #166

Samuel Richardson

+1 to getting this in, it would be very very useful when working with bower.

Pandaiolo

+1

geri777

This would be a "must have" feature!

rkingon

+1. seriously. renaming files from css to scss is not an option when dealing with bower. The moment the next dev does bower install he/she will have all the css files!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.