Skip to content
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

Using svg as background-image does not work #30

Closed
studnitz opened this issue Jan 14, 2019 · 10 comments · Fixed by #50
Closed

Using svg as background-image does not work #30

studnitz opened this issue Jan 14, 2019 · 10 comments · Fixed by #50
Assignees
Labels
bug Something isn't working enhancement New feature or request good first issue help wanted Extra attention is needed

Comments

@studnitz
Copy link

When you use the default options and rules given here, svg paths cannot be used in CSS background-image: url() anymore.

Example:

background-image: url('~/assets/some-icon.svg')

Output

background-image: url('[Object object]')

Expected

background-image: url("data:image/svg+xml;utf8,<svg> optimized svg </svg>");

This would require https://github.com/bhovhannes/svg-url-loader to work

The webpack config could then look like that, I tried to make it work locally, but somehow the resulting SVG data gets escaped (guess this is some kind of nuxt XSS protection).

config.module.rules.push({
  test: /\.svg$/,
  oneOf: [
    {
      resourceQuery: /css/,
      use: {
        loader: 'svg-url-loader',
        options: { noquotes: false }
      }
    },
    {
      use: [
        'vue-loader',
        {
          loader: 'svg-to-vue-component/loader',
          options
        }
      ]
    }
  ]
})

You could use it then like this:

background-image: url('~/assets/some-icon.svg?css')
@manniL manniL added the enhancement New feature or request label Jan 14, 2019
@studnitz
Copy link
Author

A workaround for this is putting the icons in /static instead of /assets, or maybe using file-loader instead of svg-url-loader in the webpack config mentioned above.

@manniL
Copy link
Member

manniL commented Jan 15, 2019

@studnitz I'll look into this soon ☺️ By default (w/o the module) you can use them as BG images. A custom config could be better for that one though 🤔

@manniL manniL self-assigned this Jan 15, 2019
@hmaesta
Copy link

hmaesta commented Jan 17, 2019

This is a great request – I am facing the same problem right now.

A nice approach used by vue-svg-loader is allowing the use of ?internal when you want the SVG to be inline. ⟶ See here: How to use both inline and external SVGs?

I think that would be better if we could use ?external instead – and leave the default behavior as today. That way we could use something like:

<template>
  <div>
    <InlineSVG />
    <div class="external-svg" />
  </div>
</template>

<script>
import InlineSVG from './public/inline.svg';

export {
  components: {
    InlineSVG,
  },
};
</script>

<style>
.external-svg {
  background-image: url("./public/external.svg?external"); // Note the `?external` query string
}
</style>

@studnitz
Copy link
Author

Here is another workaround from the used library:
egoist/svg-to-vue-component#18 (comment)

@priyeshvadhiya
Copy link

Here it is way to resolve them.

:style="{ backgroundImage: 'url(' + require(@/assets/img/${page.image}) + ')' }"

@manniL manniL added bug Something isn't working help wanted Extra attention is needed good first issue labels Jun 29, 2019
@manniL
Copy link
Member

manniL commented Jun 29, 2019

The workaround from egoist/svg-to-vue-component#18 (comment) could be "translated" from webpack-chain syntax to normal webpack config syntax. If I have some spare time, I'll give it a shot.

However, I'm accepting a PR (feature + one test) that fixes the issue.

@3b3ziz
Copy link
Contributor

3b3ziz commented Jul 3, 2019

@manniL But the approach mentioned in egoist/svg-to-vue-component#18 (comment) would solve only styling imported from .css files. What about <img src="test.svg"> or inline styling <div :style="{ backgroundImage: url('test.svg'} />"?

@manniL
Copy link
Member

manniL commented Jul 3, 2019

@3b3ziz True, ideally an ?inline query (described as ?internal above) would be better 👍

@lucien144
Copy link

lucien144 commented Jul 3, 2019

My approach to this is (tested on Nuxt v2.3 & v2.8) is:

// nuxt.config.js
extend(config) {
	const svgRule = config.module.rules.find(rule =>
		rule.test.test('.svg')
	);

	svgRule.test = /\.(png|jpe?g|gif|webp)$/;

	config.module.rules.push({
		test: /\.svg$/,
		oneOf: [
			{
				resourceQuery: /inline/,
				loader: 'file-loader',
				query: {
					name: 'assets/[name].[hash:8].[ext]'
				}
			},
			{
				loader: 'vue-svg-loader',
				options: {
					// Optional svgo options
					svgo: {
						plugins: [{ removeViewBox: false }]
					}
				}
			}
		]
	});
}

Solves SVG in <img/> as well as in CSS. Usage is <img src="~assets/images/ico-close.svg?inline"/>

@stouch
Copy link

stouch commented Apr 13, 2020

just for the record, since @3b3ziz has modified it himself 👍 , the good way is now :

background-image: url('~/assets/some-icon.svg?inline')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request good first issue help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants