The idea
I saw the site What colour is it? and thought the concept was really cool. For whatever reason, visualization generators pique my interest. I wanted to alter the original to see a wider range of colors, and to play with the attr()
function in CSS' ::after
psuedo-element. I also wanted to add a slider just to allow the user to tweak the generated color.
See the Pen Time color by Aaron Holmes (@aholmes) on CodePen.
The HTML and CSS
First set the attribute on your element. I decided to call it data-text
.
<h1 id="time" data-text="00 : 00 : 00"></h1>
We only need two lines of CSS to get the attribute function to display.
h1::after
{
display:block;
content:attr(data-text);
}
Normally the content
attribute is set to a static string, but there's also the attr()
function that let's you use an attribute value on your element instead.
You can find more information about attr()
on MDN.
NOTE: Browser compatibility is sketchy at best. There are some gotchas to be careful of too.
Updating the content with JavaScript
There are no DOM API methods that let us access ::after
or ::before
psuedo-elements with JavaScript. We can at least use the attr()
function in conjunction with the setAttribute()
method or dataset
property to change the content of the psuedo-elements.
With the HTML element above, here's how we can change the value of the data-text
attribute. This change will then be rendered with our CSS rules to display new text in the psuedo-element.
var timeHeader = document.getElementById('time');
var time = "15:30:25";
if (timeHeader.dataset !== undefined)
{
timeHeader.dataset.text = time;
}
else
{
timeHeader.setAttribute('data-text', time);
}
Theoretically that should be all we need! With a little more code to set the correct time value on a loop, the site will show a new time every second.
A repaint issue on Chrome version 39.0.2171.95
My experiment didn't go perfectly. I discovered that changing the attribute value does not always trigger a repaint, and thus the new time would not display. I have not figured out exactly what caused this; it was sporadic, and I wonder if it's partly related to how codepen works.
Thankfully there's an easy way to trigger a repaint. It's not exactly the prettiest solution, but it does ensure the new time is displayed each second.
timeHeader.style.display='none';
timeHeader.offsetHeight;
timeHeader.style.display='';
A little extra
The original code uses the time values as the hexidecimal values for the background color. A time of 9 hours, 23 minutes, and 40 seconds give you the hex color #092340
.
Given that this will increment the 0th digit for each red, green, and blue hex value, we end up with a similar color for each second, minute, and hour.
If the time value is 09 23 40, then our RGB values are as follows.
Hex | Dec | Conversion | |
---|---|---|---|
Red | 0x09 | 9 | (0 * 16^1) + (9 * 16^0) |
Green | 0x23 | 35 | (2 * 16^1) + (3 * 16^0) |
Blue | 0x40 | 64 | (4 * 16^1) + (0 * 16^0) |
After 1 second, blue becomes 65, then 66, 67, 68, and so on. This is a very slow increase!
Additionally, because there are only 24 hours in a day, 60 minutes to an hour, and 60 seconds to a minute, our scale of colors is limited. Red ranges from 0 - 23, green 0 - 59, and blue 0 - 59.
Here's a visualization of all possible red, green, and blue values individually.
To get a wider range of colors, each hexidecimal string value can be flipped. For example, 9 is "09" as a string, and "90" flipped. Here's what our example above looks like with the values flipped.Hex | Dec | Flipped String | |
---|---|---|---|
Red | 0x09 | 9 | 90 |
Green | 0x23 | 35 | 53 |
Blue | 0x40 | 64 | 46 |
And here's the range of colors and the pattern in which they occur.