Reputation: 50021
When I use window.getComputedStyle
on an element's color property, it returns a string with an rgb()
or rgba()
value, regardless of the syntax used to set the color originally. In Internet Explorer, when forced to use element.currentStyle
instead, it apparently returns the exact color string that was originally set (although lowercased).
Here is a demonstration of my problem:
<div id=el> </div>
<script type="text/javascript">
var el = document.getElementById('el');
el.style.color = 'red';
if (window.getComputedStyle) {
el.innerHTML = getComputedStyle(el, null).color;
} else {
el.innerHTML = el.currentStyle.color;
}
</script>
Other browsers display "rgb(255, 0, 0)". IE displays "red". I want to determine the real RGB or RGBA value. So I have two questions:
rgb()
or rgba()
string, or could they return, for example, #ff0000
, or something else?Upvotes: 5
Views: 4312
Reputation: 707258
As best I can tell, the answer is "no". There is no simple way to get the color value in IE without knowing how to parse all possible color representations. When I tried to do this, I found that I even needed to recognized all possible color names like blue
. It was a royal pain, but I did work out the code for it.
My code was trying to get the background color and it will even look at parent objects in order to find where the background color is set (so it's not doing exactly what you asked for) and it used the YUI version of getComputedStyle (you can substitute your own) but this is the code I used. It does handle these forms of color definition:
#fff
#ffffff
transparent
rgb(12,45,99)
rgba(12,45,99,30)
orange
And, the code:
JFL.GetBackgroundColor = function(o)
{
var colorNames = {
aliceblue: 'f0f8ff',
antiquewhite: 'faebd7',
aqua: '00ffff',
aquamarine: '7fffd4',
azure: 'f0ffff',
beige: 'f5f5dc',
bisque: 'ffe4c4',
black: '000000',
blanchedalmond: 'ffebcd',
blue: '0000ff',
blueviolet: '8a2be2',
brown: 'a52a2a',
burlywood: 'deb887',
cadetblue: '5f9ea0',
chartreuse: '7fff00',
chocolate: 'd2691e',
coral: 'ff7f50',
cornflowerblue: '6495ed',
cornsilk: 'fff8dc',
crimson: 'dc143c',
cyan: '00ffff',
darkblue: '00008b',
darkcyan: '008b8b',
darkgoldenrod: 'b8860b',
darkgray: 'a9a9a9',
darkgreen: '006400',
darkkhaki: 'bdb76b',
darkmagenta: '8b008b',
darkolivegreen: '556b2f',
darkorange: 'ff8c00',
darkorchid: '9932cc',
darkred: '8b0000',
darksalmon: 'e9967a',
darkseagreen: '8fbc8f',
darkslateblue: '483d8b',
darkslategray: '2f4f4f',
darkturquoise: '00ced1',
darkviolet: '9400d3',
deeppink: 'ff1493',
deepskyblue: '00bfff',
dimgray: '696969',
dodgerblue: '1e90ff',
feldspar: 'd19275',
firebrick: 'b22222',
floralwhite: 'fffaf0',
forestgreen: '228b22',
fuchsia: 'ff00ff',
gainsboro: 'dcdcdc',
ghostwhite: 'f8f8ff',
gold: 'ffd700',
goldenrod: 'daa520',
gray: '808080',
green: '008000',
greenyellow: 'adff2f',
honeydew: 'f0fff0',
hotpink: 'ff69b4',
indianred : 'cd5c5c',
indigo : '4b0082',
ivory: 'fffff0',
khaki: 'f0e68c',
lavender: 'e6e6fa',
lavenderblush: 'fff0f5',
lawngreen: '7cfc00',
lemonchiffon: 'fffacd',
lightblue: 'add8e6',
lightcoral: 'f08080',
lightcyan: 'e0ffff',
lightgoldenrodyellow: 'fafad2',
lightgrey: 'd3d3d3',
lightgreen: '90ee90',
lightpink: 'ffb6c1',
lightsalmon: 'ffa07a',
lightseagreen: '20b2aa',
lightskyblue: '87cefa',
lightslateblue: '8470ff',
lightslategray: '778899',
lightsteelblue: 'b0c4de',
lightyellow: 'ffffe0',
lime: '00ff00',
limegreen: '32cd32',
linen: 'faf0e6',
magenta: 'ff00ff',
maroon: '800000',
mediumaquamarine: '66cdaa',
mediumblue: '0000cd',
mediumorchid: 'ba55d3',
mediumpurple: '9370d8',
mediumseagreen: '3cb371',
mediumslateblue: '7b68ee',
mediumspringgreen: '00fa9a',
mediumturquoise: '48d1cc',
mediumvioletred: 'c71585',
midnightblue: '191970',
mintcream: 'f5fffa',
mistyrose: 'ffe4e1',
moccasin: 'ffe4b5',
navajowhite: 'ffdead',
navy: '000080',
oldlace: 'fdf5e6',
olive: '808000',
olivedrab: '6b8e23',
orange: 'ffa500',
orangered: 'ff4500',
orchid: 'da70d6',
palegoldenrod: 'eee8aa',
palegreen: '98fb98',
paleturquoise: 'afeeee',
palevioletred: 'd87093',
papayawhip: 'ffefd5',
peachpuff: 'ffdab9',
peru: 'cd853f',
pink: 'ffc0cb',
plum: 'dda0dd',
powderblue: 'b0e0e6',
purple: '800080',
red: 'ff0000',
rosybrown: 'bc8f8f',
royalblue: '4169e1',
saddlebrown: '8b4513',
salmon: 'fa8072',
sandybrown: 'f4a460',
seagreen: '2e8b57',
seashell: 'fff5ee',
sienna: 'a0522d',
silver: 'c0c0c0',
skyblue: '87ceeb',
slateblue: '6a5acd',
slategray: '708090',
snow: 'fffafa',
springgreen: '00ff7f',
steelblue: '4682b4',
tan: 'd2b48c',
teal: '008080',
thistle: 'd8bfd8',
tomato: 'ff6347',
turquoise: '40e0d0',
violet: 'ee82ee',
violetred: 'd02090',
wheat: 'f5deb3',
white: 'ffffff',
whitesmoke: 'f5f5f5',
yellow: 'ffff00',
yellowgreen: '9acd32'
};
function parseSingle(s)
{
s = s + s;
return(parseInt(s, 16));
}
var color;
while (o)
{
color = YD.getComputedStyle(o, "backgroundColor");
if (color && color != "transparent")
{
break;
}
if (o == document.body)
{
color = "#ffffff";
break;
}
o = o.parentNode;
}
color = color.replace(/ /g, "").toLowerCase();
if (colorNames[color])
{
color = "#" + colorNames[color];
}
var r = 256, g = 256, b = 256;
if (color.indexOf("#") == 0)
{
color = color.slice(1);
if (color.length == 3)
{
r = parseSingle(color.slice(0,1));
g = parseSingle(color.slice(1,2));
b = parseSingle(color.slice(2,3));
}
else if (color.length == 6)
{
r = parseInt(color.slice(0,2), 16);
g = parseInt(color.slice(2,4), 16);
b = parseInt(color.slice(4,6), 16);
}
}
else if (color.indexOf("rgb") == 0)
{
var results = color.match(/^rgba?\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})/);
if (results && results.length >= 4)
{
r = parseInt(results[1], 10);
g = parseInt(results[2], 10);
b = parseInt(results[3], 10);
}
}
var luminance = (0.3 * r + 0.59 * g + 0.11 * b) / 256;
return({r: r, g: g, b: b, luminance: luminance});
}
Upvotes: 3
Reputation: 50021
As suggested I examined CMS's answer here which uses queryCommandValue
. For the equivalent of CSS 'color' rather than 'backround-color', I had to use 'ForeColor' rather than 'BackColor', but this technique seems to work perfectly for getting the real value in IE.
Here is the amended, working version of the example in my question:
<div id=el> </div>
<script type="text/javascript">
var el = document.getElementById('el');
el.style.color = 'red';
if (window.getComputedStyle) {
el.innerHTML = getComputedStyle(el, null).color;
} else {
var oRG = document.body.createTextRange();
oRG.moveToElementText(el);
var iClr = oRG.queryCommandValue('ForeColor');
el.innerHTML = 'rgb('+(iClr & 0xFF)+','+((iClr & 0xFF00)>>8)+','+((iClr & 0xFF0000)>>16)+')';
}
</script>
I've been looking for an answer to my second question, but there doesn't seem to be one. If I'm reading it correctly, this page: http://www.w3.org/TR/css3-color/ explains that browsers may return, for the computed value, either a "six digit hex value or rgb(...) functional value, with an alpha value of 1" (?). It says transparent
returns rgba(0,0,0,0)
. And finally it says, "for all other values, the computed value is the specified value". This is not clear at all. E.g., must it use RGB integers or can it use percentages? May there be space around the values? Can the "specified value"'s letter case be preserved? What about hsl()
and hsla()
colors?
In practice, it seems that browsers normalize the values to return rgb(...)
or rgba(...)
, with the red-green-blue as integers and the alpha as a decimal, with a single space after each comma, although this doesn't seem to be formally specified. As an exception, Firefox seems to return transparent
if the color's alpha value is 0, regardless of the other values or how it was set; e.g., rgba(255, 0, 255, 0)
.
So, IE's odd way for getting an RGB int is far simpler, if you can use it.
Upvotes: 0