user3700591
user3700591

Reputation: 215

Multiple background-color layers

I wondered if it was possible to create two background-colors for a div an overlay them.

I want a white background-color so that the content below this div doesn't shine through and another rgba() color painted over this white to create lighter colors per script.

Upvotes: 12

Views: 18508

Answers (5)

Rounin
Rounin

Reputation: 29493

To achieve multiple background colors in CSS, a common proposal is

  • Solid Color Gradients

But there is an alternative:

  • Solid Color background-images via SVG Data URIs

The working example below contains the following areas with the following background colors:

  • <main> - dark-gray
  • <section> - light-gray
  • <div class="circle"> - translucent red

In this set-up, we want to use the same theme-color for all the circles, rgba(255, 0, 0, 0.5) but we also want the circles inside the <section> to appear to have the same background-color as the circle outside <section>.

We can observe that, due to the application of the technique below to div.circle.does-not-blend - the rightmost of the two circles inside <section> - that circle ends up with the same apparent background-color as div.circle outside <section>.


The Approach

The approach is to give div.circle.does-not-blend:

  • the same initial background-color as <main>
  • an SVG Data URI background-image with the same translucent red background-color as the other .circle elements

The SVG background-image

The SVG Data URI background-image looks like this:

data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" style="background-color:rgba(255, 0, 0, 0.5);"%2F%3E

The Result

In the final result we see that the light-gray background-color of <section> does not bleed through and influence the final background-color of div.circle.does-not-blend


Working Example

main {
  display: flex;
  justify-content: space-around;
  align-items: center;
  height: 180px;
  padding: 0 9px;
  background-color: rgb(127, 127, 127);
  border: 1px solid rgb(0, 0, 0);
}

section {
  display: flex;
  justify-content: space-around;
  align-items: center;
  flex: 0 0 66%;
  background-color: rgb(191, 191, 191);
  height: 162px;
}

.circle {
  display: inline-block;
  width: 120px;
  height: 120px;
  color: rgb(255, 255, 255);
  text-align: center;
  line-height: 120px;
  background-color: rgb(255, 0, 0, 0.5);
  border-radius: 50%;
}

.circle.does-not-blend {
  background-color: rgb(127, 127, 127);
  background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" style="background-color:rgba(255, 0, 0, 0.5);"%2F%3E');
}
<main>
  <div class="circle"></div>
  <section>
    <div class="circle">Incorrect</div>
    <div class="circle does-not-blend">Correct</div>
  </section>
</main>

Upvotes: 1

Bram Vanroy
Bram Vanroy

Reputation: 28505

Though Adrift's answer is the way to go, you can also use pseudo elements for this.

body {
    background: white;
    position: relative;
}

body:before {
    content: "";
    position: absolute;
    top: 0;
    left; 0;
    width: 100%;
    height: 100%;
    background: rgba(220,14,120,0.5);
    z-index: 1;
}

/* Just to be sure, automatically set all elements to a higher z-index than the pseudo element */
body * {
    z-index: 2;
    position: relative;
}

Here is a fiddle.

However, this is not production friendly:

  • Setting position relative on body and all other elements when not necessary
  • Setting unnecessary z-index on all elements

The only upside this method has, is that it doesn't use gradients which, from a semantic standpoint, is more logical.

Upvotes: 4

WDMTech
WDMTech

Reputation: 173

You can't define two background-colors for one element, but you could overlay one coloured element on top of a white one in order to get a blending effect, while blocking out anything below them:

JSFiddle

HTML

<div class="one">
    <div class="two"></div>
</div>

CSS

div {
    width: 100px;
    height: 100px;
}

.one {
    background-color: #fff;
}
.two {
    top: 0;
    left: 0;
    background-color: rgba(0,0,255,0.2);
}

Upvotes: 1

Adrift
Adrift

Reputation: 59819

Without understanding why you want this, it can be done by using solid color gradients: fiddle.

body {
    background: linear-gradient(rgba(220,14,120,0.5), rgba(220,14,120,0.5)),
                linear-gradient(white, white); /* first bg is on top of this */

}

Upvotes: 29

Max Baldwin
Max Baldwin

Reputation: 3472

To answer your question, yes there is a way. You can use a background image and a background color on the same div. Check out this SOF post.

Although I would consider a different method like this:

Structure:

<div class="parent">
    <div class="white"></div>
    <div class="color"></div>
</div>

CSS:

.parent {
    position: relative:
}
.white, .color {
    position:absolute;
    top: 0px;
    left: 0px;
}
.white {
    z-index: 9998;
}
.color {
    z-index: 9999;
}

You can mess around with the details here, but the overall idea is that your layer the divs on top of each other. The div with the higher z-index will be on top. Change their colors accordingly. The parent div being relative will keep the absolute divs inside of that container.

Upvotes: 0

Related Questions