what is the LESS CSS statement #import-once good for? - css

Even after reading https://github.com/cloudhead/less.js/issues/212, I don't understand the meaning of the #import-once statement.

When you work with LESS you can have few less files (I have like 12 including media-queries, resets, etc), and sometimes you don't have the control of how many #import you have done between files, and that's the reason behind #import-once, to avoid style duplication.
When should I use #import-once instead #import?
Suppose you have main.less which imports other less files. And those files all import utils.less that contains useful mixins or variables. When you do this, the mixins get duplicated in the compiled code (css file). Once for each time utils.less was imported, even your CSS file should be 1mb instead 20kb. In case like this one you should use #import-once.
EDIT:
As pointed by #TJ, since LESS 1.4.0, #import-once is removed and is now default behavior for #import.

#import-once simply means "If it was already imported before, don't import it again". It's done to prevent duplication of CSS styles.

Related

Two stylesheets targeting the same element with equal specificity, which takes precedence?

I have two stylesheets built from the same .scss files that only differ in a few places. One is a master with all styles and the other is missing a few pieces here and there. These need to coexist, they each have a specific use case and are intended to be downloaded by the user. Because webpack won't bundle CSS on its own, I have to import both of these stylesheets which means they can potentially affect my site.
My index.js is along the lines of
import "./master.scss";
import "./specific-case.scss";
My webpack.config.js is along the lines of
module.exports = {
...
...
plugins: [
specificCaseExtraction,
masterExtraction,
...
I'd like the whole application to use master.scss styles, but there are a few places where spceific-case.scss is stepping in an messing up the styling, despite them using the same source (precedence is pretty well defined with the sheets themselves, but they don't play well together which only a problem in this demo application and will never be the case when used properly).
Basically, my question boils down to this: Is there a way to ensure that one stylesheet takes precedence over another? Is it a matter of ordering? I tried swapping them in index.js but it didn't help, and swapping them in webpack.config.js is a bit more complicated because the masterExtraction is called manually while the specificCaseExtraction is actually one of many that is injected dynamically. Or, better yet, is there a way to have webpack compile and package .scss into .css without having the inject it into the page itself?
UPDATE:
Turns out that in times of equal specificity, the style that's further down the sheet is the one that takes effect. That means that reversing the order of the plugins in the list made the master.css appear below the specific-case.css in the final index.html which means that the master styles always take precedence over any others and my problem is solved.
CSS specificity is in order of precedence.
This is the best article I have seen by far: https://css-tricks.com/specifics-on-css-specificity/
Here is a similar project using LESS instead of SASS but the concept is the same.
https://github.com/mabbashm110/Sprint-Challenge--Responsive-Less
Hope that helps.

#import more performant alternative for sass

I've discovered that #import has performance implications. However all of my sass files #import a global-constants.scss at the top of the file to reuse several variables for colour and other properties, so that I can change the main colour etc from one place.
Is there a more performant way to reuse variables in sass?
EDIT: upon pondering this further, I notice that my css file that is generated from my sass file after compilation, has no import statement, and all of the variables are rendered as proper css values. So I'm probably not going to get any performance issues anyway, is my guess.
When you are using #import inside the SCSS, it will try to include the whole file and send it to the browser, (it is better, if you have configured it to return only one single CSS file or minified). That way, it is clean and better:
No #import in the output.
Source code is split using #import, keeping the modularity.
Summary: No performance issues because of #import.

Combine multiple CSS Preprocessors

We have a hundreds of .less files in production, but would like to start incorporating .scss files as well.
Would I need to make my own file type in order to compile mutliple types of CSS preprocessor files or is there already a way to do something like this:
#import 'less-styles.less';
#import 'scss-styles.scss';
#import 'stylus-styles.styl'; //potentially
whereby it produces a single CSS file in that order.
Because of valid CSS code is also valid Less code, you could compile your SCSS and stylus files first to CSS and import that.
sass scss-styles.scss scss-styles.css
Than in your Less code:
#import (less) scss-styles.css
The less keyword above does:
less: treat the file as a Less file, no matter what the file extension
The above means that you can extend and mixin the CSS selectors from the scss-styles.css file in your Less code.
Notice that variables and mixins from the from the scss-styles.css file are not available for (re)use in Less.
If you need the variables and mixins too, the only solution seems to convert your SCSS to Less. See also: https://github.com/bassjobsen/grunt-scss2less
You should be able to do the same for your stylus (.styl) files.
So far I have not seen any tools that would allow developers to cross-reference LESS mixins from Sass, or versa-vice.
That doesn't mean that you can't use multiple preprocessors in the same site, it just means that you will be limited in how they can interact. With concatenation and minification tools you could certainly build LESS and Sass separately and then merge them into a single file that gets minified.
With all of that said, I highly discourage that approach. Pick a technology for the project, and stick with it. That way you can make the most of the tools at hand, and only have to worry about a single technology lifecycle (updates, API changes, etc).

Main SASS file to multiple CSS files

So I have this unusual situation, may be it's not Sassy way OR the right way and that's why I am asking it.
I have a main.scss which basically imports all other partials and frameworks say bootstrap. It works perfectly if all I needed was one single global CSS but I require different css files for various components and pages. One option could have been to include variables and mixins in every SASS file and compile different SASS files. Following are the reasons I didn't venture this path-
This somehow doesn't seem right, may be there is much efficient and automated way.
Not everything is coded by me or I may not have options to arrange variables and mixins locations. E.g. variables and mixins are not declared in separate files and I might not have option to re-factor.
One option which I am using is to split final compiled css using grunt and placing them in different folders but then changing images and font path is turning out to be a big trouble. I am not sure how do I use imgmin or such utilities to solve my problem neither that I am using the most efficient way to achieve what I want. I also want to avoid much complications in workflow.
Looking for some advice or tip which may help me out.
I'm not sure why you would say that compiling multiple SASS files doesn't seem right. That's how I'd approach it.
If you have a lot of variables and mixins, put the shared ones into a single file.
_shared.scsc:
$blue: #3b97c6;
$grey: #e6e6e6;
#mixin my_mixin {
// ...
}
Then just have your multiple SASS files (without the underscore so that they get compiled individually).
sass1.scss
#import "_shared";
// stuff only for sass-1
sass2.scss
#import "_shared";
// stuff only for sass-2
sass3.scss
#import "_shared";
// stuff only for sass-3
Am I misunderstanding something?

