CSS Colours and Fenceposts

In CSS, RGB colours can be written as #rgb or #rrggbb, where r, g and b are hex digits.

The digits in the #rgb format map values of 0-15 to the range 0-255 in such a way that 0 maps to 0 and 15 maps to 255.

This is a fencepost system, where each of the smaller values is a post.

It happens that 16 posts and 15 rails can fill the interval 0-255, with each rail having a length of 16.

0   1   2   3         12  13  14  15
|---|---|---|-... ...-|---|---|---|
0   17  34  51        209 226 243 255

Any number in the small ranges maps to one 17 times larger in the large range. The smallest and largest numbers map to the smallest and largest in the large range and all are equally spaced.

In hex, the relation is trivial:

0   1   2   3         C   D   E   F
|---|---|---|-... ...-|---|---|---|
0   11h 22h 33h       CC  DD  EE  FF

Cause

First I thought that this worked because both 16 and 256 are powers of two.

This was quickly disproved as there’s no post-and-rail way of mapping 16 onto ranges of 32, 64 or 128 values. (4,096, 65,536 and higher are possible.)

After some thought, it can be seen that any small range can neatly map onto any larger range whose size is an integer power of the size of the small range.

In CSS colours, these are 16 and 16-squared (256).

Other examples

5 and 5-squared (25):

0   1   2   3   4
|---|---|---|---|
0   6   12  18  24

3 and 3-cubed (27):

0   1   2
|---|---|
0   13  26

Size of the multiplier

If the size of the small range is S, and the larger range is S**N, then the multiplier to map between the ranges is:

 N
___
\   S**n
/__
n=0

This sum corresponds exactly to repeating digits in base S.

e.g. The 3-cubed example can be written in base-3 as:

0   1   2
|---|---|
0   111 222