views:

32106

answers:

13

Is there a way in CSS to make the background of an element semi-transparent, but still have the text of the element non-transparent? (Without separating the text and background in two elements positioned over eachother.) I've tried

<p style="position:absolute;background-color:green;filter:alpha(opacity=60);opacity:.6;"><span style="color:white;filter:alpha(opacity=100);opacity:1;">Hello world</span></p>

But it looks like child elements are subjected to the opacity of their parent(s), so 'opacity:1' is still drawn as 'opacity:.6' from the parent.

+2  A: 

The easiest method would be to use a semi-transparent background PNG image. You can use Javascript to make it work in IE6 if you need to. I use the method outlined here.

Other than that, you could fake it using two side-by-side sibling elements - make one semi-transparent, then absolutely position the other over the top?

Chris
All I need is a simple background color, which size of PNG would you propose I create with this color? 1x1 will make rendering do a lot of work, too much pixels makes this PNG pretty big (should be ok file-size since compressed, but still rendering needs to uncompress it to use it)...
Stijn Sanders
I'd recommend something like 30px x 30px, which uses less memory when rendering it repeating than a 1x1, and is still small enough to minimise bandwidth usage.
Chris
A: 

This thread has some ideas. Either use a semi-transparent image, or overlay an additional element.

fearoffours
+2  A: 

The Problem is, that the text actually HAS full opacity in your example... it has full opacity inside the p tag. but the p tag is just semi-transparent.

You could add an semi transparent .png background instead of realizing it in CSS, or seperate text and div into 2 elements and move the text over the box (e.g. negative margin)

Otherwise it wont be possible...

EDIT:

just like Chris mentioned: if u use a .png file with transparenz, u have to use a javascript workaround to make it work in the damn IE...

Gushiken
A: 

I wrote about this a while back, bizarrely IE6 will allow you to make the background transparent and keep the text on top fully opaque, for the other browsers I then suggest using a transparent png.

Phil
+23  A: 

Either you use a semi-transparent png or you use CSS 3:

background-color:rgba(255,0,0,0.5);

Here's an article from css3.info

Georg
+2  A: 

its better to use a semi-transparent PNG IMAGE.

Just open the photoshop, create a field 1x1px, fill it with a green color and set an opacity in "Layers tab" to 60%. Then save it and make like a background

<p style="background: url(green.png);">any text</p>

and it wills cool, of couse, except lovely IE, we must add and extra hack for it:

p {filter: expression((runtimeStyle.backgroundImage != 'none') ? runtimeStyle.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src='+currentStyle.backgroundImage.split('\"')[1]+', sizingMethod=scale)' : runtimeStyle.filter,runtimeStyle.backgroundImage = 'none');}
+22  A: 

In Firefox 3 and Safari 3 you can use RGBA like gs mentioned.

A little known trick is that you can use it in IE as well using the Gradient filter.

background-color: rgba(0, 255, 0, 0.5);
filter: progid:DXImageTransform.Microsoft.Gradient(GradientType=0, StartColorStr='#7F00FF00', EndColorStr='#7F00FF00');

The first hex number defines the alpha value of the color.

Edit: full solution all browsers

.alpha60 {
/* Fallback for web browsers that doesn't support RGBa */
background: rgb(0, 0, 0);
/* RGBa with 0.6 opacity */
background: rgba(0, 0, 0, 0.6);
/* For IE 5.5 - 7*/
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000);
/* For IE 8*/
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#99000000, endColorstr=#99000000)";
}

from http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters/

Sebastian Markbåge
This seems to work great in both IE6 and IE7... thanks!
philfreo
But not in IE8. I tried the new -ms-filter syntax but it still didn't work for me :(
philfreo
@philfreo : It worked well for me in IE8.
Nordes
This post shows how to do it in IE8:http://robertnyman.com/2010/01/11/css-background-transparency-without-affecting-child-elements-through-rgba-and-filters/
Slapout
A: 

Here's how I do this (might not be optimal but it works):

Create the div that you want to be semi-transparent. Give it a class/id. Leave it EMPTY, and close it. Give it a set height and width (say, 300px by 300px). Give it an opacity of 0.5 or whatever you like, and a background color.

Then, DIRECTLY BELOW that div, create another div with a different class/id. Create a paragraph inside it, where you'll place your text. Give the div position: relative, and top: -295px (that's NEGATIVE 295 px). Give it a z-index of 2 for good measure, and make sure it's opacity is 1. Style your paragraph as you like but make sure the dimensions are less than that of the first div so it doesn't overflow.

That's it. Here's the code:

HTML

<body>
<div class="trans">
</div>
<div class="trans2">
<p>
text text text
</p>
</div>
</body>

CSS

.trans{ opacity: 0.5; height: 300px; width: 300px; background-color: orange; }

.trans2{ opacity: 1; position: relative; top: -295px; }

.trans2 p{ width: 295px; color: black; font-weight: bold; }

This works in Safari 2.x, I don't know about IE.

Which part of "Without separating the text and background in two elements positioned over eachother." wasn't clear to you?
Stijn Sanders
A: 

