Color and Background

  • Revision slug: Useful_CSS_tips/Color_and_Background
  • Revision title: Color and Background
  • Revision id: 135326
  • Created:
  • Creator: Jürgen Jeka
  • Is current revision? No
  • Comment 32 words added

Revision Content

{{ outdated(' IE7 supports PNG images with ALPHA channel; IE8 changed the syntax for the "filter" property.') }}

Translucent background

Even if {{ cssxref("opacity") }} (translucency) is a style property defined in CSS-3 specification CSS3 Color Module, chapter 3.2, browsers already support it. According to the spec, opacity can be thought of conceptually as a postprocessing operation, so the selected grade of transparency is applied to all its content.

It means that, if you have a DIV with text inside, it is impossible to have opaque text on translucent background, because if you set the opacity property for the container DIV, all its content inherits the transparency and it is impossible to override it... by normal means.

If you try this example code, you will find that opaquetext is not opaque, it inherited the parent opacity attribute and style redefine is discarded, for the reason explained above.

<div id="container">
    <div id="opaquetext">
      This is a normal text
      on a translucent background
    </div>
</div>
#container {
   background-color: #ffffff;  /* the background          */
   filter:alpha(opacity=50);   /* Internet Explorer       */
   -moz-opacity:0.5;           /* Mozilla 1.6 and below   */
   opacity: 0.5;               /* newer Mozilla and CSS-3 */
}
#opaquetext {
   filter:alpha(opacity=100);  /* discarded */
   -moz-opacity:1.0;           /* discarded */
   opacity: 1.0;               /* discarded */
}

In fact there are two workarounds to obtain this effect and both are cross-browser (take into account also the exotic Internet Explorer behaviour):

  • Rearranged hierarchy : Since the main problem is that the text to be made opaque is contained into the translucent box, put it out of that box.
  • PNG image with ALPHA channel : Use a translucent background image.

Rearranged hierarchy

As suggested before, this workaround is based on a rearranged DIV hierarchy. Since all descendants of the translucent DIV inherit the parent's opacity attribute, the key is to use separated DIVs for the translucent background and the opaque text, placed at the same hierarchy level, not the second inside the first. Both are contained in a parent DIV to be positioned absolutely or floating.

<div id="container">

   <div id="opaquetext">
      This is a normal text
      on a translucent background
   </div>

   <div id="translucentbkg">
       
   </div>

</div>

In order to place the opaquetext over the translucentbkg, absolute positioning and z-index has to be used for the text DIV. Moreover, width and height of the two DIVs have to match, so they have to be explicitly declared.

#container {
   position: absolute;
   top: 100px; left: 400px;         /* place it where you want     */
}

#translucentbkg {
   width: 250px; height: 100px;     /* to match DIVs size          */
   background-color: #ffffff;       /* the background              */
   filter:alpha(opacity=50);
   -moz-opacity:0.5;
   opacity: 0.5;
}

#opaquetext {
   width: 250px; height: 100px;     /* to match DIVs size          */
   background-color: transparent;   /* transparent background      */
   position: absolute;              /* absolute positioning        */
   z-index: 2;                      /* place it over the other DIV */
}

How to remove the pre-defined fixed height

Sometimes having a pre-defined height is a problem, because contained text length (and images) is not known. It is still possible to avoid a fixed height, with further workarounds. The simplest one is to let the opaquetext DIV extend as necessary, then use JavaScript to se translucentbkg height with the same value. But this is not a pure CSS solution.

If you want to use CSS only, the solution is quite simple, you have only to repeat content of opaquetext also in translucentbkg DIV. This is not elegant, but extremely easy to implement, also in dynamic generated pages.

<div id="container">

   <div id="opaquetext">
      This is a normal text
      on a translucent background
   </div>

   <div id="translucentbkg">
      This is a normal text
      on a translucent background
   </div>

</div>

PNG image with ALPHA channel

