app-relative paths in url() in dotless - asp.net

I have a bunch of .less files that contain image backgrounds:
.header {
background-image:url(~/images/some_image.png);
}
In debug mode, these .less files are served directly, but in release mode they're served as a part of a bundle. The path depths between the bundle URL and the individual file URLs are not always the same, so I can't just use relative URLs.
The default options for the dotless nuget package do not parse app-relative paths. Is there an option to make it do the right thing?

Edit: There is a potentially fatal flaw in this approach. The apppath.less file has to be in a certain location which isn't necessarily known, which creates a chicken-egg scenario. Still, it may be helpful to some extent.
One approach is to use an #import rule that declares a variable containing the app path like this:
#import "apppath.less"
If you can't use a .less extension, you should be able to use (less) to force .less interpretation.
#import (less) "apppath.ashx"
Instead of being a static file, apppath.less could simply use Response.Write to echo the application path, producing an output like this:
#app-path: "http://yourserver/app/path";
Then you'd use it like this:
.header {
background-image:url("#{app-path}/images/some_image.png");
}

Related

Why should you compile your less files?

I compiling my less files to one css file. But i saw on http://lesscss.org/ that you can include the less file instant on your webpage.
Client-side is the easiest way to get started and good for developing
with Less, but in production, when performance and reliability is
important, we recommend pre-compiling using node.js or one of the many
third party tools available.
To start off, link your .less stylesheets with the rel attribute set
to "stylesheet/less":
Next, download less.js and include it in a tag in
the element of your page:
What is the diffrents between compiling to css or just jusing the less file?
Compiling to CSS
Here compiling means to use a program to turn a .less file into a .css file.
For example, a less file:
.outerDiv {
.innerDiv {
color:green;
}
}
when you use a compiler on it that will generate a css file like:
.outerDiv .innerDiv {
color:green;
}
I use koala. It does not overwrite your file, it just generates a css file alongside it.
All you need to do is reference that css file in your head part, then upload to the server.
Advantages over less.js method
This is lighter (less data for the client to load) than sending over the less file (especially if you minify the css file, which koala will do for you too).
It also makes for faster loading without any "jump" for the user.
If instead you use the less.js method, then:
page loads and renders without your lovely .less styling
less.js then kicks in and restyles your page with you .less rules
If the user is on a slow connection they may see the old unstyled version for a second, then the page will suddenly reformat itself.

how to prevent a sass build of each page file when just changing a common scss file

I have a _common.scss file which I import to various page.scss files:
page.scss:
#import "common";
#page {
...
}
_common.scss:
#import "partials/all";
#import "components/all";
...
But the problem is, since all my pages import _common.scss, the way I have things structured, if I make any changes inside _common.scss (or any of the files it imports), sass has to rebuild all the page css files. But if I just make _common.scss its own file and call it with a <link> tag (<link href="common.css">), then the page.scss file has errors, because it is trying to use variables and mixins defined in _common.scss and its imports.
Is it possible to structure my project so that the page.scss files can use all the mixins and variables in _common, but so that sass doesn't have to rebuild each page.css file each time I make a change to the common file? i.e. - make it so that sass only builds the common file when a change is made in common, and only builds the page file when a change is made in page?
I would say it is not possible, since the aim is to have one css for each page at the end. This said it HAS to be rebuild if something is changed in common.

How to use less mixins in meteor with #import and not get multiple definitions

in my current meteor app I have split the less declarations in one file per Controller (iron-router). I have a common file - where I have defined some mixins - which is imported in each less file. My problem is that the classes are imported multiple times in each route.
The file structure is:
mixins.import.less (new names, reference http://docs.meteor.com/#less)
.grid-container {
// something
}
postList.less
#import (once) url('/client/views/mixins.import.less');
postDetail.less
#import (once) url('/client/views/mixins.import.less');
Then in the Chrome inspector I found duplicated everything I have written in mixins.import.less. Is it possible to avoid this double import?
Assuming you want the mixin code at least once in your compiled css (perhaps not, some just want them as mixins, not classes in the css code), then make sure you set it to bring in the "mixins.import.less" file all by itself. Then for all your dependent files using it, do this:
"postList.less", "postDetail.less", etc.
#import (reference) url('/client/views/mixins.import.less');
The (reference) option has been available since LESS 1.5, and will only bring in the code for reference purposes to be used in the LESS file, but will not itself output any css.
Meteor bundles css and js/html resources all together as a single css and a single js file in production.
In development, they are individually served, but still at the same time, during initial page load (first ever request to server)
For less files, a css file is created for each (during development). Since you are importing, what Meteor basically does is create each corresponding css file that each contain the import individually.
And when they are served to the client all together (take a look at the head section of the generated html), you end up with that many copies of the imported style declarations.
Therefore, due to this bundling behaviour of Meteor, you can just keep one copy of your less mixins in a less file, and not import at all, since they are going to be served to the client in CSS form anyway.
Also, it is possible to trick Meteor into bypassing as described in the unofficial meteor faq:
... you can change the extension of the less files to be imported from .less to .lessimport and then change your #import file.less to #import file.lessimport. This will prevent the less compiler from automatically trying to compile all your import files independently, yet still let you use them ...

Checking if a css loads an external file

I am building a tool to minify and compile CSS files on-demand. The files can be in different folders, and I need them to be called from their original folder if they are referring to an external file (image, other css, font maybe?).
I wonder which strings I should look for. I only see url( and #import, but am pretty sure I am missing some.
I can think of proprietary CSS: behavior which loads .htc (.js on some servers) for that browser. Also exists as -ms-behavior.
EDIT: oops, behavior will use url() too, not behavior() as I previously wrote... My mistake. Ex:
.ie67 * {
behavior: url('htc/boxsizing.htc');
}
I don't think that filter / -ms-filter can load an external resource; it'll rather apply to images and such (somebody correct me if I'm wrong).
In CSS2.1, external resources are URIs so except #import (that must appear before anything else), I think your list is complete.

Import regular CSS file in SCSS file?

Is there anyway to import a regular CSS file with Sass's #import command? While I'm not using all of the SCSS syntax from sass, I do still enjoy it's combining/compressing features, and would like to be able to use it without renaming all of my files to *.scss
After having the same issue, I got confused with all the answers here and the comments over the repository of sass in github.
I just want to point out that as December 2014, this issue has been resolved. It is now possible to import css files directly into your sass file. The following PR in github solves the issue.
The syntax is the same as now - #import "your/path/to/the/file", without an extension after the file name. This will import your file directly. If you append *.css at the end, it will translate into the css rule #import url(...).
In case you are using some of the "fancy" new module bundlers such as webpack, you will probably need to use use ~ in the beginning of the path. So, if you want to import the following path node_modules/bootstrap/src/core.scss you would write something like #import "~bootstrap/src/core".
NOTE:
It appears this isn't working for everybody. If your interpreter is based on libsass it should be working fine (checkout this). I've tested using #import on node-sass and it's working fine. Unfortunately this works and doesn't work on some ruby instances.
This was implemented and merged starting from version 3.2 (pull #754 merged on 2 Jan 2015 for libsass, issues originaly were defined here: sass#193 #556, libsass#318).
To cut the long story short, the syntax in next:
to import (include) the raw CSS-file the syntax is **without `.css`** extension at the end (results in actual read of partial `s[ac]ss|css` and include of it inline to SCSS/SASS):
#import "path/to/file";
to import the CSS-file in a traditional way syntax goes in traditional way, **with `.css` extension** at the end (results to `#import url("path/to/file.css");` in your compiled CSS):
#import "path/to/file.css";
And it is damn good: this syntax is elegant and laconic, plus backward compatible! It works excellently with libsass and node-sass.
__
To avoid further speculations in comments, writing this explicitly: Ruby based Sass still has this feature unimplemented after 7 years of discussions. By the time of writing this answer, it's promised that in 4.0 there will be a simple way to accomplish this, probably with the help of #use. It seems there will be an implementation very soon, the new "planned" "Proposal Accepted" tag was assigned for the issue #556 and the new #use feature.
UPD: on 26 October 2020 lib-sass was deprecated, therefore issue #556 was immediately closed.
__
answer might be updated, as soon as something changes.
Looks like this is unimplemented, as of the time of this writing:
https://github.com/sass/sass/issues/193
For libsass (C/C++ implementation), import works for *.css the same way as for *.scss files - just omit the extension:
#import "path/to/file";
This will import path/to/file.css.
See this answer for further details.
See this answer for Ruby implementation (sass gem)
You must prepend an underscore to the css file to be included, and switch its extension to scss (ex: _yourfile.scss). Then you just have to call it this way:
#import "yourfile";
And it will include the contents of the file, instead of using the CSS standard #import directive.
Good news everyone, Chris Eppstein created a compass plugin with inline css import functionality:
https://github.com/chriseppstein/sass-css-importer
Now, importing a CSS file is as easy as:
#import "CSS:library/some_css_file"
If you have a .css file which you don't wish to modify, neither change its extension to .scss (e.g. this file is from a forked project you don't maintain), you can always create a symlink and then import it into your .scss.
Creates a symlink:
ln -s path/to/css/file.css path/to/sass/files/_file.scss
Imports symlink file into a target .scss:
#import "path/to/sass/files/file";
Your target output .css file is going to hold contents from imported symlink .scss file, not a CSS import rule (mentioned by #yaz with highest comment votes). And you don't have duplicated files with different extensions, what means any update made inside initial .css file immediately gets imported into your target output.
Symbolic link (also symlink or soft link) is a special type of file
that contains a reference to another file in the form of an absolute
or relative path and that affects pathname resolution.
– http://en.wikipedia.org/wiki/Symbolic_link
You can use a third-party importer to customise #import semantics.
node-sass-import-once, which works with node-sass (for Node.js) can inline import CSS files.
Example of direct usage:
var sass = require('node-sass');,
importOnce = require('node-sass-import-once');
sass.render({
file: "input.scss",
importer: importOnce,
importOnce: {
css: true,
}
});
Example grunt-sass config:
var importOnce = require("node-sass-import-once");
grunt.loadNpmTasks("grunt-sass");
grunt.initConfig({
sass: {
options: {
sourceMap: true,
importer: importOnce
},
dev: {
files: {
"dist/style.css": "scss/**/*.scss"
}
}
});
Note that node-sass-import-once cannot currently import Sass partials without an explicit leading underscore. For example with the file partials/_partial.scss:
#import partials/_partial.scss succeeds
#import * partials/partial.scss fails
In general, be aware that a custom importer could change any import semantics. Read the docs before you start using it.
If I am correct css is compatible with scss so you can change the extension of a css to scss and it should continue to work. Once you change the extension you can import it and it will be included in the file.
If you don't do that sass will use the css #import which is something you don't want.
I figured out an elegant, Rails-like way to do it. First, rename your .scss file to .scss.erb, then use syntax like this (example for highlight_js-rails4 gem CSS asset):
#import "<%= asset_path("highlight_js/github") %>";
Why you can't host the file directly via SCSS:
Doing an #import in SCSS works fine for CSS files as long as you explicitly use the full path one way or another. In development mode, rails s serves assets without compiling them, so a path like this works...
#import "highlight_js/github.css";
...because the hosted path is literally /assets/highlight_js/github.css. If you right-click on the page and "view source", then click on the link for the stylesheet with the above #import, you'll see a line in there that looks like:
#import url(highlight_js/github.css);
The SCSS engine translates "highlight_js/github.css" to url(highlight_js/github.css). This will work swimmingly until you decide to try running it in production where assets are precompiled have a hash injected into the file name. The SCSS file will still resolve to a static /assets/highlight_js/github.css that was not precompiled and doesn't exist in production.
How this solution works:
Firstly, by moving the .scss file to .scss.erb, we have effectively turned the SCSS into a template for Rails. Now, whenever we use <%= ... %> template tags, the Rails template processor will replace these snippets with the output of the code (just like any other template).
Stating asset_path("highlight_js/github") in the .scss.erb file does two things:
Triggers the rake assets:precompile task to precompile the appropriate CSS file.
Generates a URL that appropriately reflects the asset regardless of the Rails environment.
This also means that the SCSS engine isn't even parsing the CSS file; it's just hosting a link to it! So there's no hokey monkey patches or gross workarounds. We're serving a CSS asset via SCSS as intended, and using a URL to said CSS asset as Rails intended. Sweet!
To import a regular CSS file into Sass:
Official Sass Documentation: Import CSS into Sass
Simple workaround:
All, or nearly all css file can be also interpreted as if it would be scss. It also enables to import them inside a block. Rename the css to scss, and import it so.
In my actual configuration I do the following:
First I copy the .css file into a temporary one, this time with .scss extension. Grunt example config:
copy: {
dev: {
files: [
{
src: "node_modules/some_module/some_precompiled.css",
dest: "target/resources/some_module_styles.scss"
}
]
}
}
Then you can import the .scss file from your parent scss (in my example, it is even imported into a block):
my-selector {
#import "target/resources/some_module_styles.scss";
...other rules...
}
Note: this could be dangerous, because it will effectively result that the css will be parsed multiple times. Check your original css for that it contains any scss-interpretable artifact (it is improbable, but if it happen, the result will be hard to debug and dangerous).
to Import css file in to scss simply use the this:
#import "src/your_file_path";
without using extension .css at the end
It is now possible using:
#import 'CSS:directory/filename.css';
I can confirm this works:
class CSSImporter < Sass::Importers::Filesystem
def extensions
super.merge('css' => :scss)
end
end
view_context = ActionView::Base.new
css = Sass::Engine.new(
template,
syntax: :scss,
cache: false,
load_paths: Rails.application.assets.paths,
read_cache: false,
filesystem_importer: CSSImporter # Relevant option,
sprockets: {
context: view_context,
environment: Rails.application.assets
}
).render
Credit to Chriss Epstein:
https://github.com/sass/sass/issues/193
Simple.
#import "path/to/file.css";

Resources