I've had this problem working on a few sites, so I blogged how I made it work.Take a look here: http://kiveo.net/transparent-backgrounds/

Jeremy Edgell
+1  A: 

For a simple semi-transparent background color, the above solutions (CSS3 or bg images) are the best options. However, if you don't want to rely on CSS3 or want to do something fancier (e.g. animation, multiple backgrounds, etc.), you can try the “pane technique”:

<style type="text/css" media="all">
    .pane, .pane > .back, .pane > .cont { display: block; }

    .pane {
        position: relative;
    }

    .pane > .back {
        position: absolute;
        width: 100%; height: 100%;
        top: auto; bottom: auto; left: auto; right: auto;
    }

    .pane > .cont {
        position: relative;
        z-index: 10;
    }
</style>

<p class="pane">
    <span class="back" style="background: green; opacity: 0.6; filter: alpha(opacity=60);"></span>
    <span class="cont">Hello World</span>
</p>

Basically, the technique works by using two “layers” inside of the outer pane element, one (the “back”) that fits the size of the pane element without affecting the flow of content, and one (the “cont”) that contains the content and helps determine the size of the pane.

The “position: relative” on pane is important; it tells back layer to fit to the pane's size. (If you really need the <p> tag to be absolute, you'll have to change the pane from a <p> to a <span> and wrap all that in a absolutely-position <p> tag.)

The main advantage this technique has over similar ones listed above is that the pane doesn't have to be a specified size; as coded above, it will fit full-width (normal block-element layout) and only as high as the content. The outer pane element can be sized any way you please, as long as it's rectangular (i.e. inline-block will work; plain-ol' inline will not).

Also, it gives you a lot of freedom for the background; you're free to put really anything in the back element and have it not affect the flow of content (if you want multiple full-size sub-layers, just make sure they also have position: absolute, width/height: 100%, and top/bottom/left/right: auto).

One variation to allow more flexible background layer/sub-layer placement is to use this CSS instead:

    .pane > .back {
        position: absolute;
        width: auto; height: auto;
        top: 0px; bottom: 0px; left: 0px; right: 0px;
    }

If you play around with the top/bottom/left/right values, you can inset the background by however much you want. Also, if you set a width and just left or right (not both), you can pin background layers to a specific side (same goes for height and just top or bottom).

The technique, as written, works in Firefox, Safari, Chrome, IE7+, and Opera. If you need it to work in IE6, you'll have to play around with expressions to get the width/height: 100% to work right. I believe the second CSS variation does not work in Opera.

If you want to see the whole technique in a real-world application, check out http://christmas-card-2009.slippyd.com/?f=s&amp;n=RXhhbXBsZSBmb3IgdGhlIFN0YWNrIE92ZXJmbG93IENvbW11bml0eQ%3D%3D%0A&amp;sn=T3ZlcmZsb3dpYW5z%0A

The animated, corner-faded background, the envelope, and the letter paper all use this technique with multiple image layers. While there are likely simpler ways to do this (e.g. using a CSS3 radial gradient instead of four ginormous corner-fade sub-layers or CSS3 background image positioning), the approach does work for anything you need in a background in every popular browser.

Things to watch out for:

  • Floating elements inside of the cont layer will not be contained. You'll need to make sure they are cleared or otherwise contained, or they'll slip out of the bottom.
  • Margins go on the pane element and padding goes on the cont element. Don't do use the opposite (margins on the cont or padding on the pane) or you'll discover oddities such as the page always being slightly wider than the browser window.
  • As mentioned, the whole thing needs to be block or inline-block. Feel free to use <div>s instead of <span>s to simplify your CSS.

Hope this helps.

Slippy Douglas
+2  A: 

This is the best solution I could come up with, NOT using CSS3. And it works great on FF, Chrome and IE as far as I can see.

Put a container DIV and two child DIVs in the same level, one for content, one for background:

<div class="container">
   <div class="content">
       Here is the content. <br />
       Background should grow to fit.
   </div>
   <div class="background"></div>
</div>

And using CSS, auto-size the background to fit the content and put the background actually in the back using z-index.

<style type="text/css">
   .container
   {
       position:relative;
   }
   .content
   {
       position:relative;
       color:White;
       z-index:5;
   }
   .background
   {
       position:absolute;
       top:0px;
       left:0px;
       width:100%;
       height:100%;
       background-color:Black;
       z-index:1;
       /* These three lines are for transparency in all browsers. */
       -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
       filter: alpha(opacity=50);
       opacity:.5;
   }
</style>
Gorkem Pacaci
A: 

Many many thanks for your code. i am really glad for u.

Tuhin
A: 

Here is a jQuery plugin that will handle everything for you, Transify http://jorenrapini.com/blog/css/transify-a-jquery-plugin-to-easily-apply-transparency-opacity-to-an-elements-background

I was running into this problem every now and then, so I decided to write something that would make life a lot easier. The script is less than 2kb and it only requires 1 line of code to get it to work, and it will also handle animating the opacity of the background if you like.

joren