|
Introduction
|
|
This short essay attempts to explain the use of colours on the
world wide web. In particular, it deals with the challenge of
designing pages to look their best on machines limited to 256
colours.
|
|
How computer colours are defined
|
|
How we perceive colours is actually very complicated, and is a
significant specialisation in psychology. Photographers recognise
this, and know that different kinds of film need to be used outdoors
("daylight balanced") and indoors ("tungsten balanced").
No photographer I've ever asked can explain to me why a red clipboard
appears to me to be the same colour indoors and out, although
the spectrum of light it reflects depends so much on the spectrum
that illuminates it. In fact, I can't explain it either, so I
won't try.
Forget about why it works, here's how it works,
at least in the context of a computer screen. A computer screen
can really only show three colours: red, green and blue
(RGB for short). Any other colour you perceive is actually a
mixture of varying proportions of those three. In what follows,
I'll talk about colours "displayed" by computers: bear
in mind, they're always mixtures of those three components.
|
|
The Netscape websafe palette
|
|
The number of colours that can be displayed by a typical computer
screen has grown over the years. Many computers nowadays can
simultaneously display 65536 or more; but some are limited
to 256. I believe that most web pages should be designed with
the 256-colour visitor in mind.
Notice I said "simultaneously". Most computers can
display a wide range of colours but some, to conserve memory,
define a "palette" of 256 colours for use at any one
time. Once this is defined, the colour of any one pixel can be
specified by an index number from 1 to 256 (actually from 0 to
255), rather than having to list the RGB components separately.
If your screen is limited to 256 colours, you might occasionally
load an image in a window, only to find that other windows change
colour, often with disturbing results. That's because the new
image has reassigned the palette: it uses a particular shade
of lime green that wasn't previously in the palette, so it's stolen
a palette index to represent that colour. Unfortunately, every
other pixel on the screen with that index has become lime green,
and the Mona Lisa's smile has suddenly become all the more enigmatic.
If your screen is limited to 256 colours, you may find this effect
unpleasant: if you design web pages, you should be wary of inflicting
it on your visitors.
For many years ("many" being a relative term in this
business), Netscape produced far and away the world's most popular
web browser. They had their own standard palette for use on 256-colour
machines and, because of their market dominance, it became the
de facto industry standard.
The Netscape colour palette is based around the assumption that
colours displayed on a computer screen can contain red, green
and blue components each in the range 0 to 255. If the three
components (R, G, B) are (0, 0, 0), the result is black; (R,
G, B) = (255, 255, 255) gives white. (255, 0, 0) is a bright
red, (0, 255, 0) a bright green and (0, 0, 255) a bright blue.
More subtle colours are obtained by mixing different proportions
of the three primary colours. With three components, each with
256 different values to choose from, the total number of colours
available is (256 x 256 x 256), or 16,777,216 (often called "16.8
million").
The Netscape colour palette is based around the (rather fortuitous)
fact that 255 is 5 x 51. If the red, green and blue components
are constrained to take values that are multiples of 51 (or 0),
each can have six different values: 0, 51, 102, 153, 204 or 255.
With six possibilities for each of the three components, the
number of colours available is (6 x 6 x 6), or 216. This, conveniently,
gives web page designers the majority of a 256-colour palette
to play with, while leaving a few colours at the disposal of the
operating system of the visitor.
|
|
Hexadecimal numbers
|
|
When designing graphics in a painting program, you can choose
your colours by defining RGB components in good old decimal numbers.
In HTML, however, you have to grapple with the (for many people)
alien concept of hexadecimal numbers. These are not "codes",
they are numbers - just represented in an unfamiliar way.
An example might be <BODY BGCOLOR="#99FF99">,
or <BODY BGCOLOR=#FFFFFF LINK=#00CCCC ALINK=#FF0000 VLINK=#FFFFCC>.
Just what do these weird combinations of digits and letters mean?
Hexadecimal numbers seem daunting at first, but in fact learning
about them is no more conceptually difficult than when you first
learned about the number system with which we are all familiar.
If you can cope with the idea of counting 1, 2, 3, 4, 5, 6, 7,
8, 9, 10, 11, 12, etc., all you need to grasp is that there
is nothing special about the number "ten".
Early in life, we all get taught that numbers go from 0 to 9,
then the "tens digit" appears. The "units digit"
then repeats the sequence from 0 to 9, then the "tens digit"
increases to 2. The process repeats up to 99, and the "hundreds
digit" introduces itself. This mechanism is truly one of
the greatest inventions of humankind, but it instils in us the
belief that the number ten is magic in some way, which
it is not. If we each had eight fingers, we might now count 1,
2, 3, 4, 5, 6, 7, 10, 11, 12, etc., and consider that to
be obviously right.
The number ten is known as the base of our everyday, or
decimal number system. Other bases in common use, particularly
in association with computers, are two (binary), eight (octal)
and sixteen (hexadecimal).
To explain these, I'd first like to review the decimal system,
and point out some features of it that we all tend to take for
granted. Take a decimal number, 1234, for instance. That represents
one thousand, plus two hundreds, plus three tens, plus four ones
(units). Reading from right to left, we begin with units, then
tens (the base of the number system. The next digit represents
hundreds because one hundred is ten times ten. The next
digit is thousands (ten times ten times ten). For larger numbers,
this can be extended, literally if not practicably, ad infinitum.
Octal numbers are very similar to decimal numbers, except that
where decimal digits represent, from right to left, increasing
powers of ten, octal digits represent increasing powers of eight.
Here, as elsewhere in this page, the language can be confusing,
since the word "digit" itself carries connotations of
the number ten.
Now consider the octal number 1234. From right to left, this
represents four units, plus three eights, plus two times
eight times eight, plus one time eight times eight times eight.
This is where the language becomes very confusing. Notice I
said "eight times eight": that's sixty-four, isn't
it? Yes, but the names we assign to numbers are a consequence
of their representation in the decimal system. 64 (decimal) is
the same as 100 (octal). So what should we call it? People familiar
with the octal system might well say "one hundred octal"
or even "one hundred" (if the listener could be expected
to know that the number was octal). To avoid ambiguity, it is
safer to say "one zero zero octal".
The table on the right shows a few numbers in decimal and octal representations.
|
| Decimal | Octal |
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
| 4 | 4 |
| 5 | 5 |
| 6 | 6 |
| 7 | 7 |
| 8 | 10 |
| 9 | 11 |
| 10 | 12 |
| 11 | 13 |
| 12 | 14 |
| 13 | 15 |
| 14 | 16 |
| 15 | 17 |
| 16 | 20 |
| 17 | 21 |
| 18 | 22 |
| 19 | 23 |
| 20 | 24 |
| 24 | 30 |
| 32 | 40 |
| 40 | 50 |
| 64 | 100 |
| 100 | 144 |
| 512 | 1000 |
| 1024 | 2000 |
| 65536 | 200000 |
|
|
Notice that the digits "8" and "9" are not
used in the octal system. Because the base of the system is the
number eight, only eight different digits are used to represent
any number.
I started with the octal system, because it is relatively easy
to grasp. This next section is not essential to an understanding
of hexadecimal numbers, but it does help to understand why octal
and hexadecimal systems are so often used in the computer world.
The octal system shows that we don't need ten different digits
to represent all possible numbers - eight will do. So, can we
get away with even fewer? Yes, and most importantly (because
it is the basis of all digital computers), we can use only two,
in the binary system.
Computer memory is made up of lots and lots of switches. Each
switch can have one of two states: on or off. These are taken
to represent the digits 0 and 1. As you've seen, the base ten
number system requires ten different digits, and base eight requires
eight. Base two requires only two, 0 and 1. In fact, in base
two, they are no longer called "digits" but "bits",
for "binary digits".
In the binary system, the bits represent, from right to left,
units, twos, fours, eights, etc. A binary number might look like
1111101000. Only two different digits, but a lot of them! Reading
from right to left, that's no units, no 2s, no 4s, one 8, no 16s
(forgive me for using decimal here, but I'm sure you don't want
to go on reading "two times two times two times
"),
one 32, one 64, one 128, one 256 and one 512. Add them up and,
voila: one thousand (decimal). Yes, it takes no fewer than ten
bits to represent even the smallest 4-digit decimal number. Binary
may only use two different symbols, but it uses an awful lot of
them, and is very difficult to read. On the right are a few comparisons.
|
| Decimal | Octal | Binary |
| 1 | 1 | 1 |
| 2 | 2 | 10 |
| 3 | 3 | 11 |
| 4 | 4 | 100 |
| 5 | 5 | 101 |
| 6 | 6 | 110 |
| 7 | 7 | 111 |
| 8 | 10 | 1000 |
| 1000 | 1750 | 1111101000 |
| 65535 | 177777 | 1111111111111111 |
|
|
So binary numbers are cumbersome and difficult to read (but essential
for computers). How do people who have to deal with computers
(at a low level) cope with binary numbers? The answer is that
they don't directly; they convert them to another, more compact,
number base. Converting between binary and decimal is tricky:
that's why they use octal and hexadecimal!
Take a look at the binary representation of 1000 (decimal). To
convert it to decimal, you have to recognise that it represents
512 + 256 + 128 + 64 + 32 + 8 = 1000 - that's clumsy. Because eight is
itself a power of two, however, it's relatively easy to convert
the same number to octal. Since eight is equal to two times two
times two, a binary number can be partitioned (from right to left)
in groups of three bits, and each group individually converted
to an octal digit. Thus [00]1 | 111 | 101 | 000 becomes 1|7|5|0, becomes
1750 octal.
The octal system is quite good at reducing binary numbers to something
less cumbersome, but it has one slight drawback. The bits in
computers are usually grouped together in multiples of eight (bytes),
which themselves are usually clumped in words of two or
more bytes. Take that last number in the table above, 65535 (decimal)
or 11111111 11111111 (binary). Convert that to octal, and you
get 177777. This is sixteen bits, or two bytes. But what is
the value of the first byte, and what is the second? In this
case it's easy, because all the bits are 1. In any case, it's
easy to partition the binary into two bytes, but what about the
octal? The problem is that one of the octal digits (the third
"7" in this case) contains the last bit of the first
byte and the first two bits of the second byte. This kind of
problem is bound to arise if you take groups of eight bits and
start partitioning them into groups of three, because eight is
not divisible by three. Wouldn't it be better if we had a number
system where each digit represented four bits, rather than three?
There is: it's hexadecimal.
Hexadecimal is base sixteen. Conversion between binary and hexadecimal
is easy, like conversion between binary and octal, because the
binary numbers can be partitioned into groups, each of which represents
a hexadecimal digit. It's better than octal, in that each of
those groups contains four bits, rather than three, and so will
always line up with "byte boundaries" every eight bits.
But there's a problem in writing hexadecimal numbers. Remember
that the decimal system requires ten different digits: 0, 1,
2, 3, 4, 5, 6, 7, 8, 9. Octal, being base eight uses only the
first eight of those, and binary only the first two. The hexadecimal
system needs sixteen different digits. The first ten are obvious:
they are the same as the familiar decimal ones; but what are
we to use for the last six? Easy: just turn to the alphabet.
Look at the table on the right.
|
| Decimal | Octal | Binary | Hexadecimal |
| 0 | 0 | 0000 | 0 |
| 1 | 1 | 0001 | 1 |
| 2 | 2 | 0010 | 2 |
| 3 | 3 | 0011 | 3 |
| 4 | 4 | 0100 | 4 |
| 5 | 5 | 0101 | 5 |
| 6 | 6 | 0110 | 6 |
| 7 | 7 | 0111 | 7 |
| 8 | 10 | 1000 | 8 |
| 9 | 11 | 1001 | 9 |
| 10 | 12 | 1010 | A |
| 11 | 13 | 1011 | B |
| 12 | 14 | 1100 | C |
| 13 | 15 | 1101 | D |
| 14 | 16 | 1110 | E |
| 15 | 17 | 1111 | F |
|
|
Here, I've added all the leading zeroes, so you can see that every
possible permutation of four bits can be represented by a single
hexadecimal digit.
How does all this relate to colours on a web page? Read on.
|
|
Specifying colours in HTML
|
|
In all those HTML tags where colours are represented in the form
"#RRGGBB", the "#" prefix simply signifies
that what follows is a hexadecimal number. The first two digits
represent the red component in the range 0 to FF (hexadecimal)
or 0 to 255 (decimal); the next two are the green component, and
the last two the blue.
|
|
Choosing the right colour
|
|
Even with all this background, it's not obvious what a given
combination of red, green and blue components will look like. To
help with this, I've written the following Java applet. It's very
rough around the edges, and I gave up trying to improve it when I
learned that Java security would not allow an applet like this to
copy to the clipboard. Still, I'd welcome any
comments.
|
|
|
|
|
A Microsoft Windows version of this is also available for you to
download (299 kB). This is rather more
mature than the Java version.
|
|
|