css Night Sky

Show Description

Hide Description

CSS NIGHT SKY: This CSS drawing shows the moon and almost 200 stars centered on the constellation Orion, all accurately positioned.

Hovering a star highlights it and displays a tooltip with the star name and the constellation it belongs to (though some are simply marked "miscellaneous").

The background is a css gradient.

The stars are absolutely-positioned divs, styled with the css border-radius property to make them round and the box-shadow property to give them a stary “glow.” Varying the width and height of the divs, as well as their background-color and box-shadow creates the stars’ different magnitudes.

There’s nothing particularly difficult about any of this. It’s just a matter of styling and positioning a whole bunch of elements. The challenge is to figure out the most efficient way of doing it.

Ideally, we’d like a stylesheet that would allow us to position an element anywhere we like in the x-y plane, with pixel precision — but without having to write separate classes for each and every pixel (the brute force method).

The brute force method is simple, but impractical. For example, with a 1000px wide by 800px tall window we could write classes defining the top and left positions of every pixel in the window:

.left-0-top-0 {left:0px; top:0px;} .left-0-top-1 {left:0px top:1px;} .left-0-top-2 {left:0px top:2px;} ... .left-0-top-800 {left:0px top:800px;} .left-1-top-0 {left:1px top:0px;} .left-1-top-1 {left:1px top:1px;} .left-1-top-2 {left:1px top:2px;} ... .left-1-top-800 {left:1px top:800px;} ... .left-2-top-0 {left:2px top:0px;} .left-2-top-1 {left:2px top:1px;} .left-2-top-2 {left:2px top:2px;} ... .left-2-top-800 {left:2px top:800px;}

and so on, all the way to

.left-1000-top-800 {left:1000px; top:800px;}

Example div:

<div class=".left-446-top-267"></div>

Needless to say, this would be ridiculously unwieldy; we would need more than 800,000 separate classes for our 1000px by 800px window. Of course, we could delete any unneeded classes (and there would be many), but still, making on-the-fly positional adjustments to the stars would be tedious.

Fortunately, there is a far more efficient solution. We can write separate left and top positional classes, one for each pixel, and then give each star div two classes:

.left-0 {left:0px;} .left-1 {left:1px;} .left-2 {left:2px;} ... .left-800 {left:800px;} .top-0 {top:0px;} .top-1 {top:1px;} .top-2 {top:2px;} ... .top-800 {top:800px;} example: <div class="left-234 top-468">

This reduces the number of positional classes needed to 1800, (actually 1802, since we're starting with 0) — a dramatic improvement, but still quite a lot. Can we do any better?

As it happens, we can. If we combine these left and top positional classes with a second css method of pushing elements around the screen, we can achieve another dramatic reduction in the total number of classes we need. That second method is to adjust the object’s margin-left and margin-top properties.

Consider: we can first roughly position an element with left and top positional classes in 10px increments:

.left-0 {left:0px;} .left-10 {left:10px;} .left-20 {left:20px;} ... .left-1000 {left:1000px;} .top-0 {top:0px;} .top-10 {top:10px;} .top-20 {top:20px;} ... .top-1000 {top:1000px;}

and then fine-tune the position in 1px increments with suitably-defined margin-left and margin-top classes:

.margin-left-0 {margin-left:0px;} .margin-left-1 {margin-left:1px;} .margin-left-2 {margin-left:2px;} ... .margin-left-9 {margin-left:9px;} .margin-top-0 {margin-top:0px;} .margin-top-1 {margin-top:1px;} .margin-top-2 {margin-top:2px;} ... .margin-top-9 {margin-top:9px;}

We only need 20 of these margin classes (ten each for margin-left and margin-right), and for our 1000px by 800px screen we would need only 100 left and 80 top classes, for a total of 200.

<div class="top-200 left-330 margin-left-4 margin-top-8">

[This div would be positioned at (204,338) in the xy plane.]

We could actually achieve greater efficiency by increasing the left and top positional classes increment from 10px to 20px, and adding the necessary margin classes from 11 to 20px: this reduces the total number of classes in our example from 200 to 110 (50 plus 40 plus 20), but these 20px increments might be less convenient to work with.

The downside to this method is that it is suitable only for fixed units like pixels or ems; percentages won’t work.