112

I have a simple Chrome extension that uses the content script feature to modify a website. More specifically, the background-image of said website.

For some reason I can't seem to be able to use local images, even though they are packed in the extension.

body {
    background: #000 url('image.jpg') !important;
    background-repeat: repeat !important;
}

That's it, the simplest CSS... but it won't work. The browser doesn't load the image.

Ninjakannon
  • 3,751
  • 7
  • 53
  • 76
Bjarki Jonasson
  • 1,165
  • 3
  • 9
  • 5

12 Answers12

278

Chrome has i18n support that provides the ability to reference your extension in your CSS. I keep my images in an image folder in the extension, so reference assets in the CSS like so:

background-image:url('chrome-extension://__MSG_@@extension_id__/images/main.png');
zessx
  • 68,042
  • 28
  • 135
  • 158
David Lemphers
  • 3,568
  • 3
  • 18
  • 10
  • 4
    Great one. This is a great solution and does indeed work for both unpackaged and packaged extensions - thanks for sharing a really great tip. – RidingTheRails Apr 13 '12 at 17:13
  • 43
    Thanks, this is exactly what I was looking for. Just a footnote: remember that you need to declare your assets as web_accessible_resources in your manifest file (as explained here: http://code.google.com/chrome/extensions/manifest.html#web_accessible_resources). Otherwise they won't be loaded – ariera Jul 01 '12 at 17:22
  • 2
    One thing i realized! Never think accepted answer is the only correct solution for that question! I was afraid i have to do hardcode when i saw accepted answer but after seeing you answer i told myself this guy saved my day!! ;-) – Rafique Mohammed Aug 12 '15 at 20:27
  • This is almost always the better way to do it. Pure CSS vs. coupling Javascirpt and CSS together in @serg answer. This should be the accepted answer in my opinion. – Jeremy Zerr Aug 06 '16 at 16:49
  • @ariera's link is here now: https://developer.chrome.com/extensions/manifest/web_accessible_resources – Ben Jan 11 '17 at 15:08
  • If you struggle with chrome vs firefox: use this: `@supports(-webkit-user-select: none ) { :root{ --url_header: url("chrome-extension://__MSG_@@extension_id__/images/header.gif"); } } @supports(-moz-user-select: none ) { :root{ --url_header: url("moz-extension://__MSG_@@extension_id__/images/header.gif"); } }` – Sonny D Oct 23 '18 at 21:33
  • 1
    this doesn't work for chrome 76, it can only work when I specify the real extension id, like: ```url(chrome-extension://fibcjgogcmhklkadjokijclpdcfmpdhp/resources/32px.png)```, rather than ```url(chrome-extension://__MSG_@@extension_id__/resources/32px.png)```, any idea? – aaron Sep 05 '19 at 07:47
  • @aaron Add images to `web_accessible_resources` in `manifest.json` – Eugene Mala Mar 20 '23 at 10:20
79

Your image URL should look like chrome-extension://<EXTENSION_ID>/image.jpg

You would be better off replacing css through javascript. From docs:

//Code for displaying <extensionDir>/images/myimage.png:
var imgURL = chrome.extension.getURL("images/myimage.png");
document.getElementById("someImage").src = imgURL;
Sam Hanley
  • 4,707
  • 7
  • 35
  • 63
serg
  • 109,619
  • 77
  • 317
  • 330
  • 7
    @Salem Because otherwise you would need to hardcode your extension id in css. – serg Jul 28 '11 at 22:04
  • Not to be dumb, but why is that an issue? – Salem Jul 28 '11 at 22:08
  • 5
    @Salem It would be inconvenient to develop as unpacked extension id and uploaded to the gallery one have different ids. It's not the end of the world, just inconvenience and sort of bad practice, just like hardcoding absolute file pathes in the code for example. – serg Jul 28 '11 at 22:23
  • Since this is the accepted answer, you should see comment on the other answer where ariera mentioned about including web_accessible_resources in your manifest file to access local fonts and images. – Aryan Firouzian Feb 26 '17 at 16:44
  • `chrome.runtime.getURL` — the new API – Inversion Apr 15 '23 at 10:41
52

There are a lot of older answers and solutions to this question.

As of August 2015 (using Chrome 45 and Manifest version 2), the current "best practice" for linking to local images within Chrome Extensions is the following approach.

1) Link to the asset in your CSS using a relative path to your extension's images folder:

.selector {
    background: url('chrome-extension://__MSG_@@extension_id__/images/file.png');
}

2) Add the individual asset to to the web_accessible_resources section of your extension's manifest.json file:

"web_accessible_resources": [
  "images/file.png"
]

Note: This method is suitable for a few files, but doesn't scale well with many files.

Instead, a better method is to leverage Chrome's support for match patterns to whitelist all files within a given directory:

{
    "name": "Example Chrome Extension",
    "version": "0.1",
    "manifest_version": 2,
    ...    
    "web_accessible_resources": [
      "images/*"
    ]
}

