New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

inline-image() with no base64-encoding (for SVG) #1460

Open
afoeder opened this Issue Nov 29, 2013 · 28 comments

Comments

Projects
None yet
@afoeder

afoeder commented Nov 29, 2013

When using inline-image() with an SVG file, it's so far correctly output with url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXR ....

However, for SVG files, this is unnecessary overhead (the typical base64-33%-overhead) since it's enough to only urlencode the plain SVG content, and probably additionally "minify" the markup. The output could read like

url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' ...

What do you think?

(Sources:

@waynedpj

This comment has been minimized.

Show comment
Hide comment
@waynedpj

waynedpj Nov 29, 2013

i have been looking into doing this for SVG images as CSS backgrounds and was surprised to not find it already in Compass since it seems like a very likely candidate for a helper.

here is some more detail on inlining SVG in CSS:

http://r.va.gg/2012/05/data-uri-svg.html

peace, w

waynedpj commented Nov 29, 2013

i have been looking into doing this for SVG images as CSS backgrounds and was surprised to not find it already in Compass since it seems like a very likely candidate for a helper.

here is some more detail on inlining SVG in CSS:

http://r.va.gg/2012/05/data-uri-svg.html

peace, w

@scottbert

This comment has been minimized.

Show comment
Hide comment
@scottbert

scottbert Dec 15, 2013

This'd be awesomely useful and probably fairly easy to achieve.

scottbert commented Dec 15, 2013

This'd be awesomely useful and probably fairly easy to achieve.

@exwar

This comment has been minimized.

Show comment
Hide comment
@exwar

exwar Apr 12, 2014

+1 for this issue.
It will also provide more browser coverage

exwar commented Apr 12, 2014

+1 for this issue.
It will also provide more browser coverage

@depoulo

This comment has been minimized.

Show comment
Hide comment
@depoulo

depoulo commented Aug 26, 2014

+1

7 similar comments
@mherchel

This comment has been minimized.

Show comment
Hide comment
@mherchel

mherchel commented Sep 17, 2014

+1

@matt-d-rat

This comment has been minimized.

Show comment
Hide comment
@matt-d-rat

matt-d-rat commented Sep 22, 2014

+1

@mechanicalduck

This comment has been minimized.

Show comment
Hide comment
@mechanicalduck

mechanicalduck commented Oct 4, 2014

+1

@TPABHuKOB

This comment has been minimized.

Show comment
Hide comment
@TPABHuKOB

TPABHuKOB commented Oct 20, 2014

+1

@albi

This comment has been minimized.

Show comment
Hide comment
@albi

albi commented Oct 23, 2014

+1

@jacksleight

This comment has been minimized.

Show comment
Hide comment
@jacksleight

jacksleight commented Oct 23, 2014

+1

@yleviel

This comment has been minimized.

Show comment
Hide comment
@yleviel

yleviel commented Oct 27, 2014

+1

@Alexis2004

This comment has been minimized.

Show comment
Hide comment
@Alexis2004

Alexis2004 Nov 2, 2014

Until it is not implemented in compass itself you can use this custom function (place it in the end of your config.rb file):

require 'sass'

module Sass::Script::Functions

  def inline_svg_image(path)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    encoded_svg = URI::encode(svg)
    data_url = "url('data:image/svg+xml;utf8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

Now you can inline svg files using following syntax in sass file: background-image: inline-svg-image("path/to/image.svg")

Alexis2004 commented Nov 2, 2014

Until it is not implemented in compass itself you can use this custom function (place it in the end of your config.rb file):

require 'sass'

module Sass::Script::Functions

  def inline_svg_image(path)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    encoded_svg = URI::encode(svg)
    data_url = "url('data:image/svg+xml;utf8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

Now you can inline svg files using following syntax in sass file: background-image: inline-svg-image("path/to/image.svg")

@depoulo

This comment has been minimized.

Show comment
Hide comment
@depoulo

depoulo Nov 2, 2014

Great, thanks! Life's easier if you know Ruby ;)

depoulo commented Nov 2, 2014

Great, thanks! Life's easier if you know Ruby ;)

@jrodl3r

This comment has been minimized.

Show comment
Hide comment
@jrodl3r

jrodl3r commented Nov 29, 2014

+1 👍 Thx @Alexis2004!

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Nov 29, 2014

I don't use Compass, but I noticed a posting to this. You all may not have realized that this currently does not work in all browsers: less/less.js#2184 (comment)

Sorry, my memory was off.

stevenvachon commented Nov 29, 2014

I don't use Compass, but I noticed a posting to this. You all may not have realized that this currently does not work in all browsers: less/less.js#2184 (comment)

Sorry, my memory was off.

@Alexis2004

This comment has been minimized.

Show comment
Hide comment
@Alexis2004

Alexis2004 Dec 1, 2014

@stevenvachon, thanks for your comment! I've rechecked generated svg files in IE and realized that they really not displayed at all due to IE consider that svg encoding is incorrect.

Here's corrected version of config.rb file that make it works in IE9/10/11:

require 'sass'
require 'cgi'

module Sass::Script::Functions

  def inline_svg_image(path)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    encoded_svg = CGI::escape(svg).gsub('+', '%20')
    data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

Also here's example showing difference between wrong and correct svg encoding: http://dbushell.com/demos/svg/utf8uri/test2.html

Alexis2004 commented Dec 1, 2014

@stevenvachon, thanks for your comment! I've rechecked generated svg files in IE and realized that they really not displayed at all due to IE consider that svg encoding is incorrect.

Here's corrected version of config.rb file that make it works in IE9/10/11:

require 'sass'
require 'cgi'

module Sass::Script::Functions

  def inline_svg_image(path)
    real_path = File.join(Compass.configuration.images_path, path.value)
    svg = data(real_path)
    encoded_svg = CGI::escape(svg).gsub('+', '%20')
    data_url = "url('data:image/svg+xml;charset=utf-8," + encoded_svg + "')"
    Sass::Script::String.new(data_url)
  end

private

  def data(real_path)
    if File.readable?(real_path)
      File.open(real_path, "rb") {|io| io.read}
    else
      raise Compass::Error, "File not found or cannot be read: #{real_path}"
    end
  end

end

Also here's example showing difference between wrong and correct svg encoding: http://dbushell.com/demos/svg/utf8uri/test2.html

@mherchel

This comment has been minimized.

Show comment
Hide comment
@mherchel

mherchel Dec 1, 2014

@Alexis2004 Freaking awesome! Just tested in IE9, FF, Safari, and Chrome. 🍺 🍺 🍺 🍺

mherchel commented Dec 1, 2014

@Alexis2004 Freaking awesome! Just tested in IE9, FF, Safari, and Chrome. 🍺 🍺 🍺 🍺

@fwebdev

This comment has been minimized.

Show comment
Hide comment
@fwebdev

fwebdev commented Jan 7, 2015

+1

@thomasbachem

This comment has been minimized.

Show comment
Hide comment
@thomasbachem

thomasbachem Mar 28, 2015

My testing shows that many SVG images result in bigger size when URL-encoded than Base64-encoded, so I'll stick with inline-image.

thomasbachem commented Mar 28, 2015

My testing shows that many SVG images result in bigger size when URL-encoded than Base64-encoded, so I'll stick with inline-image.

@stevenvachon

This comment has been minimized.

Show comment
Hide comment
@stevenvachon

stevenvachon Mar 28, 2015

@thomasbachem are you using gzip on your server? It makes a world of difference on file size.

stevenvachon commented Mar 28, 2015

@thomasbachem are you using gzip on your server? It makes a world of difference on file size.

@thomasbachem

This comment has been minimized.

Show comment
Hide comment
@thomasbachem

thomasbachem Mar 28, 2015

@stevenvachon You're right, I didn't compare it in gzipped state.

thomasbachem commented Mar 28, 2015

@stevenvachon You're right, I didn't compare it in gzipped state.

@SamHasler

This comment has been minimized.

Show comment
Hide comment
@SamHasler

SamHasler May 28, 2015

(For anyone else googling this) There's a pure sass function for this here: http://codepen.io/Tigt/blog/optimizing-svgs-in-data-uris

SamHasler commented May 28, 2015

(For anyone else googling this) There's a pure sass function for this here: http://codepen.io/Tigt/blog/optimizing-svgs-in-data-uris

@sharq88

This comment has been minimized.

Show comment
Hide comment
@sharq88

sharq88 Jun 23, 2015

@SamHasler thank you very very much... I wasted sooo much time on this.. Ahh.. thanks!!!

sharq88 commented Jun 23, 2015

@SamHasler thank you very very much... I wasted sooo much time on this.. Ahh.. thanks!!!

@alimdar

This comment has been minimized.

Show comment
Hide comment
@alimdar

alimdar Jan 16, 2016

has anyone found a way to change svg color while using libSass? ive used the ruby code before and it works great, but now switching to libsass, i need a different solution. Anyone?

alimdar commented Jan 16, 2016

has anyone found a way to change svg color while using libSass? ive used the ruby code before and it works great, but now switching to libsass, i need a different solution. Anyone?

@thomasbachem

This comment has been minimized.

Show comment
Hide comment
@thomasbachem

thomasbachem Jan 16, 2016

@alimbar I developed an extension for that called compass-svg-templates.

thomasbachem commented Jan 16, 2016

@alimbar I developed an extension for that called compass-svg-templates.

@alimdar

This comment has been minimized.

Show comment
Hide comment
@alimdar

alimdar Jan 17, 2016

thank you @thomasbachem, i took a look at it, it still requires ruby, but for libsass shouldnt it be c++? sorry, im trying to get my head around libsass and what can i use with it

alimdar commented Jan 17, 2016

thank you @thomasbachem, i took a look at it, it still requires ruby, but for libsass shouldnt it be c++? sorry, im trying to get my head around libsass and what can i use with it

@strarsis

This comment has been minimized.

Show comment
Hide comment
@strarsis

strarsis Jan 31, 2016

You can do this with libsass, too using eyeglass which allows using npm packages:

eyeglass-file-text for plain text + binary files (as base64 string)
eyeglass-inline-svg (uses eyeglass-file-text above + eyeglass-inline-urlescape)
for plain text in data uris, notably SVG files.

strarsis commented Jan 31, 2016

You can do this with libsass, too using eyeglass which allows using npm packages:

eyeglass-file-text for plain text + binary files (as base64 string)
eyeglass-inline-svg (uses eyeglass-file-text above + eyeglass-inline-urlescape)
for plain text in data uris, notably SVG files.

@lvl99

This comment has been minimized.

Show comment
Hide comment
@lvl99

lvl99 Mar 19, 2016

I wrote a feature for my own usage whereby one can inline SVG code written in the SCSS file without base64 encoding: inline-svg-code

lvl99 commented Mar 19, 2016

I wrote a feature for my own usage whereby one can inline SVG code written in the SCSS file without base64 encoding: inline-svg-code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment