I'm new to Sass and struggling with this. I can't get the color to render in both hex (for IE) and rgba. Every little piece is frustrating me because I haven't mastered the syntax yet, and Google results for Sass are still sparse.
Here's the mixin:
#mixin transparent($hex, $a){
/* for IEGR8 */
background: transparent;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$a}#{$hex},endColorstr=#{$a}#{$hex});
zoom: 1;
/* for modern browsers */
background-color: rgba(#{$hex},.#{$a});
}
Such that #include transparent(#FFF,.4) should produce the nice, browser compatible transparent code below:
background: transparent;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#40FFFFFF,endColorstr=#40FFFFFF);
zoom: 1;
background-color: rgba(100,100,100,.40);
I've been noobing on the following for a couple hours:
The # required for #RGB format.
The . required for rgba alpha.
Both need to be included for the call to rgba(), however the # can't be included for the IE #AARRGGBB or it will look like #AA#RRGGBB, and the . can't be included for IE or it rejects #.AARRGGBB.
Am I missing a much simpler way to do this? Can this be done with Sass string manipulation or any slightly clever color cast function in Sass which handles this for me already?
#mixin transparent($color, $alpha) {
$rgba: rgba($color, $alpha);
$ie-hex-str: ie-hex-str($rgba);
background-color: transparent;
background-color: $rgba;
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie-hex-str},endColorstr=#{$ie-hex-str});
zoom: 1;
}
NOTE: The ie-hex-str is only available in recent versions, not sure when it was introduced though
I think I encountered a similar problem when I wanted to pass a url to the mixin. Instead of sending only the url I had the send the whole url parameter as a parameter to the mixin. If you understand what I mean?
example:
#mixin bg($url)
background: #000 $url repeat-x
insted of:
#mixin bg($url)
background: #000 url($url) repeat-x
Also, this might not the suited for your application, but I usually work around that problem using opacity:
#mixin transparent_bg($hex, $a){
/* for IEGR8 */
filter:alpha(opacity=$a)
zoom: 1;
/* for modern browsers */
background-color: $hex;
opacity: ($a*10)
}
This probably is as bulletproof as you'll get without a proper shim.
To build on seutje's answer, this lets you use ms-filter transparency if you're doing background-color on IE, but if you if you know the colour of the element behind the element you want to make transparent, you can use Sass's "mix" function to mix the two colours and get fake transparency - for any kind of colour. That means borders and text and all that jive. It's still a manual fallback but it'll give you the exact colour you're trying to simulate with a solid hex.
SCSS:
#mixin alpha-color($foreground-color, $property: 'background-color', $background-context-color: #fff) {
#{$property}: mix(
fade-in($foreground-color, 1),
$background-context-color,
percentage(opacity($foreground-color))
); // Browsers without color opacity
#{$property}: $foreground-color; // Decent browsers
#if $property == 'background-color' {
.lt-ie9 & { // IE8 has background filters; use them instead
#{$property}: transparent;
$ie-hex: ie-hex-str($foreground-color);
filter:progid:DXImageTransform.Microsoft.gradient(startColorstr=#{$ie-hex},endColorstr=#{$ie-hex});
zoom: 1;
}
}
}
To get border-color: rgba(255, 0, 0, 0.5) on a blue background, you'd use it like:
.blue-container {
$color-bg: rgb(0,0,255);
background-color: $color-bg;
.transparent-red-element {
#include alpha-color(rgba(255, 0, 0, .65), border-color, $color-bg);
}
}
Sass automatically turns 100% opacity colors back into a hex code, hence the fade-in of 100%.
The only browsers without colour opacity are IE8 <=8 and Opera <=9.6, and IE 8 has filters so this only helps for colors other than background-color. The principle is that you mix the background and foreground colours together into a flat hex.
ie-hex-str is like a year old now so you'll definitely have it.
Related
I found another question on SO about rgb vs rgba that is very similar, but it's missing an answer about the usage of rgb with opacity.
I know the difference between both – rgba is just rgb but with alpha for opacity. The thing is, it has been months or even years that I am using rgb with opacity values. It has always worked for me. rgb(255, 0, 255, 0.5)
Makes me wonder if there's an advantage to use one if both works the same? rgb has been there longer so browser compatibility I suppose is better? Also I was told by a coworker that rgba value will only work for background colors, but then again, I did some tests in codepen and it works on Edge and Chrome.
(I know both are Chrome based both these are the one I have downloaded)
Related question : What are differences between RGB vs RGBA other than 'opacity'
Here is my snippet
/* texts */
.one {
color: rgba(255, 200, 0, .5);
}
.oneFive {
color: rgb(255, 200, 0, .5);
}
/* backgrounds */
.two {
background-color: rgb(255, 0, 255, 0.5);
}
.three {
background-color: rgba(0, 0, 255, 0.5);
}
/* */
/* settings */
/* */
.two, .three {
height: 50px;
}
.two {
margin-top: 30px;
}
.two, .three, .zero {
color: white;
}
.one, .oneFive {
height: 50px;
font-weight: bold;
font-size: 2em;
padding-left: 40px;
padding-top: 20px;
}
body {
background-color: #444;
color: white;
}
.zero {
background-color: darkgreen;
width: 300px;
height: 350px;
position: absolute;
top: 35px;
z-index: -1;
}
dark grey 100% opacity
<div class="zero">dark green 100% opacity</div>
<div class="oneFive">rgb yellow text 70% opacity</div>
<div class="one">rgba yellow text 70% opacity</div>
<div class="two">rgb 50% background opacity</div>
<div class="three">rgba 50% background opacity</div>
Answer as requested:
I'm going to go out on a limb and say it's the browser translating what is essentially an "incorrect" value set in rgb with an opacity value.
If you look in the browser dev tools under the computed tab, you'll notice that the rgb values are computed to rgba (at least in Firefox).
I'm thinking that any browser that supports CSS3 will "fix" the property.
Also I was told by a coworker that rgba value will only work for background colors: Your coworker is wrong.
rgb has been there longer so browser compatibility I suppose is better? I wouldn't say that. You'll never notice a performance hit, but you'll make your browser do less work if it doesn't have to "fix" your incorrect values being passed to the rgb set. Update: rgba is an alias for rgb, so it's really not fixing anything, it's simply passing to rgb anyway.
Here is some documentation on rgb and rgba - specifically the aliasing of the functions:
https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#rgb_colors
Makes me wonder if there's an advantage to use one if both works the same?
It's not about advantage but this is something new defined in the Specification
rgb() and rgba(), and hsl() and hsla() are now aliases of each other (all of them have an optional alpha). ref
And
Also for legacy reasons, an rgba() function also exists, with an identical grammar and behavior to rgb(). ref
So rgba() is meant to disappear and only rgb() should be used but this won't happen because it will create a lot of issues and conflit so rgba() will still be considered and will simply have the same syntax as rgb()
Also note that the new syntax no more contain comma:
rgb() = rgb( <percentage>{3} [ / <alpha-value> ]? ) |
rgb( <number>{3} [ / <alpha-value> ]? )
<alpha-value> = <number> | <percentage>
You should write rgb(255 65 40) or rgb(255 65 40 / 80%) for example but still for legacy reasons the comma syntax is still supported:
For legacy reasons, rgb() also supports an alternate syntax that separates all of its arguments with commas:
I stumbled onto this site: and started thinking. Is this possible using twitter's bootstrap? I don't see an opacity setting in the css file? Is it as easy as adding it.
In general, this is possible. Testflightapp uses the background-color: rgba attribute with an opacity level.
So if you want to set a background color with opacity to on of you element use this CSS:
elementname {
background-color: rgba(128, 128, 128, 0.5); /* Red [0-255], Green [0-255], Blue [0-255], Alpha [0-1] */
}
If you want to set the opacity on the element as a whole use:
elementname {
opacity: 0.5; /* opacity [0-1] */
-moz-opacity: 0.5; /* opacity [0-1] */
-webkit-opacity: 0.5; /* opacity [0-1] */
}
This is only supported by browsers that support CSS3.
A late answer, but I just found this question whilst looking up something very similar.
If you're using bootstrap with less, so that you're building the css yourself as part of an asset pipeline you should set opacity using the utility macro.
selector {
.opacity(50); /* opacity [0->100] */
}
It'll define the correct browser prefixes, including the IE filter syntax for you.
If you are using bootstrap with sass. You can use the opacity mixin.
#include opacity([from 0-100]);
This will take handle all browser compatibilities (if supported) dealing with opacity.
I've looked at Blueprint, Less, and SCSS and none of them appear to do what I want. I find this difficult to believe because handling vendor prefixes is the most frustrating part of writing CSS, so it would appear to be to be the first problem anyone who writes a CSS framework ought to address.
I want to know, is there a framework (or rails gem) that I can use, that allows me to write border-radius:5px and then let's me assume that it will create a rule with all the proper vendor prefixes?
Thanks
You can actually do this quite easily with a LESS Mixin - basically you write it once and from there on out you apply it with one line. Like this:
// Border Radius
.border-radius(#radius: 5px) {
-webkit-border-radius: #radius;
-moz-border-radius: #radius;
border-radius: #radius;
}
Then you symply do this one-liner where you need a border radius:
.classname {
.border-radius(5px);
}
If you are not ready for LESS, then you could just process your code through Prefixr - it generates the browser prefixes for you (then you have to copy paste the code back into your file).
you can use that: http://sjevsejev.blogspot.com/2012/07/lessjs-function-generates-prefixes-for.html
then it would be enough to use:
.pf('transition','all 1s ease-in-out');
.pf('border-radius',3px);
.pf('box-shadow','2px 2px 5px 0 rgba(0,0,0,.6)');
.pf('flex', 1);
Perhaps a recently published collection of scss to css vendor prefix repository might be of interest, following is pulled from the border-radius.scss file...
#mixin border-radius($value) {
#include render-vendor-prefixes(
$property: border-radius,
$value: $value,
$vendor-list: (
-webkit, // Android 2.1, Chrome 5.0/4.0, iOS 3.2-, Safari 5.0/3.1,
-moz, // Firefox 4.0/3.0
),
$prefix: property,
);
}
Using the above #mixin could look like...
#import '_scss/modules/vendor-prefixes/lib/map-vendor-prefixes.scss';
#import '_scss/modules/vendor-prefixes/lib/render-vendor-prefixes.scss';
#import '_scss/modules/vendor-prefixes/calc.scss';
.something {
#include border-radius(10% 30% 50% 70%);
}
... and for completeness, the above complies to...
.something {
-webkit-border-radius: 10% 30% 50% 70%;
-moz-border-radius: 10% 30% 50% 70%;
border-radius: 10% 30% 50% 70%;
}
In my CSS I have the following:
.Thing {
filter: alpha(opacity=40);
opacity:0.4;
-moz-opacity:0.4;
}
.Thing button {
filter: alpha(opacity=100);
opacity:1;
-moz-opacity:1.0;
}
However, the button is still .4 opacity. I then try opacity: 2 and such and it looks like I can give it less opacity but not more. Is there a way I can remove it or do I have to write multiple rules to get everything but the button?
I am testing with Firefox and Chrome.
use rgba with a rgb fallback.
background-color: rgb(0,0,0);
background-color: rgba(0,0,0, 0.5); /*ie6 will ignore this*/
rgba will only apply opacity to the target element.
What i've recently been doing is using the rgbapng sass/compass plugin which generates a png image to use as a fallback for browsers without rgba support.
Note: you'll still need to use an ie6 png fix for this to work.
Not a fix for the opacity issue but a possible workaround.
How about removing the button from the normal document flow and then placing back inside the .Thing
Something like this: http://jsfiddle.net/CqgkM/
I want to set Opacity of div's background without affecting contained element in IE 8. have a any solution and don't answer to set 1 X 1 .png image and set opacity of that image because I am using dynamic opacity and color admin can change that
I used that but not working in IE 8
#alpha {
filter: alpha(opacity=30);
-moz-opacity: 0.3;
-khtml-opacity: 0.3;
opacity: 0.3;
}
and
rgba(0,0,0,0.3)
also.
The opacity style affects the whole element and everything within it. The correct answer to this is to use an rgba background colour instead.
The CSS is fairly simple:
.myelement {
background: rgba(200, 54, 54, 0.5);
}
...where the first three numbers are the red, green and blue values for your background colour, and the fourth is the 'alpha' channel value, which works the same way as the opacity value.
See this page for more info: http://css-tricks.com/rgba-browser-support/
The down-side, is that this doesn't work in IE8 or lower. The page I linked above also lists a few other browsers it doesn't work in, but they're all very old by now; all browsers in current use except IE6/7/8 will work with rgba colours.
The good news is that you can force IE to work with this as well, using a hack called CSS3Pie. CSS3Pie adds a number of modern CSS3 features to older versions of IE, including rgba background colours.
To use CSS3Pie for backgrounds, you need to add a specific -pie-background declaration to your CSS, as well as the PIE behavior style, so your stylesheet would end up looking like this:
.myelement {
background: rgba(200, 54, 54, 0.5);
-pie-background: rgba(200, 54, 54, 0.5);
behavior: url(PIE.htc);
}
[EDIT]
For what it's worth, as others have mentioned, you can use IE's filter style, with the gradient keyword. The CSS3Pie solution does actually use this same technique behind the scenes, but removes the need for you to mess around directly with IE's filters, so your stylesheets are much cleaner. (it also adds a whole bunch of other nice features too, but that's not relevant to this discussion)
it's simple only you have do is to give
background: rgba(0,0,0,0.3)
& for IE use this filter
background: transparent;
zoom: 1;
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#4C000000,endColorstr=#4C000000); /* IE 6 & 7 */
-ms-filter: "progid:DXImageTransform.Microsoft.gradient(startColorstr=#4C000000,endColorstr=#4C000000)"; /* IE8 */
you can generate your rgba filter from here http://kimili.com/journal/rgba-hsla-css-generator-for-internet-explorer/
opacity on parent element sets it for the whole sub DOM tree
You can't really set opacity for certain element that wouldn't cascade to descendants as well. That's not how CSS opacity works I'm afraid.
What you can do is to have two sibling elements in one container and set transparent one's positioning:
<div id="container">
<div id="transparent"></div>
<div id="content"></div>
</div>
then you have to set transparent position: absolute/relative so its content sibling will be rendered over it.
rgba can do background transparency of coloured backgrounds
rgba colour setting on element's background-color will of course work, but it will limit you to only use colour as background. No images I'm afraid. You can of course use CSS3 gradients though if you provide gradient stop colours in rgba. That works as well.
But be advised that rgba may not be supported by your required browsers.
Alert-free modal dialog functionality
But if you're after some kind of masking the whole page, this is usually done by adding a separate div with this set of styles:
position: fixed;
width: 100%;
height: 100%;
z-index: 1000; /* some high enough value so it will render on top */
opacity: .5;
filter: alpha(opacity=50);
Then when you display the content it should have a higher z-index. But these two elements are not related in terms of siblings or anything. They're just displayed as they should be. One over the other.
Try setting the z-index higher on the contained element.
What about this approach:
<head>
<style type="text/css">
div.gradient {
color: #000000;
width: 800px;
height: 200px;
}
div.gradient:after {
background: url(SOME_BACKGROUND);
background-size: cover;
content:'';
position:absolute;
top:0;
left:0;
width:inherit;
height:inherit;
opacity:0.1;
}
</style>
</head>
<body>
<div class="gradient">Text</div>
</body>
It affects the whole child divs when you use the opacity feature with positions other than absolute. So another way to achieve it not to put divs inside each other and then use the position absolute for the divs. Dont use any background color for the upper div.
Maybe there's a more simple answer, try to add any background color you like to the code, like background-color: #fff;
#alpha {
background-color: #fff;
opacity: 0.8;
filter: alpha(opacity=80);
}
Use RGBA or if you hex code then change it into rgba. No need to do some presodu element css.
function hexaChangeRGB(hex, alpha) {
var r = parseInt(hex.slice(1, 3), 16),
g = parseInt(hex.slice(3, 5), 16),
b = parseInt(hex.slice(5, 7), 16);
if (alpha) {
return "rgba(" + r + ", " + g + ", " + b + ", " + alpha + ")";
} else {
return "rgb(" + r + ", " + g + ", " + b + ")";
}
}
hexaChangeRGB('#FF0000', 0.2);
css ---------
background-color: #fff;
opacity: 0.8;
OR
mycolor = hexaChangeRGB('#FF0000', 0.2);
document.getElementById("myP").style.background-color = mycolor;