3

I have this in my CSS:

.body {
    width: 150px;
    height: 40px;
    padding: 20px;
    background-color: rgba(255,0,0,1);
    text-align: center;
    border: 1px solid black;
    border-top-left-radius: 15px;
    border-top-right-radius: 15px;
    display: block;
    top: 50px;
    font-weight: bold;
    font-size: 25px;
}

And I want to change the background-color's opacity (alpha) when the user clicks on a button:

<button onclick="lessColour()">-Colour</button>

How can I create this lessColour() function so that everytime the user clicks on the button, the background-color's alpha is decreased 0.1?

BTW, I have to do that with 3 different elements.

Danziger
  • 19,628
  • 4
  • 53
  • 83
Chokitu
  • 57
  • 1
  • 7
  • Do you mean you need to change the opacity of the `body` from 3 different buttons or change the opacity of 3 different elements? – Danziger Jan 31 '18 at 02:36
  • So, I have 1 div with 3 different elements. Body, Top and Circle. I need to make a script that when I click this button, the background opacity of those elements (objects) is going to decrease by 0.1 in a 0-1 scale. – Chokitu Jan 31 '18 at 02:37
  • Do you have to detect the current colour of the element or is it always going to be _red_? – Phil Jan 31 '18 at 02:43
  • Body is red, Top is Blue and Circle is black – Chokitu Jan 31 '18 at 02:45
  • I only need to decrease the opacity each time someone presses the button. I'll also have a button to increase the opacity. – Chokitu Jan 31 '18 at 02:45
  • 1
    So... If it started 255,0,0,1 and I press the button 1 time is going to turn 255,0,0,0.9 and if I press it again 255,0,0,0.8, but If I press the other button is going to turn 255,0,0,0.9 again. – Chokitu Jan 31 '18 at 02:46
  • 2
    So, have you tried writing this code yourself. You seem to know exactly what needs to happen. Why don't you do some research on how to alter an element's background color using JavaScript, try something out, then ask a question. – Heretic Monkey Jan 31 '18 at 02:52
  • Possible duplicate of [How do I change the background color with JavaScript?](https://stackoverflow.com/questions/197748/how-do-i-change-the-background-color-with-javascript) – Heretic Monkey Jan 31 '18 at 02:53
  • I've been trying but it's not really working – Chokitu Jan 31 '18 at 02:57

5 Answers5

5

You need to create a function that takes two arguments:

  • The element (or elements) whose background-color's opacity you want to change, so that you can do it in multiple elements at once.

  • The amount you want to change alpha (increase if positive or decrease if negative).

In order to get the current alpha value you need to:

  1. Use getComputedStyle and getPropertyValue to get the current background-color value.

  2. Parse that value to get just the alpha component.

  3. Update the element's background-color with element.style.backgroundColor.

Altogether, it will look like this:

// First, get all your elements:

const a = document.getElementById('a');
const b = document.getElementById('b');
const c = document.getElementById('c');


// And the buttons to update them:

const decreaseA = document.getElementById('decrease-a');
const decreaseAB = document.getElementById('decrease-ab');
const decreaseABC = document.getElementById('decrease-abc');

const increaseA = document.getElementById('increase-a');
const increaseAB = document.getElementById('increase-ab');
const increaseABC = document.getElementById('increase-abc');

const decreaseAll = document.getElementById('decrease-all');
const increaseAll = document.getElementById('increase-all');


// Define your function:

function updateColor(elements, change) {

  // Make sure elements is always an Array, so that you can call the
  // function with either an Array of elements or a single one (without
  // having to wrap it in an Array yourself.
  
  elements = Array.isArray(elements) ? elements : [elements];
 
  // Process all elements:
 
  elements.forEach(element => {
    // Get the current background-color value:
    const value = getComputedStyle(element).getPropertyValue("background-color");
    
    // Get all color components (alpha may not be there if = 1):
    const parts = value.match(/[\d.]+/g);
    
    // If alpha is not there, add it:
    if (parts.length === 3) {
      parts.push(1);
    }
    
    // Modify alpha:
    parts[3] = Math.min(1, Math.max(0, parseFloat(parts[3]) + change));
    
    // Set the element's text to be the current alpha value (just for the example):
    element.innerText = parts[3].toFixed(2);
    
    // Apply new value:
    element.style.backgroundColor = `rgba(${ parts.join(',') })`;
  });
}


// Add event handlers for the buttons that will call the function with the right params:

decreaseA.onclick = () => updateColor(a, -0.1);
decreaseAB.onclick = () => updateColor(b, -0.1);
decreaseABC.onclick = () => updateColor(c, -0.1);

increaseA.onclick = () => updateColor(a, 0.1);
increaseAB.onclick = () => updateColor(b, 0.1);
increaseABC.onclick = () => updateColor(c, 0.1);

decreaseAll.onclick = () => updateColor([a, b, c] , -0.1);
increaseAll.onclick = () => updateColor([a, b, c], 0.1);


// Set the initial text inside each sample without modifying the color (just for the example):

updateColor([a, b, c] , 0);
body {
  margin: 0;
  font-family: monospace;
}

.samples {
  overflow: hidden;
}

.buttons {
  overflow: hidden;
  border: 2px solid #FFF;
}

span {
  float: left;
  width: 33.33333333%;
  line-height: 100px;
  height: 100px;
  text-align: center;
}

button {
  float: left;
  width: 33.33333333%;
  background: #000;
  color: #FFF;
  border: none;
  line-height: 32px;
  font-family: monospace;
  outline: none;
  border: 2px solid #FFF;
}

#decrease-all,
#increase-all {
  width: 50%;
}

