This is the sixth day of my participation in the August More text Challenge. For details, see: August More Text Challenge

We have a set of radio buttons to switch between different background colors. The main structure is as follows:

<form class="controls">
  <input type="radio" name="color" value="night-fade" checked />
  <input type="radio" name="color" value="warm-flame" />
  <input type="radio" name="color" value="spring-warmth" />
</form>
Copy the code

In the past, we could use JavaScript to detect when a user was interacting with a radio button and attach a class accordingly.

const bgColor = document.querySelector('body')
const controls = document.querySelector('.controls')

let currentClass = 'night-fade'

const onChange = e= > {
  if(! e.target.value || ! e.target.checked)return

  if (bgColor.classList.contains(currentClass)) {
    bgColor.classList.replace(currentClass, e.target.value)
  } else {
    bgColor.classList.add(e.target.value)
  }

  currentClass = e.target.value
}

controls.addEventListener('change', onChange)
Copy the code

Then, we add a CSS background-image for each class to switch the background:

body {
  background-image: linear-gradient(to top, #a18cd1 0%.#fbc2eb 100%);
}

body.warm-flame {
  background-image: linear-gradient(45deg.#ff9a9e 0%.#fad0c4 99%.#fad0c4 100%);
}

body.spring-warmth {
  background-image: linear-gradient(to top, #fad0c4 0%.#ffd1ff 100%);
}
Copy the code

The effect is as follows:

However, now we have a better option: CSS custom properties (also known as variables). It makes your CSS and JS look more concise and convenient, and we use it to do the same.

Custom properties

We can assign a custom property to each of the following background color values globally, i.e., root:

:root {
  --bg-color-night-fade: linear-gradient(to top, #a18cd1 0%.#fbc2eb 100%);
  --bg-color-warm-flame: linear-gradient(45deg.#ff9a9e 0%.#fad0c4 99%.#fad0c4 100%);
  --bg-color-spring-warmth: linear-gradient(to top, #fad0c4 0%.#ffd1ff 100%);
}
Copy the code

Next, we define a new –bg-color variable to specify an initial background color within the local scope of the element to which the background color is to be applied (in this case, the body). This will be used to dynamically change the –bg-color value when the radio button changes, so that background-image and –bg-color are updated simultaneously.

We use the first –bg-color-night-fade variable as the initial value corresponding to the first radio button option:

body {	
  --bg-color: var(--bg-color-night-fade);
  background-image: var(--bg-color);
}
Copy the code

Finally, listen for change on the radio button under the form. In the onChange event handler, we update the value of bc-color with the custom property corresponding to the selected radio.

const bgColor = document.querySelector('body')
const controls = document.querySelector('.controls')

const onChange = (e) = > {
  if(! e.target.value || ! e.target.checked)return
  
  bgColor.style.setProperty('--bg-color'.`var(--bg-color-${e.target.value}) `)
}

controls.addEventListener('change', onChange)
Copy the code

You can check it out here at 👉.