Chris DeLuca

The blog of the person

My artsy-fartsy css web experiment

The other day I had some time in between work and an improv show I was doing that night, so to pass the time, I created a simple web experiment in CSS.

I call it, Day and Night.

The quick pitch is that you can control the sun with your mouse, and if you bring the sun down behind the hills in the foreground, the scene changes from day to night.

Night and Day screenshot

Night and Day screenshot

The experiment is written entirely in HTML, CSS, and JavaScript. You can check out the code on GitHub.

The Guts and Gears

The HTML is very simple. There’s a div for the sun, and both hills, and the body serves as the sky.

<body id="sky" class="sky">
  <div id="sun" class="sun"></div>
  <div class="hills-wrapper">
    <div id="hill-background" class="hill-background"></div>
    <div id="hill-foreground" class="hill-foreground"></div>
  </div>
</body>

I used Sass to keep my styles organized and badass, and I used percentage widths and heights for all the elements, except for the sun, to keep things mobile friendly.

Next, I stuck the hills to the bottom of the page.

.hills-wrapper {
  position: relative;
}
.hill-background,
.hill-foreground {
  position: fixed;
  width: 100%;
  bottom: 0;
}

I made use of border-radius to make the hills look like, well, hills, instead of color swatches, in addition to the sun, to make it look round instead of dumb.

I wrote a color scheme for day and night, taking advantage of the compass shade mixin as much as looked good. I also made use of adjoining classes to define the night colors (stay tuned for how they’re utilized in a moment), to a) keep things clean and easy to read, and b) to flip a big ol’ bird to IE6 (seriously, why does CSSLint still consider them a bad practice? Let IE6 die!).

/* variables */
$night_sky : #001f3f;
$night_clouds : shade($clouds, 70%);
$night_grass : shade($grass, 70%);
/* classes */
.sky.night { background-color: $night_sky; }
.clouds.night { background-color: $night_clouds; }
.hill-background.night { background-color: darken($night_grass, 3); }
.hill-foreground.night { background-color: $night_grass; }

Moving on the the JavaScript, I first attached the sun div to mouse movement. Hello addEventListener firing on mousemove.

// Mouse move event listener.
document.addEventListener('mousemove', function(e) {
  var top = e.clientY - 100,
  left = e.clientX - 100,
  aboveTheHills;
  // Stick the sun to the cursor.
  sun.setAttribute('style', 'left:' + left + 'px;top:' + top + 'px');

Finally, I needed to detect if the sun was below the hills. The method I came up with isn’t perfect, since the sun can still be peaking out from behind the rounded hills, but it would be way to hard to teach the DOM how to “see” if the sun was visible.

However, my solution does consistantly change from day to night, no matter the screen size, with the power of math!

 // Detect night.
aboveTheHills = window.innerHeight - hillBg.clientHeight + (sun.clientHeight / 2);
if (e.clientY > aboveTheHills) {
  // It's night.
  sky.className = 'sky night';
  hillBg.className = 'hill-background night';
  hillFg.className = 'hill-foreground night';
}
else {
  // It's day.
  sky.className = 'sky';
  hillBg.className = 'hill-background';
  hillFg.className = 'hill-foreground';
}

Finish it off by adding a background-color transition to all the effected elements, and you get to be the god of the sun!