Using this approach will allow you to quickly and effortlessly use images in your Chrome Extension's CSS file using natively supported methods.

rjb
  • 9,036
  • 2
  • 44
  • 49
25

One option would be to convert your image to base64:

and then put the data right into your css like:

body { background-image: url(data:image/png;base64,iVB...); }

While this might not be an approach you would want to use when regularly developing a webpage, it is a great option due to some of the constraints of building a Chrome Extension.

Community
  • 1
  • 1
Brian Sloane
  • 351
  • 3
  • 2
  • 1
    I prefer this option. I disagree that Google is correct to suggest injecting _all_ images via the approach mentioned above. The base64 approach is also faster. +1!!! – Skone Nov 18 '11 at 22:51
22

My solution.

With Menifest v2 you need to add web_accessible_resources to the file and then use chrome-extension://__MSG_@@extension_id__/images/pattern.png as the url in your css file.

CSS:

 #selector {
      background: #fff url('chrome-extension://__MSG_@@extension_id__/images/pattern.png'); 
 }

Manifest.json

{
  "manifest_version": 2,

  "name": "My Extension Name",
  "description": "My Description",
  "version": "1.0",

  "content_scripts": [
      {
        "matches": ["https://mydomain.com/*"],
        "css": ["style.css"]
      }
    ],

  "permissions": [
    "https://mydomain.com/"
  ],
  "browser_action": {
      "default_icon": {                    
            "19": "images/icon19.png",           
            "38": "images/icon38.png"          
       },
       "default_title": "My Extension Name"  
   },
   "web_accessible_resources": [
       "images/pattern.png"
     ]
}

p.s. Your manifest.json might look different to this one.

Foxinni
  • 3,980
  • 2
  • 26
  • 26
9

One thing to mention is that in the web_accessible_resources you can use wildcards. So instead of

"images/pattern.png"

You can use

"images/*"

patrick_hogan
  • 301
  • 2
  • 2
9

This CSS-version-only works in extension environment (app page, popup page, background page, option page) as well as content_scripts CSS file.

In .less file, I always set a variable at the beginning:

@extensionId : ~"__MSG_@@extension_id__";

Then later, if you want to refer to extension-local-resource like images, use:

.close{
    background-image: url("chrome-extension://@{extensionId}/images/close.png");
}
Thach Lockevn
  • 1,438
  • 1
  • 12
  • 15
4

Just to clarify, according to the documentation, every file in an extension is also accessible by an absolute URL like this:

chrome-extension://<extensionID>/<pathToFile>

Note the <extensionID> is a unique identifier that the extension system generates for each extension. You can see the IDs for all your loaded extensions by going to the URL chrome://extensions. The <pathToFile> is the location of the file under the extension's top folder; it's the same as the relative URL.

...

Changing background image in CSS:

#id { background-image: url("chrome-extension://<extensionID>/<pathToFile>"); }


Changing background image in CSS through JavaScript:

document.getElementById('id').style.backgroundImage = "url('chrome-extension://<extensionID>/<pathToFile>')");


Changing background image in CSS through jQuery:

$("#id").css("background-image", "url('chrome-extension://<extensionID>/<pathToFile>')");

quackkkk
  • 139
  • 1
  • 13
2

we can use the Predefined messages of Chrome extensions. Predefined messages

body {
  background-image:url('chrome-extension://__MSG_@@extension_id__/background.png');
}
Ren Yun
  • 31
  • 2
0

For manifest v3, there are some modifications:

  1. chrome.extension.getUrl() -> chrome.runtime.getUrl()
  2. "web_accessible_resources" -> "web_accessible_resources.resources"
  3. fill in "web_accessible_resources.matches"

2, 3 like this:

"web_accessible_resources": [{
  "resources": ["images/logo.png"],
  "matches": ["<all_urls>"],
}],

reference:

tyn
  • 1
  • 1
0

Those answers above are great but your extension gets a new id every time it gets installed, so putting the id manually doesn't work if you gonna make it public at some point.

Here's my solution using manifest v.3:

//Get the url from some file within your extension's folder and store it on a global variable
var url = chrome.runtime.getURL('my_extension/img/Icon.svg');

//Take off the last part from the url string
url = url.replace('img/Icon.svg', '');

Now replace the src attribute for a custom one on every img tag and keep the file path as it's value like this:

<img ref-file="img/IconStop.svg" alt="">

Then run this function after loading the html:

loadImgs = function () {
    $("img[ref-file]").each(function() {
        var ref_file = $(this).attr('ref-file');
        url = url + ref_file;
        $(this).attr('src', url);
    });
}
0

This works for me in a Chrome extension built in Vue.js The logo was stored in /public/images/logo.png and my components in /src/components/shared/logo.vue

<template>
  <img :src="logoURL" alt="Logo" />
</template>
<script>
export default {
    computed: {
        logoURL() {
            return chrome.runtime.getURL("images/logo.png");
        }
    }
}
</script>

manifest.json

{
  "manifest_version": 3
}
sparkle
  • 7,530
  • 22
  • 69
  • 131