I am trying to use the Rails asset pipeline in my app in a way described at (http://www.mattboldt.com/organizing-css-and-sass-rails/), but am noticing some weird behavior which I believe is causing my styles not to be applied.
The structure of my assets directory is as such:
+-- assets
+--- images
+--- javascripts
+--- stylesheets
+--- styles
- global.scss
- scaffolds.scss
- application.css
- main.scss
I've set up my application.css file to require only itself and a main.scss file in the same app/assets/stylesheets directory:
*= require_self
*= require main
This main.scss file contains all of the other files I'd like to import:
#import "bootstrap-sprockets";
#import "bootstrap";
#import "styles/global.scss";
#import "styles/scaffolds.scss";
However, it seems like none of my styles are being applied when I try to view the project in my browser. The peculiar thing I'm noticing is that my browser is showing that it's downloading both an application-self-<hash>.css file, and a main-self-<hash>.scss file. The first file is mostly blank, and looks as follows:
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
* compiled file so the styles you add here take precedence over styles defined in any styles
* defined in the other CSS/SCSS files in this directory. It is generally better to create a new
* file per style scope.
*
*/
The main-self-<hash>.css file contains all of the custom CSS I've imported into it from other files. I was under the impression that it should actually be compiled into the application.css file instead of being compiled into css and served in its own file. In any case, the effects of this are clear - my styles aren't being applied. I'm not sure where to look to resolve this. Can anyone help point me in the right direction, please?
[EDIT] It seems like externally-sourced (from a URL) CSS files do get compiled properly, and their styles are applied. For instance, I added #import url('http://www.w3schools.com/lib/w3.css'); to my main.scss file and made use of it by applying one of the CSS file's classes to one of my div elements. The style was applied.
In Development mode the assets (css, js) are rendered as is in separate files.
They are combined into one file in production mode when you run
rake assets:precompile
You can check browser "Requests" and "Sources" in Developer tools to make sure if the files are being loaded.
I don't know if it solves the entire problem, but I do know that application.css should be named application.css.erb or the requires will not work.
From the Rails spec
"The asset pipeline automatically evaluates ERB. This means if you add
an erb extension to a CSS asset (for example, application.css.erb),
then helpers like asset_path are available in your CSS rules:
Note about assets
Since all compiled assets are served from /public/assets/, adding a subdirctory structure in the source tree under stylesheets serves only add points of possible failure in the code.
Related
This is maybe too early to get good answers, but here we go: I have a test Rails project, with assets/ directory that looks something like this:
config/
manifest.js
images/
javascripts/
application.js
stylesheets/
_base.scss
_reset.scss
_theme.scss
_variables.scss
application.scss
The manifest file looks like this:
// JS and CSS bundles
//= link_tree ../javascripts .js
//= link_tree ../stylesheets .css
// Images so that views can link to them
//= link_tree ../images
And the application.scss like this:
#import "reset";
#import "variables";
#import "base";
#import "theme";
_base.scss and _theme.scss both make use of variables defined in the _variables.scss file.
What I want it to do is just compile application.scss as normal, but it fails because it doesn't think the variables are defined; this is reasonable, I'm linking as a tree, so [I assume] it's compiling each file individually, and the variables are not available to the two files at that point in time.
So I try link ../stylesheets/application.css instead of the tree, and I get the error message couldn't find file '../stylesheets/application.css' under '/Users/danielcouper/Projects/myproject/app/assets/config'; ie it seems to be looking in entirely the wrong place, or there are different (undocumented) rules regarding filepaths depending on whether you use link or link_tree.
If I move manifest.js out from the assets/config/ directory to assets/ to get the relative paths working, as described in the Sprockets upgrading notes, I get an error telling me that there is no manifest file under assets/config/.
The documentation is [understandably] super sparse at the minute; the only useful thing I've read was at http://eileencodes.com/posts/the-sprockets-4-manifest/, which allowed me to get to this point
Don't use link_tree, link tree will import all the files in the tree. If you only want one application.css file use this:
link application.scss
This way sprockets will start at that file and sass will do the imports.
I just bootstrapped a new rails project and I was trying to reference from an open sourced rails project on how they architect their app.
Link to the open sourced project
I noticed they have multiple layouts e.g. admin, application, home ..etc. And each may load in different stylesheets via stylesheet_link_tag.
For example in focus_home.html.erb:
<!-- Load styles -->
<%= stylesheet_link_tag 'focus_home' %>
<%= stylesheet_link_tag 'app/components/modal' %>
And in their app/assets/stylesheets directory, they have focus_home.scss
I try to follow their architecture where I have multiple css files and I call different stylesheets with different layout.
I created my home.scss to be used by home.html.slim
when I started my rails server and try to load the home page, the following error occurs
Asset filtered out and will not be served: add
`Rails.application.config.assets.precompile += %w( home.css )` to
`config/initializers/assets.rb` and restart your server
Basically it asked me to tell rails to precompile home.scss. However, when I browse through the open source project's code base. It doesn't seem to have this line of code. The precompilation just seem to happen like magic.
So I am wondering what I am missing ?
==============
Edit: Further explain the case
In their project they DO NOT have an application.css file like normal rails project.
/* * This is a manifest file that'll be compiled into application.css, which will include all the files * listed below. *
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets, * or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path. * * You're free to add application-wide styles to this file and they'll appear at the bottom of the * compiled file so the styles you add here take precedence over styles defined in any styles * defined in the other CSS/SCSS files in this directory. It is generally better to create a new * file per style scope. * *= require_tree . *= require_self */
Instead, in their application.scss, it goes like
#charset "utf-8";
#import "vars/base";
#import "constants";
// Libraries
#import 'bootstrap';
#import 'app/mixins/*';
#import 'basscss';
#import '_deprecated/basspluss';
#import '_deprecated/utility';
#import '_deprecated/nocss_vars';
#import '_deprecated/nocss';
#import '_deprecated/nocss_mq';
#import "app/main";
#import "base/*";
#import "utilities/*";
#import "app/components/*";
#import "components/*";
#import "app/slop";
#import 'libs/owl.carousel';
#import 'libs/owl.transitions';
#import 'libs/owl.theme';
#import 'c3/c3'
So I wonder how they actually do their precompilation??
You don't need to use Sprockets comments in your application.scss and must only use #import CSS rules.
From rails-sass documentation:
Sprockets provides some directives that are placed inside of comments
called require, require_tree, and require_self. DO NOT USE THEM IN
YOUR SASS/SCSS FILES. They are very primitive and do not work well
with Sass files. Instead, use Sass's native #import directive which
sass-rails has customized to integrate with the conventions of your
Rails projects.
Then, if you have any other .scss that needs to be precompiled, you will have to explicitly add them using the Rails.Application.config.assets.precompile directive, then the sprockets railtie will do the rest of the job!
To answer your original question, the reason why the open source project do not need to specify assets to precompile is because they are using config.assets.compile = true in the config/environment/production.rb file. This is obviously a very bad practice and I don't recommend you to switch this directive to true in a production environment... you will end up with a slow code making a lot of requests and there a slow page load.
In app/assets/stylesheets, I have many sass files. In a requested page, every file in app/assets/stylesheets is imported (with a tag). How do I make it so that not every file from the directory is imported, but only the ones that I pick?
Note: I'm running Rails 4.1.2
You change your app/assets/stylesheets/application.css file.
Instead of *=require_tree .
Add:
*=require './file1'
*=require './file2'
...
You don't need to supply .css or .css.scss
Manifest
As alluded to by #Ruby Racer, you'll be looking to manipulate the manifest of your stylesheets in your application:
Sprockets uses manifest files to determine which assets to include and
serve. These manifest files contain directives - instructions that
tell Sprockets which files to require in order to build a single CSS
or JavaScript file.
The way to use this is at the top of any of your css files, typically your application.css file -
/app/assets/stylesheets/application.css
/* = require "file" */
By doing this, you'll be able to build your stylesheet assets as you require
--
SASS
If it's only the stylesheets you want to change, you need to remember something else -
If you changed the extension of your CSS to .css.scss, you'll be able to call the #import function of SASS to create a similar effect to the manifest functionality:
#app/assets/stylesheets/application.css.scss
#import "file"
I'm trying to add Compass to my Rails 3.2 app, using compass-rails. How can I get it to automatically import all of the stylesheets in app/assets/stylesheets? At the moment I have to manually do #import 'filename'; in application.css.scss for each one.
Put all your scss files (except application.css.scss) in a different folder:
/application.css.scss
/all/hello.css.scss
/all/hi.css.scss
application.css.scss file like below will work.
#import "compass";
#import "all/*";
For bundling stylesheets, use the asset pipeline
If you're using the asset pipeline, this should happen automagically with:
/*
* In application.css
*= require_tree .
*/
Docs: http://guides.rubyonrails.org/asset_pipeline.html#manifest-files-and-directives
The important caveat is "Using Sprockets directives all Sass files exist within their own scope, making variables or mixins only available within the document they were defined in."
For mixins & vars, have your imports in one place, then import once
If you're heavy on the functions, try having a file like app/assets/stylesheets/base.css.scss that contains #import directives (wildcard or not) for all your mixin and var files. Then you only need to #import "base" once for every stylesheet and can still bundle your css using sprockets directives.
Here's my application.css:
/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require bootstrap
*= require bootstrap-responsive
*= require style
For some reason none of my css styles are being applied. When I view source and open application.css, the file is exactly the same. It's not compiling it. The application.js is compiling just fine!
my gemfile: https://gist.github.com/1748054
Any ideas?
EDIT: Fixed it by adding */
Make sure you have:
# Enable the asset pipeline
config.assets.enabled = true
set in your config/application.rb
Also this is a bit of a shot in the dark but don't you need to have a line like this:
*=require_self
before anything else. I always use sass imports to include my stylesheets with more precision. So mine would look like this:
/*
*= require_self
*/
#import "bootstrap.css";
#import "bootstrap-responsive.css";
#import "style.css";
Then just make sure your file is named application.css.scss