We’ve all had to do it – change the color of text or visible html elements like Div backgrounds or borders, etc. One thing I’ve noticed is that when I request the background color of a Div I get the RGB triplet, not a hexadecimal value. Observe this example:
(Please use a modern browser, I’ve made no effort to make the examples work in old browsers)
<html><head><title></title> <script language="javascript"> function getColor(){ document.getElementById('result').innerHTML = document.getElementById('dd').style.backgroundColor; } </script> </head> <body> <p><a href="javascript:getColor()">Click here to get the color of the box</a></p> <p>The box color is: <span id="result"></span></p> <div style="height:100px;width:100px;background-color:#185f8e;border:1px solid #ccc;" id="dd"></div> </body> </html>
Notice that the color obtained is not the hexadecimal value that you saw in the sample source provided above but the RGB equivalent even though its Hexadecimal to begin with.
Next, if I were to attempt to change the color by setting the css background-color value to an RGB value nothing will happen. See this example:
<html><head><title></title> <script language="javascript"> function setColor(){ document.getElementById('result').style.backgroundColor = 'rgb(122, 122, 122)'; } </script> </head> <body> <p><a href="javascript:setColor()">Click here to change the box color with an RGB value: rgb(122, 122, 122);</a></p> <p>The box color is: <span id="result"></span></p> <div style="height:100px;width:100px;background-color:#185f8e;border:1px solid #ccc;" id="dd"></div> </body> </html>
As you can see… nothing happens…. so in order to change the background color you must use a hexidecimal value.
If we get a hex value from an element it will be RGB so in order to make it useful elsewhere in our code we would need to convert the RGB back to hexadecimal. Below is a function I wrote that will do that for us.
... function convertToHex(str){ var raw = str.match(/(\d+)/g); var hexr = parseInt(raw[0]).toString(16); var hexg = parseInt(raw[1]).toString(16); var hexb = parseInt(raw[2]).toString(16); hexr = hexr.value == 1 ? '0' + hexr: hexr; hexg = hexg.length == 1 ? '0' + hexg: hexg; hexb = hexb.length == 1 ? '0' + hexb: hexb; var hex = '#' + hexr + hexg + hexb; return hex; } ...
This function takes an RGB of the following format: rgb(x, x, x) where “x” is any number within the RGB number range. The short description of what is happening would be to say that hexadecimal is base 16, thus the toString(16) which gives us the hex equivalent of each individual RGB value.
The long description would to say that the basic usage of toString() is to convert a number to a string, but we can also pass an argument to the toString() method to tell it what base to convert the number to. A few different bases are available. If we wanted to convert a number to binary we would use toString(2) (pronounced to string base 2), to octal, we would use toString(8) and finally to convert to hexadecimal we use toString(16). Using a base of 10 as in toString(10) is the same as using nothing at all – base 10 is decimal which is what numbers are to begin with.
An interesting thing to note is that hexadecimal is a numbering system from 0 to 9 and then continuing from A to F which totals 16 characters. 15 in hex is “f” which is just one character in length. 16 is two characters – ’10’. So any RGB value lower than 16 in hexadecimal will be a single character in length. Such values need to be left-padded by a zero since a hexadecimal color is always a total of 6 characters (2 characters per R, G, and B). To use our example, 15 = f in hex, we need to left zero pad it to be “0f”. If your RGB value is rgb(15, 15, 15) the proper hexadecimal value would be “0f0f0f” and not “fff” (which is a completely different color, see below). You can see the zero-padding happening in the ternary operators on lines 7, 8, and 9.
The caveat to all of this are the “shortcode” hex values that you see from time to time. Such as “fff” for white which in its full form is “ffffff”, or “ccc” for a light grey which is really “cccccc”. How about this shortened hex: “7de” – that would be “77ddee”. See the pattern? If a browser sees a 3 character hex value then each individual character must represent R, G, and B. In the absence of any other data the rest of the hex values are implied by the existing data, so “7” = “77, “d” = “dd” and “e” = “ee”. It is then necessary to give a browser a full hexadecimal value where necessary to get the actual colors, not implied colors. Left zero-padding where needed achieves this.
So here now is my last example using a color palette toolbar to change the color of a Div element, where I take the background color of the clicked Div element, which is revealed as RGB, convert it back to hexadecimal and apply it to the color box:
<html><head><title></title> <script language="javascript"> function convertToHex(str){ var raw = str.match(/(\d+)/g); var hexr = parseInt(raw[0]).toString(16); var hexg = parseInt(raw[1]).toString(16); var hexb = parseInt(raw[2]).toString(16); hexr = hexr.length == 1 ? '0' + hexr: hexr; hexg = hexg.length == 1 ? '0' + hexg: hexg; hexb = hexb.length == 1 ? '0' + hexb: hexb; var hex = '#' + hexr + hexg + hexb; return hex; } window.addEventListener('load',function(){ document.getElementById('colorWrapper').addEventListener('click',function(e){ if (e.target.attributes['class'].nodeValue == 'colorSwatch'){ document.getElementById('box').style.backgroundColor = convertToHex(e.target.style.backgroundColor); } },false); },false); </script> <style type="text/css"> #colorWrapper{ padding:0px 8px 8px 8px; border:1px solid #000; width:228px; margin: 0px 0px 20px 0px; } .colorSwatch{ height:50px; width:50px; display:inline-block; } </style> </head> <body> <div id="colorWrapper"> <p>Select a color to change the box's background color.</p> <div class="colorSwatch" style="background-color:#5d8eae"></div> <div class="colorSwatch" style="background-color:#adae5d"></div> <div class="colorSwatch" style="background-color:#78ae5d"></div> <div class="colorSwatch" style="background-color:#a05dae"></div> </div> <div style="height:100px;width:100px;background-color:#185f8e;border:1px solid #ccc;" id="box"></div> </body> </html>
An interesting thing to note is that the hexedecimal is not inserted as hexadecimal – its inserted as RGB! Yeah… I don’t know why either… if someone knows, please enlighten me in the comments below….