dean.edwards.name/weblog/2009/10/convert-any-colour-value-to-hex-in-msie/

Convert any colour value to hex in MSIE

The following function will convert any colour value (rgb, named colours, etc) to the hex equivalent in MSIE:

function toHex(color) {
  var body  = createPopup().document.body,
      range = body.createTextRange();
  body.style.color = color;
  var value = range.queryCommandValue("ForeColor");
  value = ((value & 0x0000ff) << 16) | (value & 0x00ff00) | ((value & 0xff0000) >>> 16);
  value = value.toString(16);
  return "#000000".slice(0, 7 - value.length) + value;
};

For other browsers you can use getComputedStyle() so that is already a solved problem.

Note: this method has been around for a while. I posted this adaptation because it does not suffer some of the drawbacks of the original.

If you are concerned about performance then you can always re-use the popup and range objects.

Comments (26)

Leave a comment

But probably not the extended color names (i.e. from SVG) – I want my papaywhip! :)

[...] This post was Twitted by mamund [...]

Cool! It works: “lightgray” becomes “#d3d3d3″!

Actually, lightgray throws an exception (380: Invalid property value.).
It’s lightgrey (en-gb) and gray (en-us).

So you’d better add exception handling…

  • Comment by: Doeke Zanstra
  • Posted:

@Doeke,

I can’t recreate that error. It returns the correct value for both “lightgrey” and “lightgray” on my IE7/IE8 machine. What version of IE are you using?

  • Comment by: -dean
  • Posted:

Nice one Dean, just a reminder about slice and negative index behavior:

return “#” + (“000000″ + value.toString(16)).slice(-6);

Thanks

uhm, apparently there could be some side-effect with createPopup: http://ajaxian.com/archives/windowcreatepopup-leaks-80kb-in-ie-7 ( via @jdalton ) Anything about it?

@Andrea, Good point. I forgot about that. It’s best to re-use the popup object then.

  • Comment by: -dean
  • Posted:

There’s not that many CSS color names so the best solution in my opinion (which doesn’t touch the DOM) would just be to define an object with all of the color values as properties, as I have done in the CSS color module for the color.js library.

If you are concerned about losing 80Kb of memory ;) then this also works:

function toHex(color) {
  var document = new ActiveXObject("htmlfile");
  document.write("<body>");
  document.close();
  var body = document.body;
  var range = body.createTextRange();
  body.style.color = color;
  var value = range.queryCommandValue("ForeColor");
  value = ((value & 0x0000ff) << 16) | (value & 0x00ff00) | ((value & 0xff0000) >>> 16);
  value = value.toString(16);
  return "#000000".slice(0, 7 - value.length) + value;
};

It’s possible that ActiveX will be disabled so you may want to fallback to the popup approach.

  • Comment by: -dean
  • Posted:

@Elijah this snippet is not just about lightgray, it’s about every possible IE color representation via style. The access object property is quite common solution but size speaking it’s horrible and it puts lots of words into the dictionary and gzip cannot help that much here … I guess it should be part of a dedicated IE file then :-)

@Dean, if you are sure no leaks there, why do not try a more compact version? :-)

function toHex(color) {
  with(new ActiveXObject("htmlfile")){
    close(write(""));
    body.style.color = color;
    var value = body.createTextRange().queryCommandValue("ForeColor");
    value = ((value & 0x0000ff) << 16) | (value & 0x00ff00) | ((value & 0xff0000) >>> 16);
    return "#" + ("000000" + value.toString(16)).slice(-6);
  };
};

@Andrea, People will always rewrite code anyway. I post enough information to solve the problem yourself. :)

  • Comment by: -dean
  • Posted:

right, so at least please note you forgot to close the “document stream” and that body tag is not necessary as soon as you write something, even nothing, the document.body will be available if you close it. This could be quite a key being IE famous for leaks, maybe we should try to avoid every kind of “opened document”. Thanks in any case for the original idea and snippet. Regards

please note you forgot to close the “document stream”

Oops. Fixed. Thanks.

  • Comment by: -dean
  • Posted:

good comment

  • Comment by: cc
  • Posted:

why not create “TEXTAREA” to createTextRange

  • Comment by: cc
  • Posted:

@cc – you can do that but you have to insert the textarea into the DOM, this will certainly cause a reflow and will be slow.

  • Comment by: -dean
  • Posted:

[...] Dean Edwards: Convert any colour value to hex in MSIE [...]

if i want to convert to hex in any browser i need to create “TEXTAREA” to use getComputedStyle

is there any better way?

  • Comment by: cc
  • Posted:

@cc, in other browsers you can use getComputedStyle() on an element to get the rgb version of its colour. In MSIE you must use the currentStyle property. But you then need to convert the MSIE value to rgb. If it is a named colour then the technique I posted will allow you to convert the value without inserting an element into the DOM.

  • Comment by: -dean
  • Posted:

use getComputedStyle() on an element

i mean that

if i only have color string

i need an element to use getComputedStyle

so i create a “TEXTAREA”

  • Comment by: cc
  • Posted:

set the TEXTAREA” display is “none” i think it wont cause a reflow

  • Comment by: cc
  • Posted:

Yet again, MSIE proving it can’t seem to be at all similar to other browsers. Don’t you get bored of fixing IE specific problems?

カラーキーワードをHEXやRGBに変換したい…  こんばんは。久しぶりにDean Edwardsのブログを覗いたら、MSIEでカラーキーワード(redとかtomatoとか)やらをHEX方式(#f01234とか)に変換するやり方が載ってました。fun……

  • Trackback by: ppBlog1.8.7
  • Posted:

[...] original here: Dean Edwards: Convert any colour value to hex in MSIE By admin | category: RGBカラー | tags: accessories, culture, edwards, facts, [...]

Leave A Comment

Line and paragraph breaks automatic, email address never displayed. Some HTML allowed.