Application.css

*= require palette *= require global *= require_tree . *= require_self 

vendor / assets / stylesheet / pallete.scss

 .grey { background-color: #9e9e9e; } 

global.scss

 html { body { header { @extend .grey; } } } 

Gives an error message:

"html body header" failed to @extend ".grey".
The selector ".grey" was not found.
Use "@extend .grey! Optional" if it should be able to fail.

If the .grey class is .grey in the global.scss file and the global.scss in the same file, then everything works fine, from any other files it is not extendend.

I tried to move the palette file from vendor to app , change the order in application.css , remove *= require_tree . , updated gems, overloaded the server, the computer - the result is the same.

 rake assets:clean rake assets:precompile 

Also did not change anything.

In an empty application from scratch the same problem.

Versions of ruby ​​and gems:

  • ruby 2.2.0p0
  • Rails 4.2.5
  • sass (3.4.21)
  • sass-rails (5.0.4)

    1 answer 1

    All right, the SCSS files are compiled by Sass one by one, and then Sprockets (the assembly system for Rails) stitches the resulting styles from them (using the require directives in the comments).

    Thus, when global.scss is global.scss , Sass knows nothing about the contents of palette.scss . To find out, you need to import the appropriate file:

     @import 'palette.scss' 

    ... yes, this is very similar to the CSS-based @import , Sass expands it syntactically, neatly catching cases when it needs to be left "as is". In fact, this includes the contents of the specified file in place of this directive. That is, the import can be done even inside the rule block, and everything will be loaded inside it. The guide on the link above details.


    I pay attention that idiomatic Sass-import usually occurs with files that have _ at the beginning of the file name (so-called partial ), like _palette.scss , and import it like this:

     @import 'palette' 

    It should also be understood that the use of code in the included files, which is rendered in non-empty CSS, will result in these blocks occurring several times if, as a result, this file is imported several times. To avoid this, you can use the selector-stub :

     %grey { background-color: #9e9e9e; } 

    If you render this construct in CSS, you get an empty file. But you can do @extend %grey , getting the desired effect.

    • Thanks, with Sass and Sprockets everything is clear, but what about import? Embed @import 'palette' into each .scss file? Is this somehow not DRY and will it cause a repetition of the code from the palette file? Or instead of application.css use application.scss and import all .scss files there? - Ampersand
    • Completed the question. ) - Ampersand
    • @Ampersand is not DRY as much as the sharing of a common code into a separate function is not DRY. Yes, the code from the palette will be displayed in this way several times, so it makes sense to use %псевдоселекторами , which themselves are not rendered, but can be used to extend others. - D-side
    • Um, I was mistaken with the term: this is "placeholder selector", selector-stub ( source ). - D-side
    • Clear. Thanks for the extended answer! - Ampersand