Syntactic Fructose Syntactic Fructose -4 years ago 68
Sass (Sass) Question

How to give controller sass files precedence over sass imported from application.scss

I'm having an issue in that inside my controllers scss file, I continually have to mark everything with

in order to style elements. Here's an example input element in my
controllers scss:

.search-field {
width: 300px !important;
box-shadow: none !important;
border-bottom: none !important;
display: inline-block;
font-size: 16px;
margin-left: 15px !important;

This is because inside
, I imported my material library which takes precedence over

* 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, 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 other CSS/SCSS
* files in this directory. Styles in this file should be added after the last require_* statement.
* It is generally better to create a new file per style scope.
*= require_tree .
*= require_self
@import "materialize";
@import "font-awesome";
* {
font-family: 'Raleway', sans-serif;

html {
width: 100%;
height: 100%;
body {
margin: 0;
min-width: 100%;
min-height: 100%;
background-color: #1A1A1A;

How can I avoid having to use the
flag everywhere?


I have also tried the following (with no luck)

I added an additional link to my controllers css

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= stylesheet_link_tag 'map', media: 'all', 'data-turbolinks-track': 'reload' %>

then removed the use of
require_tree .
inside application.scss

When I restarted the server however, I still needed the !important tags. Still no luck

Answer Source

Since it's very rare to need every stylesheet in your application to be loaded on every page, you'll find importing only what's necessary per page to be much more efficient, shorten load times, and also address the problem of which styles take precedence! The Rails way to do this is to remove the require tree statements in your /application.js and /application.scss files. The only files imported in your application.js & application.scss files should be app-wide styles or js. Then you would add the following lines to your layouts/application.html.erb file:

Inside the <head> tag:

<%= stylesheet_link_tag params[:controller] if Rails.application.assets_manifest.assets["#{params[:controller]}.css"]

This will then include the corresponding controller's stylesheets. Putting this before or after the stylesheet_link_tag for your application changes the precedence based upon your needs.

Then in your <body> tag you should add:

 <%= javascript_include_tag params[:controller] if Rails.application.assets_manifest.assets["#{params[:controller]}.js"]

Now, to make this work in production for deploying your app you'll need to add the controller names to your config/initializers/assets.rb file or else you'll get an error that the assets weren't compiled. In that file you'll add as follows for your map controller:

Rails.application.config.assets.precompile += %w( maps.js )

Rails.application.config.assets.precompile += %w( maps.css) #Note rails expects the css suffix and not the scss suffix here so use that and not scss even though your file may be maps.scss  

Then everytime you add a new controller in the future, add that controller's name to the arrays shown above and then run bundle exec rake assets:precompile RAILS_ENV=production and you're good to go. For more examples checkout my old answer on basically the same problem here: sprockets loads sass in random order with twitter bootstrap

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download