#a { background: rgba(255, 0, 0, 1); }
#b { background: rgba(0, 255, 0, 1); }
#c { background: rgba(0, 0, 255, 1); }
<div class="samples">
  <span id="a"></span>
  <span id="b"></span>
  <span id="c"></span>
</div>

<div class="buttons">
  <button id="increase-a">INCREASE A</button>
  <button id="increase-ab">INCREASE B</button>
  <button id="increase-abc">INCREASE C</button>
  <button id="decrease-a">REDUCE A</button>
  <button id="decrease-ab">REDUCE B</button>
  <button id="decrease-abc">REDUCE C</button>
  <button id="increase-all">INCREASE ALL</button>
  <button id="decrease-all">REDUCE ALL</button>
</div>
Danziger
  • 19,628
  • 4
  • 53
  • 83
  • Still couldn't make it, let me try again – Chokitu Jan 31 '18 at 03:19
  • The elemnts are already with the backgrounds specified on each one of them in CSS For example: `.body { width: 150px; height: 40px; padding: 20px; background-color: rgba(255,0,0,1); text-align: center; border: 1px solid black; border-top-left-radius: 15px; border-top-right-radius: 15px; display: block; top: 50px; font-weight: bold; font-size: 25px; }` – Chokitu Jan 31 '18 at 03:24
  • Like in the example. All three `#a`, `#b` and `#c` elements already have an initial background color defined in CSS using the `background` property. I don't see the issue. – Danziger Jan 31 '18 at 03:33
  • Yep, I can't really change this structure. – Chokitu Jan 31 '18 at 03:37
  • Still, don't know what the problem is. Just call `updateColor` with whatever element you want to update: `updateColor(document.body, -0.1)`, `updateColor(Array.from(document.querySelectorAll('.circle')), -0.1)`, ... – Danziger Jan 31 '18 at 03:42
  • 1
    The only situation I can imagine where this might not work is if you have some `background-color` set using `!important` in your stylesheets. In that case, just replace this line: ``element.style.backgroundColor = `rgba(${ parts.join(',') })`;`` with this other one: ``element.style.backgroundColor = `rgba(${ parts.join(',') }) !important`;``. – Danziger Jan 31 '18 at 03:44
1

Hope it helps

function lessColour() {
  var elements = document.getElementsByClassName("opacityChange");
  var element, colors;
  for (i = 0; i < elements.length; i++) {
    element = getComputedStyle(elements[i]).getPropertyValue('background-color');
    //Get values
    colors = element.split(', ');
    colors[0] = parseFloat(colors[0].split('(')[1]);
    colors[1] = parseFloat(colors[1]);
    colors[2] = parseFloat(colors[2]);
    //Correct missing alpha
    if (colors.length == 3)
      colors[3] = 1;
    //Apply new style
    colors[3] = parseFloat(colors[3]) - 0.1;
    colors = 'rgba(' + colors.join(',') + ')';
    elements[i].style.backgroundColor = colors;
  }

}
.body {
  width: 150px;
  height: 40px;
  padding: 20px;
  background-color: rgba(255, 0, 0, 1);
  text-align: center;
  border: 1px solid black;
  border-top-left-radius: 15px;
  border-top-right-radius: 15px;
  display: block;
  top: 50px;
  font-weight: bold;
  font-size: 25px;
}

.circle {
  /*float: left;*/
  margin: 0 auto;
  height: 35px;
  width: 35px;
  border: 1px solid black;
  border-radius: 100px;
  background: rgba(0, 0, 0, 1);
  display: inline-block;
  margin-left: 10px;
}

