How can you use CSS variables with JavaScript to change images?

4.9k views Asked by At

I'm working on a small update to http://codepen.io/wesbos/pen/adQjoY and wanted to use a CSS variable to change the image, just to see if I can do it. So far, it's not working.

<img src=imageFile>

<style>
:root {
    --image: 1;
    --imageFile: '"https://source.unsplash.com/7bwQXzbF6KE/800x500"';
}

img {
    src: var(--imageFile);
}
</style>

and I have some If, Then, Else, implemented in <script> ... </script> to change the imageFile variable.

In the DevTools console I get:

GET file:///Users/tim/bloc/JavaScript30-master/03%20-%20CSS%20Variables/imageFile net::ERR_FILE_NOT_FOUND

The image doesn't change. Can you help? Here is my full code before the update:

// get the inputs
const inputs = [].slice.call(document.querySelectorAll('.controls input'));

// listen for changes
inputs.forEach(input => input.addEventListener('change', handleUpdate));
inputs.forEach(input => input.addEventListener('mousemove', handleUpdate));

function handleUpdate(e) {
// append 'px' to the end of spacing and blur variables
    const suffix = (this.id === 'base' ? '' : 'px');
    document.documentElement.style.setProperty(`--${this.id}`, this.value + suffix);
}
:root {
  --base: #ffc600;
  --spacing: 10px;
  --blur: 10px;
}

body {
  text-align: center;
}

img {
  padding: var(--spacing);
  background: var(--base);
  -webkit-filter: blur(var(--blur));
  /*  */
  filter: blur(var(--blur));
}

.hl {
  color: var(--base);
}

body {
  background: #193549;
  color: white;
  font-family: 'helvetica neue', sans-serif;
  font-weight: 100;
  font-size: 50px;
}

.controls {
  margin-bottom: 50px;
}

a {
  color: var(--base);
  text-decoration: none;
}

input {
  width:100px;
}
<h2>Update CSS Variables with <span class='hl'>JS</span></h2>
<div class="controls">
  <label>Spacing:</label>
  <input type="range" id="spacing" min="10" max="200" value="10">

  <label>Blur:</label>
  <input type="range" id="blur" min="0" max="25" value="10">

  <label>Base Color</label>
  <input type="color" id="base" value="#ffc600">
</div>

<img src="http://unsplash.it/800/500?image=899">

<p class="love">Made by <a href="http://twitter.com/wesbos">@wesbos</a> </p>
<p class="love">Chrome 49+, Firefox 31+</p>

3

There are 3 answers

2
sachsure On

If you want to use CSS to specify the source of your file you can use something like this:

HTML:

<img>

CSS:

img{
  content:url("IMAGE URL");
}

for your reference: https://jsfiddle.net/tqoLe7r3/

4
Okomikeruko On

In your :root declaration, you can only set CSS values as variables.

Try this:

:root{
  --imageFile: url('https://source.unsplash.com/7bwQXzbF6KE/800x500');
}
img {
  content: var(--imageFile);
}

Like this: https://jsfiddle.net/wdkmbeL7/

0
BoltClock On

src is an HTML attribute, not a CSS property.

src=imageFile points to a resource in the current URL directory path called imageFile. That's why the browser is attempting to GET file:///Users/tim/bloc/JavaScript30-master/03%20-%20CSS%20Variables/imageFile, which naturally doesn't work.

You can still use custom properties, but as you need to set an HTML attribute, not a CSS property, the img rule is not needed. Give the img an ID instead, remove the double nesting of quotes from your custom property value as they're not needed (not even in JavaScript), and set the value of the src HTML attribute to the custom property value directly:

var customProps = window.getComputedStyle(document.documentElement);
var img = document.createElement('img');
img.id = 'imageFile';
img.alt = '';
img.src = customProps.getPropertyValue('--imageFile');
document.body.appendChild(img);
:root {
    --image: 1;
    --imageFile: https://source.unsplash.com/7bwQXzbF6KE/800x500;
}
<!--
The script should generate an img element that looks like this:
<img id="imageFile" alt="" src="https://source.unsplash.com/7bwQXzbF6KE/800x500">
-->

Some notes:

  • I'm leaving the --image custom property in although it's unused in this example. I presume it's meant to be appended to the URL as query string data — which shall be left as an exercise for the reader.

  • The ID is also technically unused in this example as I'm adding the element via JavaScript because it's not possible to mark up an img element without a non-empty src in a valid HTML document, but it will be useful when swapping out the image later as described in the question.

  • In case anyone is wondering if using JavaScript for this sort of thing is a hack, it's not — the spec itself explicitly lists JavaScript as a valid (even typical) use case for CSS custom properties.