How to Apply CSS Opacity to Background Color Only?

The CSS opacity property is a great way to set a low opacity on HTML elements making the entire element semi-transparent including all of its children. But what if we only wish to set the opacity on the background color whilst keeping the content (such as text and images) opaque? Here are a few ways to accomplish that:

Set Background Color Opacity Using Alpha Channel Color Notations

We can use the following CSS3 alpha channel color functional notations to set the background color to a lower opacity:

Using the RGBA (Red-Green-Blue-Alpha) Model:

Syntax:

background-color: rgba(red, green, blue, alpha);

Where the values of each color in RGB can be an integer between 0-255 or a percentage value from 0-100%, and the value of Alpha can be a number between 0-1.

Examples:

rgba(0, 0, 255, 0)      /* transparent */
rgba(0, 0, 255, 0.5)    /* 50% opaque blue */
rgba(0, 0, 255, 1)      /* fully opaque blue */

Using the HSLA (Hue-Saturation-Lightness-Alpha) Model:

Syntax:

background-color: hsla(hue, saturation, lightness, alpha);

Where the possible values of the HSLA color notation are:

  • Hue: specified in degrees (imagine a color wheel) where:
    • 0° – red
    • 60° – yellow
    • 120° – green
    • 180° – turquoise
    • 240° – blue
    • 300° – pink
    • 360° – red
  • Saturation: specified in percentage where 0% is completely desaturated (or gray) and 100% is fully saturated (or full color).
  • Lightness: specified in percentage where 0% is completely dark (or black) and 100% is completely light (or white).
  • Alpha: a number between 0-1 where 0 is fully transparent and 1 is fully opaque.

Examples:

hsla(240, 100%, 50%, 0)     /* transparent */
hsla(240, 100%, 50%, 0.5)   /* 50% opaque blue */
hsla(240, 100%, 50%, 1)     /* fully opaque blue */

Use a Lower Opacity CSS Pseudo Element to Create a Colored Background Layer

Let's suppose you have the following elements; a content child element nested inside a parent element:

<div id="parent">
  <div id="child">
    Text
  </div>
</div>

With a structure like that, you can create a background layer (having no content) via CSS pseudo elements like so:

#parent::after { content: ''; }

Now you can make the background layer the same size as the parent div and position it relative to the parent like so:

#parent { height: 45px; position: relative; }
#parent::after {
	content: ''; 
	width: 100%; 
	height: 100%;
	background-color: pink; 
	opacity: 0.5; 
	position: absolute; 
	top: 0; 
	left: 0;
	z-index: -1;
}

You should now see a pink colored background layer with an opacity of 50% that only applies to the background color and not the content.

Following is a quick explanation of how the generated content (our background layer) is styled:

  • To generate empty/invisible content we can simply set the content property's value to an empty string or a space character.
  • Setting width and height to 100% ensures the generated content is of the same size as the parent element.
  • Setting a lower opacity makes the background layer transparent.
  • position: relative on the parent element and position: absolute on the generated content ensures the generated content is positioned relative to the parent.
  • Setting left: 0 and top: 0 ensures the generated content is positioned to the top left edge of the parent element.
  • Setting a negative z-index value ensures the generated content recedes to the background and all child element content appears above it.

If the parent element has a background color of its own, then you can set a positive z-index value on the generated content (the background layer) and a higher z-index value on the child element along with relative positioning like so:

#parent { height: 45px; background-color: yellow; position: relative; }
#parent::after {
	content: ''; 
	width: 100%; 
	height: 100%; 
	background-color: pink; 
	opacity: 0.5; 
	position: absolute; 
	top: 0; 
	left: 0; 
	z-index: 1;
}
#child {position: relative; z-index: 2;}

This post was published (and was last revised ) by Daniyal Hamid. Daniyal currently works as the Head of Engineering in Germany and has 20+ years of experience in software engineering, design and marketing. Please show your love and support by sharing this post.