This solution still uses the parent-child hierarchy, but actually it is an hybrid technique, because it implements the translucent background with totally different means across different browsers.

  • Mozilla : Translucency is implemented using a PNG image with ALPHA channel as container's background image.
  • Internet Explorer : Since IE-6 (and below) does not support PNG images with ALPHA channel, translucency is implemented with the ALPHA filter of the previous example, but inheritance of the descendants is overridden thanks to a non-standard IE behaviour.

Notes and drawbacks with this solution:

  • Another containing DIV has to be nested to have a working effect on Internet Explorer.
  • Parent DIV is absolutely positioned and the new containing DIV with translucent background has to be a normal DIV. The text DIV has to be relatively positioned in order to override the translucency inheritance.
  • A few CSS hacks have to used, in order to have different working CSS rules across the two browsers.
  • A specific PNG image has to be generated, with the wanted grade of transparency.
<div id="container">
  <div id="translucentbkg">
    <div id="opaquetext">
      This is a normal text
      on a translucent background
    </div>
  </div>  
</div>
#container {
   position: absolute;
   width: 250px;
   top: 400px;  left: 100px;
   }

#translucentbkg {
   width: 250px;
   background-image: url(transparent.png) !important;  /* Mozilla only */
   background-color: transparent !important;           /* Mozilla only */
   background-image: none;                             /* IE only */
   background-color: #ffffff;                          /* IE only */
   filter:alpha(opacity=50);                           /* IE only */
   }

#opaquetext { position: relative; }

{{ languages( { "fr": "fr/Astuces_CSS/Couleurs_et_fonds" } ) }}

Revision Source

<p>{{ outdated(' IE7 supports PNG images with ALPHA channel; IE8 changed the syntax for the "filter" property.') }}</p>
<h3>Translucent background</h3>
<p>Even if {{ cssxref("opacity") }} (translucency) is a style property defined in CSS-3 specification <a class="external" href="http://www.w3.org/TR/css3-color/#transparency" title="http://www.w3.org/TR/css3-color/#transparency">CSS3 Color Module, chapter 3.2</a>, browsers already support it. According to the spec, <em> opacity can be thought of conceptually as a postprocessing operation</em>, so the selected grade of transparency is applied to all its content.</p>
<p>It means that, if you have a DIV with text inside, it is impossible to have <strong>opaque text on translucent background</strong>, because if you set the <em>opacity</em> property for the container DIV, all its content inherits the transparency and it is impossible to override it... by normal means.</p>
<p>If you try this example code, you will find that <strong>opaquetext</strong> is not opaque, it inherited the parent opacity attribute and style redefine is discarded, for the reason explained above.</p>
<pre>&lt;div id="container"&gt;
    &lt;div id="opaquetext"&gt;
      This is a normal text
      on a translucent background
    &lt;/div&gt;
&lt;/div&gt;
</pre>
<pre>#container {
   background-color: #ffffff;  /* the background          */
   filter:alpha(opacity=50);   /* Internet Explorer       */
   -moz-opacity:0.5;           /* Mozilla 1.6 and below   */
   opacity: 0.5;               /* newer Mozilla and CSS-3 */
}
#opaquetext {
   filter:alpha(opacity=100);  /* discarded */
   -moz-opacity:1.0;           /* discarded */
   opacity: 1.0;               /* discarded */
}
</pre>
<p>In fact there are two workarounds to obtain this effect and both are cross-browser (take into account also the <em>exotic</em> Internet Explorer behaviour):</p>
<ul> <li><strong>Rearranged hierarchy</strong> : Since the main problem is that the text to be made opaque is contained into the translucent box, put it out of that box.</li>
</ul>
<ul> <li><strong>PNG image with ALPHA channel</strong> : Use a translucent background image.</li>
</ul>
<h4>Rearranged hierarchy</h4>
<p>As suggested before, this workaround is based on a rearranged DIV hierarchy. Since all descendants of the translucent DIV inherit the parent's opacity attribute, the key is to use separated DIVs for the translucent background and the opaque text, placed at the same hierarchy level, not the second inside the first. Both are contained in a parent DIV to be positioned absolutely or floating.</p>
<pre>&lt;div id="container"&gt;

   &lt;div id="opaquetext"&gt;
      This is a normal text
      on a translucent background
   &lt;/div&gt;

   &lt;div id="translucentbkg"&gt;
       
   &lt;/div&gt;