Importing & Extending raw CSS?

I have a preprocessor import problem. I have vendor css that i would like to copy functionality. Unfortunately, i don't control the html for this situation either.. so essentially i have vendor css & different vendor html, and i am trying to extend functionality of one css rule into another.
Now, the basic concept in many css preprocessors is to extend the rule.
// Vendor
.foo { font-weight: bold; }
.bar { text-color: red; }
// Mine
.bar { .foo }
In the above example, you don't have access to .foo or .bar, but with preprocessors, you can extend functionality from .foo into .bar, which works great for less/stylus/etc. The problem, is when the vendor rules are only defined in raw css.
So with that said, the most obvious solution is to have Stylus/Less import the raw css as stylus/less. However, neither seem to be able to actually do this.. that i've found at least. Less doesn't seem able to (#import "foo.css" directives are ignored) and while Stylus has an option to actually include the imported raw CSS, it did not seem to actually be processing it. That is to say, it would include the css, but #extend directives failed (perhaps i am wrong?).
The other option i could think of is simply renaming the .css files to the preprocessor language extension. Since we want to keep the vendor stuff out of our hands, allowing for proper versioning/etc, This involves a build process which copies the target css files and renames them into the target language extension, but this is error prone. Stylus ran into syntax errors immediately, and Less could just as easily (as not all CSS is valid Less. most is, but not all).
So.. any additional thoughts on this front? Hopefully there is an option i may be missing? Perhaps SCSS handles this better?
Currently, with what i have found is/isn't possible.. i feel the only stable way is to simply copy the raw css bits into my css code. If the vendor code changes, i'll have to update manually, but at least i don't run the risk of vendor stuff changing and all of a sudden the build process fails, because vendor introduced some CSS syntax not supported by less/etc. It is far from good.. but the worst that can happen is my css looks funny, and i need to update.
edit:
I'm going to try SCSS next.. we'll see how it goes. On the site, they claim all CSS(3 only?) syntax is valid SCSS
edit2: For clarity. My question is, give the above scenario, what would you do? Importing the .css files is not possible (See note below!), and renaming .css files to .less/.stylus can in turn be error prone, since less is not a perfect superset of CSS(namely due to proprietary features).
!Note!: I have since been digging around the less source to see what could be done to fix this problem, rather than work around it, and ran into a dozen support tickets on the matter. The main discussion of which seems to be taking place on #issue 1185, and more importantly, check out the changelog which *(i believe) addresses this issue! CHANGELOG 1.4.0 Beta
So with that said, the #import (less) "file.css" is likely the winning scenario here, even if it may have a few bugs due to the beta status. Yay :)
Your best bet is either what #Lee Olayvar said, or use the new ":extend()" feature in LESS. It sounds like you might have tried the extend feature, but you used the "SASS directive" syntax (which IMO is improper use of an at-rule), whereas LESS uses the CSS-like pseudo-selector syntax:
.foo:extend(.bar) {}
And if you are patient (in the coming days/weeks), you will see a new feature that is perfect for what you want to do, and it's unique to LESS. It will allow you to extend or mixin external "silent" styles. Meaning you will be able to "#import" and external stylesheet but the styles won't show up in your compiled code unless you extend them or use them as a mixin.
I'm on the core team for Less.js btw, so let me know if you have any other questions or if I can be of further help.
It looks like all imported .css files won't be prepocessed by less but will just be added with an #import at the top.
You can import both CSS and LESS files. Only LESS files import statements are processed, CSS file import statements are kept as they are. If you want to import a CSS file, and don’t want LESS to process it, just use the .css extension
Source: http://lesscss.org/
The best thing you could do would be the renaming I believe.
While still in beta, the newly added #import (less) "file.css" syntax should properly handle all CSS files. Due to the "official" support, it can also be expected/assumed that any proprietary syntax that breaks LESS would be fixed (though possibly not "supported").
So in theory this is the best option! Barring SCSS, which i have not tried yet in this scenario. Stylus still has issues though, in my tests.
For more information, check out this issue or this changelog.

Resources