Random Background Color onHover/onClick?

Hey guys,

I have an idea for a project I want to build in Webflow (not build yet so I cannot provide a link :pray:t3:)

Ideally I also would need the possibility to add the following to Webflow´s element trigger interactions:

OnHover and/or onClick the background color of an element should be chosen randomly from an array of predefined colours.

Any ideas how I could achieve that?
(not super savvy in JS unfortunately ;-))

Thanks in advance!

Cheers,
Manuel

Stackoverflow is a great resource for discovering ways to solve a problem like this. Just need to do some research. You can always hire a freelancer to write your code for you.

I don’t think you can achieve that with Webflow IX2.
A simple JS code will do the trick, though.

Try this one.

  • I make sure the random color it gets is not the same as a previous one
  • Easily change the config value to match your need
  • It’ll work with multiple elements.
  • nice encapsulated code :slight_smile:
// just change all the value here.
            const PREDEFINED_COLOR = [ "#555","#888","#999","#345","#876"]
            const YOUR_TARGET_CLASS = "target-class-that-need-to-change-the-color"
   
// you can ignore all the code below.         
            const changeBgColorOnClick = (function () {
                  const config  = {
                        targetClass : "target-class-that-need-to-change-the-color",
                        colorList : [ "#555","#888","#999","#345","#876"]
                  }
                  const init = (newConfig)=>{
                        updateConfig(newConfig)
                        let currentColorIndex = 0
                        $(`.${config.targetClass}`).on('click',(e)=>{
                              let $target = getCorrectTargetNotItsChild(e.target)
                              currentColorIndex = getRandomInt(config.colorList.length,currentColorIndex)
                              $target.css("background-color",config.colorList[currentColorIndex])
                        })
                  }
                  function updateConfig(newConfig) {
                        Object.assign(config,newConfig)
                        
                  }
                  function getCorrectTargetNotItsChild(target) {
                        let $target = $(target)
                        if(!$target.hasClass(`.${config.targetClass}`)){
                              $target.parents(`.${config.targetClass}`)
                        }
                        return $target
                  }
                  function getRandomInt(max,not) {
                        const value = Math.floor(Math.random() * max);
                        if(value === not){
                              return getRandomInt(max,not)
                        }
                        return value
                  }

                  return {init}
            })()
            
            changeBgColorOnClick.init({
                  colorList : PREDEFINED_COLOR,
                  targetClass : YOUR_TARGET_CLASS
            })
1 Like

Hey Smith.S!

Wow, you are awesome! This looks very promising!!!
Thanks a lot for putting it together, I appreciate this very much!
I will try it out for sure and then let you know how it works!

Thanks again – have a great day!
Manuel

Hi webdev,

thanks for your comment – you are absolutely correct!

However, since I am planning to build the project in webflow and there´s also a “Custom Code” section here in the forum, why not also try my best here? :wink: I was actually also wondering if there might be a possibility within the webflow interactions even and I am just not aware of it, this I would not find out anywhere else but here.

(… and no worries, I am not just looking for other people´s knowledge, I love sharing all I know too, at the end we learn best through sharing anyway.)

Cheers,
Manuel

PS: side note to the webflow developers – it might be somehow complicated but: the possibility for random values/behaviour within the interactions would bring the interactions (which are already sooo great!) to a whole new level! :slight_smile:

hi @ManuelE here another approach how you can do that.

const elements = [...document.querySelectorAll(".random-bg-elm")];
const colors = ["#268492", "#6948f0", "#fec4c2", "#87a3c2"];

elements.forEach((elm) => {
  elm.addEventListener("click", () => {
    let rndColor = colors[Math.floor(Math.random() * colors.length)];
    elm.style.background = rndColor;
  });
});
1 Like

Hi Smith.S & Stan!

Thanks again to you guys. Both solutions work perfectly!

However, I have realized that I actually would need something a bit more difficult :roll_eyes:
Because the color should actually change only every 2nd time (is there something like “second click” I could address in JS too?).

Otherwise this comes with much more complexity so please don´t start writing code for me again! I have to figure out another solution by myself or will change the concept of this a bit.

… just if you are interested what I want to achive, this is the project:
https://kokomm-wirkzeuge.webflow.io/

It´s basically a board with buttons. At the end they can be all turned around and reveal a message/answer.
Up to now only the button “Sympathiezauber” (left/mid area) is working, everything else is dummy-background. Ideally the button should have another background color every time they get turned around but when I turn it back (2nd click) it should keep the color. — huuuh. (I am aware that right now it´s not changing the color at all - it´s just to show the turn around effect right now)

hi @ManuelE here is another snippet that limit color change only on first click, you can take it further from here. :wink:

elements.forEach((elm) => {
  let clicksNr = 0; // start number of clicks
  elm.addEventListener("click", () => {
    // limit action only for first click
    if (clicksNr === 0) {
      // do your stuff
      let rndColor = colors[Math.floor(Math.random() * colors.length)];
      elm.style.background = rndColor;
      // here you can grab front of your element and assign color  
    } else {
      // if number clicks is bigger than 0 return (do nothing)
      return;
    }
   // add 1 to counter
    clicksNr += 1;
  });
});

EDIT: if you need trigger action for every even attempt you can use modulo operator in if condition. :wink:

if (clicksNr % 2){
  // do your stuff
}

Hey Stan,

Hours later … :joy: I think I got it now!
Thanks for your effort and guiding me in the right direction!!!

const elements = [...document.querySelectorAll(".color-change")];
const colors = ["#268492", "#6948f0", "#fec4c2", "#87a3c2"];

elements.forEach((elm) => {
  let clicksNr = 0; // start number of clicks
  elm.addEventListener("click", () => {
    if (clicksNr % 2 === 0) {  // check if number is even
    // random color change
    let rndColor = colors[Math.floor(Math.random() * colors.length)];
    elm.style.background = rndColor;
    // +1 to counter
    clicksNr++ 
    } else {
    // if number is odd only +1 to counter
    clicksNr++      
    }
  });

});

If you are interested, you can see it here:
https://jsfiddle.net/2p3tsved/2/

Not so complicated at the end! But unthinkable if I don´t know where to start :wink:

Thanks again!

Cheers,
Manuel

1 Like

Hi Stan,

actually, I have one more (and last – I promise ;-)) question:

I have realized that I have to target a children element, not the element itself.
I did some research and thought I could do this with something like that:

elm.children( ".nested-element" ).style.background = rndColor;

But it doesn´t work. What am I doing wrong? :upside_down_face:

THANKS A LOT! :pray:t3:

hi @ManuelE

const childElm = elm.children[0]; //get first child of parent element
childElm.style.background= rndColor;

:pray:t3: :pray:t3: :pray:t3:

Works perfectly!