3

I am trying to set an opacity on the body. However, I have run into an issue.

When setting the opacity on the body, only its content will be affected. The background is not affected by the opacity.

$("button").click(function() {
  $("body").toggleClass("opacity");
});
* {
  box-sizing: border-box;
}

body {
  background: linear-gradient(to right, #1BBCB1, #37B9E9);
  font-family: 'Arial';
  margin: 0;
  text-align: center;
  opacity: 1;
}

body.opacity {
  opacity: .3;
}

button {
  background-color: transparent;
  border: 2px solid #000;
  border-radius: 3px;
  margin-top: 15px;
  padding: 10px;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>The background gradient disapears when I set the opacity smaller then 1</p>
<button>Toggle opacity</button>

When doing the same on a div it works fine.

$("button").click(function() {
  $("div").toggleClass("opacity");
});
* {
  box-sizing: border-box;
}

body {
  font-family: 'Arial';
  margin: 0;
  text-align: center;
}

div {
  background: linear-gradient(to right, #1BBCB1, #37B9E9);
  opacity: 1;
}

div.opacity {
  opacity: .3;
}

button {
  background-color: transparent;
  border: 2px solid #000;
  border-radius: 3px;
  margin-top: 15px;
  padding: 10px;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
  <p>The background gradient disapears when I set the opacity smaller than 1</p>
  <button>Toggle opacity</button>
</div>

But I can't do this with a div. I have to set it on the body. How can I make the opacity affect the body's background?

P.S. Happy new year!

hungerstar
  • 21,206
  • 6
  • 50
  • 59
Red
  • 6,599
  • 9
  • 43
  • 85

3 Answers3

2

This is because the background of body is propagated to the html element (since this one doesn't have a background set) thus the html is also having the same background of the body. In your case, the opacity works fine with background also but you simply see the one of the html element.

Add a background to html to see the difference:

$("button").click(function() {
  $("body").toggleClass("opacity");
});
* {
  box-sizing: border-box;
}

html {
 background:red;
}

body {
  background: linear-gradient(to right, #1BBCB1, #37B9E9);
  font-family: 'Arial';
  margin: 0;
  text-align: center;
  opacity: 1;
}

body.opacity {
  opacity: .3;
}

button {
  background-color: transparent;
  border: 2px solid #000;
  border-radius: 3px;
  margin-top: 15px;
  padding: 10px;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>The background gradient disapears when I set the opacity smaller then 1</p>
<button>Toggle opacity</button>

Some usefull links to understand this behavior:

https://www.w3.org/TR/css-backgrounds-3/#special-backgrounds

https://css-tricks.com/just-one-of-those-weird-things-about-css-background-on-body/

https://stackoverflow.com/a/47998865/8620333

What's the meaning of "propagated to the viewport" in the CSS spec?

Temani Afif
  • 245,468
  • 26
  • 309
  • 415
  • 1
    Ah, indeed. I need to set a background on the `html` element. When setting `html {background: #fff;}` it works fine. Thanks for your insights! – Red Jan 02 '18 at 15:14
  • This is not inheritance. A parent doesn't inherit its child properties. This is propagation. See https://stackoverflow.com/questions/41886274/whats-the-meaning-of-propagated-to-the-viewport-in-the-css-spec/41886687#41886687 – BoltClock Jan 02 '18 at 16:22
  • @BoltClock well i didn't really meant the inheritance of CSS :) i used it in a general way to say that html take/get the same background, but i updated with the correct word and added your link also. – Temani Afif Jan 02 '18 at 18:46
0

Use rgba() for your linear gradient colors. That way you can set the transparency of the colors. By default have the alpha transparency value set to 1 (a.k.a. 100% opacity = no transparency). Then change the value to something less than 1 so the background becomes semi-transparent.

Note: This solution will only affect the background and not child elements. Of which, may or may not be the intended result.

$("button").click(function() {
  $("body").toggleClass("opacity");
});
* {
  box-sizing: border-box;
}

body {
  background: linear-gradient(to right, rgba(27, 188, 177, 1), rgba(55, 185, 233, 1));
  font-family: 'Arial';
  margin: 0;
  text-align: center;
  opacity: 1;
}

body.opacity {
  background: linear-gradient(to right, rgba(27, 188, 177, 0.3), rgba(55, 185, 233, 0.3));
}

button {
  background-color: transparent;
  border: 2px solid #000;
  border-radius: 3px;
  margin-top: 15px;
  padding: 10px;
  cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>The background gradient disapears when I set the opacity smaller than 1</p>
<button>Toggle opacity</button>
hungerstar
  • 21,206
  • 6
  • 50
  • 59
-2

As far as I know, the opacity property of the body does not exist. So you can obtain the desired effect with something like this:

https://codepen.io/calexandru/pen/YYQLmW

$( function () {
  $("#target").on("click", function() {
    $('body').addClass('opacity-container');
  });
} );
.opacity-container::after {
  /*CSS*/
  content: "";
  background: url(https://firebasestorage.googleapis.com/v0/b/betaproject-8a669.appspot.com/o/Quote-Generator%2F1.jpg?alt=media&token=4de18117-665f-4166-9111-4401af0cd555);
  opacity: 0.5;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  position: absolute;
  z-index: -1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<p>Click the button for background with opacity</p>
<button id="target">Click me</button>
hungerstar
  • 21,206
  • 6
  • 50
  • 59