Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Inline CSS or JS in Rails
config.assets.precompile += [
# precompile any CSS or JS file that doesn't start with _
/(^inline[^_\/]|\/[^_])[^\/]*.(js|css)$/,
...
def read_file_contents(stylesheet)
if %w(test development).include?(Rails.env.to_s)
# if we're running the full asset pipeline,
# just grab the body of the final output
stylesheet.body
else
# in a production-like environment, read the
# fingerprinted and compiled file
File.read(File.join(Rails.root, 'public', 'assets', stylesheet.digest_path))
end
end
def inline_file(asset_path)
file = Rails.application.assets.find_asset(asset_path)
file.nil? ? '' : read_file_contents(file)
end
def inline_js(asset_path)
"<script>#{inline_file asset_path}</script>"
end
def inline_css(asset_path)
"<style>#{inline_file asset_path}</style>"
end
# use a method like this to automatically load CSS that
# follows the current controller/action name structure
# example: assets/stylesheets/views/users/show.sass
def current_view_stylesheet
inline_css("views/#{params[:controller]}/#{params[:action]}") +
end
@wafiq

This comment has been minimized.

Copy link

wafiq commented Oct 27, 2015

Should stylesheet.body be stylesheet.source instead?

Source: https://github.com/rails/sprockets/blob/master/lib/sprockets/asset.rb#L26

@Dagnan

This comment has been minimized.

Copy link

Dagnan commented Jan 25, 2017

.source works for Rails 5.

@Dagnan

This comment has been minimized.

Copy link

Dagnan commented Jan 25, 2017

@dignoe

This comment has been minimized.

Copy link

dignoe commented Mar 3, 2017

FYI - I couldn't get this to work in Rails 3.2 with Sprockets 2.2.3. Here's what I did (created independently of this code, but posting here for anyone who needs some help):

module StylesheetsHelper

  private

  def include_inline_stylesheet(file)
    content_for :stylesheets do
      content_tag("style", inline_stylesheet_source(file).html_safe, type: "text/css")
    end
  end

  def inline_stylesheet_source(file)
    path = file.pathmap("%-1d")
    filename = File.basename(file, ".html.erb").titleize.parameterize

    if Rails.env.development? || Rails.env.test?
      Rails.application.assets["responsive/inline/#{path}/#{filename}"].body
    else
      asset_path = ActionController::Base.helpers.asset_path("responsive/inline/#{path}/#{filename}.css")
      File.read("#{Rails.root}/public#{asset_path}")
    end    
  end

end

And then in my views I add <%= include_inline_stylesheet(__FILE__) %> and I have a <%= yield :stylesheets %> in my <head>.
CSS files are in the format of responsive/inline/orders/index.css.scss (Note that this code replaces underscores with dashes in the filename, so my_file.html.erb becomes my-file.css).

@FinnWoelm

This comment has been minimized.

Copy link

FinnWoelm commented Jul 31, 2017

This is genius. Thank you a lot, @averyvery and @Dagnan!

@wagoid

This comment has been minimized.

Copy link

wagoid commented Sep 25, 2017

@averyvery you could also leverage Rails cache when reading the file contents, replacing this:
File.read(File.join(Rails.root, 'public', 'assets', stylesheet.digest_path))
by this:
render file: File.join(Rails.root, 'public', 'assets', stylesheet.digest_path)

render here will return the actual string with the file contents, because it's being called from a view template 😃
That will avoid a lot of I/O operations and make your users happier!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.