Set the CSS-only clock with the HTML <time> element
A few weeks ago I published a post on building a CSS-only Analog Clock:
I also posted a follow-up post on converting it to a Digital Clock:
The feedback I received was that it is not really a settable clock as the values are all hard-coded in CSS.
We all know that:
HTML and CSS simply do not have access to the machines local time so there is no way for us to fetch the current time without JavaScript.
We could, however, move the hard-coded time from CSS and to HTML into a <time>
element to make this definition have some assigned semantic value.
<time>
MDN Web Docs confirms that the <time>
element is probably the best way to capture time in HTML.
The
<time>
HTML element represents a specific period in time. It may include thedatetime
attribute to translate dates into machine-readable format, allowing for better search engine results or custom features such as reminders.
To capture the current time correctly in HTML, we could do something like this:
<time id="time" datetime="2021-11-29T03:58">Now</time>
The CSS clock used two Custom Properties to start the clocks at a specific time:
--setTimeHours: 3;
--setTimeMinutes: 58;
With these settings added to the :root
context, the CSS clock would start at exactly 3:58.
So how could we use the ISO date value in the datetime=""
attribute of the <time>
element to set the CSS Custom Properties?
Attribute selectors
Since we are not building a calendar, we can simply ignore the date for now. All we are interested in are the hours and minutes. Probably the best we can do is try and use the CSS Attribute Selectors.
With the current example of 3 hours and 58 minutes, we could select the element when the hour value is 3 and then set the setTimeHours
custom property to 3:
[datetime*="T03"] ~ .clock {
--setTimeHours: 3;
}
This specific attribute selector basically says: “match any element with “T03” appearing anywhere in the datetime
attribute value”. This would match our current <time>
element and would set the hour custom property to 3.
The general sibling selector (~
) selects the .clock
element that appears after the <time>
element in the HTML hierarchy within the same level (siblings). This will set the custom properties to the clock's own scope.
We can do the same thing with the minute:
[datetime*=":58"] ~ .clock {
--setTimeMinutes: 58;
}
This works similarly, we just changed the attribute selector to match an attribute value with “:58” in it.
Now, this will obviously only work if the time inside the attribute is exactly “T03:58”. To generate all the other selectors for all the other combinations, you need to repeat this for the hours 1–12 and for minutes 0 to 59. There is no other way which is not ideal, but we can ask some help from a pre-processor, like SCSS to perform this for us:
@for $i from 0 through 9 {
[datetime*="T0#{$i}"] ~ .clock { --setTimeHours: #{$i} }
}@for $i from 10 through 24 {
[datetime*="T#{$i}"] ~ .clock { --setTimeHours: #{$i} }
}@for $i from 0 through 9 {
[datetime*=":0#{$i}"] ~ .clock { --setTimeMinutes: #{$i} }
}@for $i from 10 through 60 {
[datetime*=":#{$i}"] ~ .clock { --setTimeMinutes: #{$i} }
}
Notice, how we had to add an extra case for both the hours and minutes to handle single and double-digit values with the leading 0s.
And that is it! This will now automatically set the CSS-clock to any time added to the <time>
HTML element encoded as an ISO date-time.
Let me know what you think!