by Vaibhav Kandwal
In this article, we’ll be creating a web-app that converts color codes between Hexadecimal and RGB.
The project structure is pretty simple.
index.html: Contains the structure of the app.
style.css: Styles the page.
app.js: Contains all the code required to run the project.
Here’s the list of things I wanted this app to perform:
- Whenever something is typed in a text-field for hex, the app should check if the color is valid. If it is, convert it to RGB, set it as the background and then put the RGB value in the RGB text-field and vice versa.
- If a short hex color code is typed into the text-field, expand it when the text-field loses focus (user clicks outside of text area).
- Automatically prepend ‘#’ symbol to the hex input.
I have created two text fields with ids of ‘hex’ and ‘rgb’ respectively. Besides each is an svg icon for error, which has a class of hidden, by default.
Here’s a basic layout to make the markup look a bit better. I am defining two classes here,
.dark. The first one is used to hide/show the error SVG icon and the latter to change the text color based on the background color. By default, I have set the text to a dark color (for bright backgrounds).
Here’s the magic part. I will be breaking down the code into chunks:
First, we are defining variables that target the inputs with id ‘hex’ and ‘rgb’. Next up, we have functions to check if input Hex/RGB is valid or not. They use a basic regex setup and return a boolean. If you get intimidated by them, I recommend you to try out this RegexTutorial.
Here, I have made a parse function called
modifyHex which checks if the input hex is 4 characters long; that is, contains ‘#’ and is shorthand (for example, #333) and replaces the ‘#’ with an empty character. Then it checks if the length now is 3 and expands it to 6 characters long (for example, #123 = #112233).
Now we are defining two functions that can convert hex to rgb and vice versa. Here’s the step-by-step breakdown for
hexToRgb(This code is expanded to better explain how the process is working):
- Define an empty array to store the result.
- Replace the ‘#’ symbol, if it exists, and if the length is not equal to 6 (that is, the shorthand version), call the above
modifyHexfunction and expand it.
- In a very basic way, hex to rgb works by converting the hex code (in base 16) to rgb code (in base 10). Every two characters in the hex code represent a value in the rgb color code. For Example in #aabbcc, red is (aa to base 10), green is (bb to base 10) and blue is (cc to base 10). So in the function, we are slicing the hex value, converting it to base 10 using
parseInt, and then storing it in the defined array.
- Finally, we are returning the output string.
rgbToHex function (this is written with shorter logic):
- We are directly using a regex to extract the parts inside the parenthesis — that is, rgb(123,21,24) will return 123,21,24.
- Next, we are using a map function to return a new array, which converts the number to base 16, then pads the value.
Let me explain this part. When we use regex to match the parts inside the parentheses, we return data of type ‘string’. To convert it to Base 16, we have to use the
toString method, with a parameter of ‘16’.
Now, toString method is applicable to only numeric data types, so we use
parseInt to first convert every element of the array to a number, then use
toString(16) to convert it to hexadecimal form and then finally add padding to make it exactly 2 characters long. Padding is necessary, if you have something like ‘14’, which you want to convert to hexadecimal, it will return ‘e’. But hex color code needs 2 characters for each part, so padding is required, which makes it ‘0e’.
padStart is an ES8 feature, which might not be supported in every browser. To keep this tutorial simple, I have not transpiled it to ES5.
3. Finally, we are returning the resulting array by joining it and converting it to uppercase.
This function is used to add that little error mark on the right side of input, in case the entered input type is wrong.
It simply runs the contents of the input (
rgb.value ) through their respective check functions and uses the returned boolean to add/remove the
Now we are defining a function which takes the background color and then determines if it is dark or bright (I got this code from StackOverflow). It multiplies the individual color values with some calculated numbers and returns ‘black’ or ‘white’. I then use another function to change the text color by adding/removing the
Adding Event Listeners:
Finally, we are going to use all the above functions by adding Event Listeners.
First, we are adding a
keyup event to the
hex input. This event is triggered each time a key is released. Here’s what the function is doing:
- We are checking if the input code is valid and expanding it if it’s shorthand.
- We are setting the body’s background color to the input value.
- We are checking if the color is bright/dark and changing the text color accordingly.
- Finally, we are calling the convert function and then putting the converted color into the RGB input.
The other event listener we used is
blur . It is triggered each time the input loses ‘focus’, or in layman terms, each time you click/tap outside of input element,
blur is triggered. So it’s good to modify the input hex!
So, we check if the hex color is valid or not, then we expand it if it is short, and finally we are adding a ‘#’ if it doesn’t exist. Note that we are checking if index 0 and 1 contain ‘#’. This is done so that the function doesn’t prepend ‘#’ twice.
Now we are adding the same
keyup event listener to the rgb input and it too follows the same series of steps as the hex event listener.
Lastly, we are adding an event listener
keyup to the entire document, that is, it will be triggered for any of the two input elements. Inside it, we are calling the
errorMark function, which adds the error icon, in case there’s an error, or removes it if everything is valid.
Here’s the final code for
There you have it! I know the code is not perfect and can be refactored, but hey, this is just the beginning. If you want to improve this code, you can go ahead and open a PR on my github repo.