.top {
  margin-left: 72px;
  height: 35px;
  width: 50px;
  border: 1px solid black;
  border-bottom-width: 2px;
  border-top-left-radius: 110px;
  border-top-right-radius: 110px;
  background: rgba(0, 0, 255, 1);
  display: block;
}
<div class="main">
  <div class="top opacityChange"></div>
  <div class="body opacityChange"></div>
  <div class="circle opacityChange"></div>
  <button onclick="lessColour()">-Colour</button>
</div>
Gerardo BLANCO
  • 5,590
  • 1
  • 16
  • 35
  • The elemnts are already with the backgrounds specified on each one of them in CSS For example: `.body { width: 150px; height: 40px; padding: 20px; background-color: rgba(255,0,0,1); text-align: center; border: 1px solid black; border-top-left-radius: 15px; border-top-right-radius: 15px; display: block; top: 50px; font-weight: bold; font-size: 25px; }` – Chokitu Jan 31 '18 at 03:29
  • `.circle { /*float: left;*/ margin: 0 auto; height: 35px; width: 35px; border: 1px solid black; border-radius: 100px; background: rgba(0,0,0,1); display: inline-block; margin-left: 10px; }` – Chokitu Jan 31 '18 at 03:34
  • 1
    If the initial `background-color`'s `alpha` is `1`, `getComputedStyle(element).getPropertyValue('background-color')` will return `rgb(255, 0, 0)` instead of `rgba(255, 0, 0, 1)`, so you code will not work, as it will try to assign `rgb(255,0,0),0.9)` as the new `backgroundColor`. You are parsing the current value incorrectly. – Danziger Jan 31 '18 at 03:34
  • `.top { margin-left: 72px; height: 35px; width: 50px; border: 1px solid black; border-bottom-width: 2px; border-top-left-radius: 110px; border-top-right-radius: 110px; background:rgba(0,0,255,1); display: block; }` – Chokitu Jan 31 '18 at 03:34
  • I can't really change this structure. – Chokitu Jan 31 '18 at 03:35
  • Hi @Chokitu. Im just back online. I will get to help you as soon as possible. – Gerardo BLANCO Jan 31 '18 at 14:33
  • @Danziger thats why i have ``if (colors.length == 3) colors.push(1);`` – Gerardo BLANCO Jan 31 '18 at 15:25
  • @Chokitu so i added your css styles. Did my edit help or did you run into a problem? – Gerardo BLANCO Jan 31 '18 at 15:29
  • @GerardoBLANCO Take another look my comment and to your code (which is not working). The issue I pointed out has to do with how you split the color components (`.split(', ')`), not with the `alpha` channel not being present. – Danziger Jan 31 '18 at 19:40
  • @Chokitu Did my edit help or did you run into a problem? – Gerardo BLANCO Jan 31 '18 at 22:36
0

You can encapsulate a function that uses getComputedStyle to guess the alpha.

const setAlpha = (element, a) => {
   const current_color = getComputedStyle(element).getPropertyValue("background-color");
   const match = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[\.\d+]*)*\)/g.exec(current_color);
   const a = a > 1 ? (a / 100) : a;
   element.style.backgroundColor = "rgba(" + [match[1],match[2],match[3],a].join(',') +")";
}

setAlpha(document.getElementById('elementName'), 0.1);

If you want to know the previous alpha (which value you can use to decrease/increase):

const getBgAlpha = (element) => {
       const current_color = getComputedStyle(element).getPropertyValue("background-color");
       const match = /rgba?\((\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(,\s*\d+[\.\d+]*)*\)/g.exec(current_color);
       return match[4];
}
R01010010
  • 5,670
  • 11
  • 47
  • 77
0

My solution below reduces the alpha value for the background, but you can apply the same approach to any element. You can also create a function that does the opposite (i.e., to darken the background).

let alphaValue = 1;
let rgbValue = `rgb(22,50,122,${alphaValue}`;

document.body.style.backgroundColor = rgbValue;

const button = document.getElementById('opacBtn');

button.addEventListener('click', lightenElement);

function lightenElement(e){
  if(Math.round(alphaValue * 100) / 100 == '0') return;
  
  else{
   alphaValue -= 0.1; 
   rgbValue = `rgb(22,50,122,${alphaValue}`;
   document.body.style.backgroundColor = rgbValue;
  }
}
<button id="opacBtn">Lighten</button>

Note: I noticed that even if the alphaValue was negative the background color rgba would still have an alpha value of 0 (it cannot be negative). However, if you decided to add a button to increase the alpha, and the current alpha value was negative, you would need to keep clicking it until the value becomes positive to darken the background. That's why I added the if statement in the function to avoid that.

gamolly
  • 1
  • 1
-1
function lessColour(){
   document.getElementById("butn1").style.backgroundColor = "rgba(0,0,0,0.1)";
}
Minal Chauhan
  • 6,025
  • 8
  • 21
  • 41