Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / HTML

A JavaScript Color Viewer

4.00/5 (4 votes)
23 May 2011CPOL4 min read 26.8K   241  
A web page to view HTML/CSS colors
screen.jpg

Introduction

In CSS, HTML, WPF XAML, and many other files, color is specified in the following forms:

  1. a color name - like red
  2. '#' followed by 6-bit hex value - like #123456
  3. '#' followed by 3-bit hex value - like #123, which will be expanded to #112233 by system
  4. rgb color - like RGB(255, 0, 0)

I found many times, especially when I read other's code, I have to figure out which color these numbers really represent. So, I developed a JavaScript color viewer, which can be downloaded and used in your local computer. An online version can also be found here.

Background

The color is entered dynamically by the user. The program has no idea of what it will be in advance. However, the program has to pick a color for the foreground text. No matter which color we pick, it could be the same as the background color, so we could not be able to see it. For that reason, we need to use at least two contrast colors for the text. In the program, we use black or white as the text color. And use a function to calculate background color brightness based on its RGB value. The function is based on this article which refers to this article.

We can also display text below the color block and use black as the only text color. But I feel that makes this program quite boring.

Using the Code

The program has 3 files, one HTML file, one JavaScript file and one CSS file. The HTML file is easy, it is listed below:

HTML
<div id="controls">
    <span>Color</span>
    <input type="text" id="txt" size="30"/>
    <input type="button" id="btn" value="Display"/>
</div>
<div id="message">Input is invalid!</div>
<div id="view"></div>

The "message" is displayed when user entered some invalid color. The "view" is where the color blocks will be inserted.

The JavaScript file contains the following parts:

  1. Two text brightness calculation functions
  2. A text parser, which is used to parse the input text, validate it, and find RGB channel values
  3. A display function, which insert squares into the HTML DOM tree

The JavaScript code to calculate the color brightness from RGB channel is:

JavaScript
function getTextColor2(red, green, blue) {
    var brightness = ((red * 299) + (green * 587) + (blue * 114)) / 1000;
    if(brightness < 125) { //background is dark
        return 'white';
    } else {
        return 'black';
    }
}

In my humble opinion, for programmers, knowing this function exists is more important than knowing why it works. However, if you really want to know why, please refer to the previously mentioned articles to see the details.

You can also calculate the brightness from hex values:

JavaScript
function getTextColor(hex) {
    if(hex.length == 3) {
        hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
    }
    var red = parseInt(hex.substring(0, 2), 16);
    var green = parseInt(hex.substring(2, 4), 16);
    var blue = parseInt(hex.substring(4, 6), 16);

    return getTextColor2(red, green, blue);
}  

The 3-bit hex color value like #123 is expanded to #112233. JavaScript parseInt function can take the second parameter, which is the radix (base) of the number to be parsed. The radix can be any number from 2 to 36. In our case, we use 16 to parse hex strings.

JavaScript has both substr and substring function. substr is not in the ECMAScript standard. So, we are not using it here. However, substr is supported by most web browsers. The usage of these 2 string functions is:

  • s.substr(start, length)
  • s.substr(start) // to end
  • s.substring(start, end) // 2 indices

The difference is substr goes from an index to some length, and substring goes from index to index. The way I remember it is: "ing" of substring is index.

The text parser uses the following regular expression to parse the input.

JavaScript
var regHex6 = /^#?([a-f\d]{6})$/;
var regHex3 = /^#?([a-f\d]{3})$/;
var regRgb = /^rgb\s*\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*\)$/;

The beginning "#" is optional for hex input, this is for some lazy people like me. \d{1,3} means a digit repeat 1, 2 or 3 times.

The text parser also needs a giant dictionary "standardColors" to check all the standard colors. This dictionary is at the end of the JavaScript file and not listed here. The parser will check whether the color exists, and what is the hex value of the color, so the program can calculate the text color.

The code for text parser is below, it returns an object of 2 properties. One property, text, will be displayed as the foreground text. The other property, textColor, will be either black or white, which is calculated from previously mentioned brightness functions and will be used as the text color. The 3 regular expressions will be used to match the input one by one, if no one matches, the function will assume the input is a color name. And the "standardColors" dictionary will be checked.

JavaScript
function parseInput(text) {
    var textLower = text.trim().toLowerCase();
    var result = textLower.match(regHex6);
    var hex;

    if(result) {
        hex = result[1];
        return {
            text: '#' + hex,
            textColor: getTextColor(hex)
        };
    }
    result = textLower.match(regHex3);
    if(result) {
        hex = result[1];
        return {
            text: '#' + hex,
            textColor: getTextColor(hex)
        };
    }
    result = textLower.match(regRgb);
    if(result) {
        var red = result[1];
        var green = result[2];
        var blue = result[3];
        if(red < 256 && green < 256 && blue < 256) {
            return {
                text: 'RGB(' + red + ', ' + green + ', ' + blue + ')',
                textColor: getTextColor2(red, green, blue)
            };
        }
    }
    hex = standardColors[textLower];
    if(hex) return {
                text: textLower,
                textColor: getTextColor(hex)
            };
    return null;
}

Finally, after user entered the color, the following function inserts a color block into the HTML DOM.

JavaScript
var displayColor = function() {
    var result = parseInput(txt.value);

    if(result) {
        msg.style.display = "none";
        view.innerHTML =
            '<div class="' + result.textColor + '">' +
                '<div class="inner">' +
                    '<span>' + result.text + '</span>' +
                '</div>' +
            '</div>' + view.innerHTML;
        view.firstChild.style.backgroundColor = result.text;
        txt.value = "";

    } else {
        msg.style.display = "block";
    }
};

view is a <div> element in HTML file. The following line adds a new block into the view.

JavaScript
view.innerHTML = [something] + view.innerHTML;

The inserted <div> elements will be displayed according to the CSS file, which is listed below:

CSS
#view > div {
    width: 100px;
    height: 100px;
    margin: 5px;
    float: left;
    display: table;
    text-align: center;
    font-weight: bold;
    font-size: 16px;
    font-family: "Courier New";
}

.white {
    color: white;
}

.black {
    color: black;
    border: 1px solid #eee;
}

.inner {
    display: table-cell;
    vertical-align: middle;
}

To vertically center the text display, the outer <div> uses the style display: table;, and inner <div> uses the style display: table-cell; and vertical-align: middle;. This works for most browsers.

Points of Interest

The displayColor function has a lot of string plus operations. In the first draft, I used a string format function, which makes the code much cleaner. It works in most browsers. However, Internet Explorer just doesn't like it for some unknown reason. My string format function is listed here:

JavaScript
String.prototype.format = function() {
    var result = this;
    for(arg in arguments) {
        result = result.replace("{" + arg + "}", arguments[arg]);
    }
    return result;
};

If you know why this function doesn't work on Internet Explorer, please let me know.

History

  • First version: May 19, 2011

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)