JS: Making a Color Picker from Scratch, part 1: HTML/ CSS

Tom Cantwell
3 min readFeb 12, 2021

A major feature missing from my pixel drawing web app is the ability to select a color. Making a color picker is no simple task, so I’m dividing it up. Before we get to the Javascript, first I’m going to set up the basic layout with HTML and CSS.

This is what it will look like.

It’s important to have a clear vision of what your component will look like, so that’s why I’m starting with a rough layout of the HTML and CSS.

The main container needs to be able to be toggled onto the screen and hidden by the user. For now I’m just going to have it appear in the center of the screen:

<div class="color-container">
<h3>Color Picker</h3>
<div id="interface"></div>
</div>

.color-container {
display: flex;
flex-flow: column nowrap;
visibility: hidden;
pointer-events: none;
position: absolute;
top: 50%;
left: 50%;
color: white;
background: rgb(61, 61, 61);
text-align: center;
width: 570px;
height: 366px;
font-family: "04Font";
font-size: 16px;
padding: 0;
align-self: center;
transform: translate(-50%, -50%);
box-shadow:
2px 0px rgb(255, 255, 255),
-2px 0px rgb(255, 255, 255),
0px -2px rgb(255, 255, 255),
0px 2px rgb(255, 255, 255);
}

visibility: hidden and pointer-events: none work well together to hide a component that’s actually always there, it just can’t be interacted with at all until the user triggers a change in these properties with javascript, similar to a tooltip. I chose flex-direction: column to arrange the title and content easily. Luckily, since this is also a component that ignores the layout of the rest of the webpage, I can give it a fixed width and height without worrying.

I divided the content into a left and right div to organize it. On the left, the canvas where we’ll see a gradient of values for the selected hue, a slider to choose a hue, as well as the OK and Cancel buttons:

<div id="interface">
<div id="left">
<div id="picker">
<canvas id="color-picker"></canvas>
<input type="range" id="hue" name="hue" value="255" min="0" max="255">
</div>
<div id="buttons">
<btn>OK</btn>
<btn>Cancel</btn>
</div>
</div>
</div>

#interface {
display: flex;
flex-flow: row nowrap;
height: 300px;
}
#interface #left {
display: flex;
flex-flow: column nowrap;
height: 346px;
}
#interface #left #picker {
display: flex;
flex-flow: row nowrap;
height: 290px;
width: 330px;
}
#color-picker {
background-color: white;
width: 250px;
height: 250px;
margin: 20px;
box-shadow:
2px 0px rgb(131, 131, 131),
-2px 0px rgb(131, 131, 131),
0px -2px rgb(131, 131, 131),
0px 2px rgb(131, 131, 131);
}
#hue {
flex-shrink: 0;
-webkit-appearance: none;
appearance: none;
transform: rotate(90deg);
transform-origin: left;
width: 250px;
height: 20px;
margin: 10px;
background: white;
outline: none;
box-shadow:
2px 0px rgb(131, 131, 131),
-2px 0px rgb(131, 131, 131),
0px -2px rgb(131, 131, 131),
0px 2px rgb(131, 131, 131);
}
#hue::-webkit-slider-thumb {
-webkit-appearance: none;
height: 24px;
width: 5px;
outline: 2px solid rgb(0, 0, 0);
}

The hue slider is an input[type=range] element and to make it vertical and customized, the best way is to make appearance: none and do two transforms to rotate and then, importantly, set the transform-origin. You can make the basic slider vertical with appearance: vertical-slider but then you can’t customize it.

The right side right now is more standard flexbox stuff with nested column layouts and a bunch of input[type=number] elements. I’m going to cover this side in more detail later when I change them from standard number inputs to hybrid number/slider inputs so that they can either be typed in or changed with a slider on click. Next time I’ll cover making the visuals for the gradients and colors, as well as the javascript to actually select a color.

--

--