&lt;/div&gt;
</pre>
<p>In order to place the <strong>opaquetext</strong> over the <strong>translucentbkg</strong>, absolute positioning and <em>z-index</em> has to be used for the text DIV. Moreover, width and height of the two DIVs have to match, so they have to be explicitly declared.</p>
<pre>#container {
   position: absolute;
   top: 100px; left: 400px;         /* place it where you want     */
}

#translucentbkg {
   width: 250px; height: 100px;     /* to match DIVs size          */
   background-color: #ffffff;       /* the background              */
   filter:alpha(opacity=50);
   -moz-opacity:0.5;
   opacity: 0.5;
}

#opaquetext {
   width: 250px; height: 100px;     /* to match DIVs size          */
   background-color: transparent;   /* transparent background      */
   position: absolute;              /* absolute positioning        */
   z-index: 2;                      /* place it over the other DIV */
}
</pre>
<p><strong>How to remove the pre-defined fixed height</strong></p>
<p>Sometimes having a pre-defined height is a problem, because contained text length (and images) is not known. It is still possible to avoid a fixed height, with further workarounds. The simplest one is to let the <strong>opaquetext</strong> DIV extend as necessary, then use JavaScript to se <strong>translucentbkg</strong> height with the same value. But this is not a pure CSS solution.</p>
<p>If you want to use CSS only, the solution is quite simple, you have only to repeat content of <strong>opaquetext</strong> also in <strong>translucentbkg</strong> DIV. This is not elegant, but extremely easy to implement, also in dynamic generated pages.</p>
<pre>&lt;div id="container"&gt;

   &lt;div id="opaquetext"&gt;
      This is a normal text
      on a translucent background
   &lt;/div&gt;

   &lt;div id="translucentbkg"&gt;
      This is a normal text
      on a translucent background
   &lt;/div&gt;

&lt;/div&gt;
</pre>
<h4>PNG image with ALPHA channel</h4>
<p>This solution still uses the parent-child hierarchy, but actually it is an hybrid technique, because it implements the translucent background with totally different means across different browsers.</p>
<ul> <li><strong>Mozilla</strong> : Translucency is implemented using a PNG image with ALPHA channel as container's background image.</li>
</ul>
<ul> <li><strong>Internet Explorer</strong> : Since IE-6 (and below) does not support PNG images with ALPHA channel, translucency is implemented with the ALPHA filter of the previous example, but inheritance of the descendants is overridden thanks to a non-standard IE behaviour.</li>
</ul>
<p>Notes and drawbacks with this solution:</p>
<ul> <li>Another containing DIV has to be nested to have a working effect on Internet Explorer.</li> <li>Parent DIV is absolutely positioned and the new containing DIV with translucent background has to be a normal DIV. The text DIV has to be relatively positioned in order to override the translucency inheritance.</li> <li>A few CSS hacks have to used, in order to have different working CSS rules across the two browsers.</li> <li>A specific PNG image has to be generated, with the wanted grade of transparency.</li>
</ul>
<pre>&lt;div id="container"&gt;
  &lt;div id="translucentbkg"&gt;
    &lt;div id="opaquetext"&gt;
      This is a normal text
      on a translucent background
    &lt;/div&gt;
  &lt;/div&gt;  
&lt;/div&gt;
</pre>
<pre>#container {
   position: absolute;
   width: 250px;
   top: 400px;  left: 100px;
   }

#translucentbkg {
   width: 250px;
   background-image: url(transparent.png) !important;  /* Mozilla only */
   background-color: transparent !important;           /* Mozilla only */
   background-image: none;                             /* IE only */
   background-color: #ffffff;                          /* IE only */
   filter:alpha(opacity=50);                           /* IE only */
   }

#opaquetext { position: relative; }
</pre>
<p>{{ languages( { "fr": "fr/Astuces_CSS/Couleurs_et_fonds" } ) }}</p>
Revert to this revision