Automatic night mode with vanilla JS
Today, I live-coded an automatic night mode feature using vanilla JS (video and text write-up below).
For this project, I want to detect the time where the user is located, and display a time-aware greeting and color palette. Let’s dig in.
The template
My starting HTML looks like this.
<p id="greeting"></p>
Inside the empty #greeting
element, I want to display a customized greeting, like, “Good morning” or “Good afternoon”, based on the time of day where the visitor is.
I also want to update the UI at night, and in the morning/evening.
.night body {
background-color: #001f3f;
color: white;
}
.transitional body {
background-color: #f7f7f7;
}
I have a .night
class that uses a midnight blue color for the background instead of default white. For the morning and evening, I have a .transitional
class that makes the background gray to be a bit more gentle on the eyes.
You can download the source code on GitHub.
Watch me code this project
If you want, you can follow along while I figure this one out in real time. If you’re rather read about it, keep scrolling.
How it works
For this project, the first thing I did was use the new Date()
constructor to get a Date
object for the current user and their location. Then, I used the getHours()
method to get the hour of the day.
The getHours()
method returns the hour portion of the time as an integer, in 24-hour format.
This means that for 10am, it would return 10
, and for 10pm it would return 22
. This is really handy for what we’re trying to do.
// Get the time right now
var now = new Date().getHours();
I also used the querySelector()
method to get the #greeting
element.
// Get the #greeting element
var greeting = document.querySelector('#greeting');
Displaying a greeting
Now, let’s display a greeting based on the time of day.
I creating a getGreeting()
function that will return the greeting as a string. I’ll set the textContent
of my greeting
element to whatever it returns.
/**
* Get the greeting based on time
* @return {String} The greeting
*/
var getGreeting = function () {
// Code goes here...
};
// Set the greeting
greeting.textContent = getGreeting();
Inside the getGreeting()
function, I check to see what now
is. If it’s bigger than 20
(8pm), I return Good night!
. If it’s bigger than 17
(5pm), I return Good evening!
. And so on.
Because I use return
, once we find a match, nothing else in the function runs. If no match is found, Good morning!
is returned.
/**
* Get the greeting based on time
* @return {String} The greeting
*/
var getGreeting = function () {
if (now > 20) return 'Good night!'; // If it's after 8pm
if (now > 17) return 'Good evening!'; // If it's after 5pm
if (now > 11) return 'Good afternoon!'; // If it's after noon
return 'Good morning!'; // Default message
};
Updating the color palette
Next, I want to update the color palette based on the time. I created an adjustColorMode()
helper function, and run it when the page loads.
/**
* Adjust the color theme based on time
*/
var adjustColorMode = function () {
// Code goes here...
};
// Update color palette
adjustColorMode();
If now
is greater than 20
(8pm), I want to add the .night
class. I used the classList.add()
method for that. Then I ran return
so the rest of the function would not run.
If now
is greater than 17
or less than 11
(if it’s after 5pm or earlier than 11am), I added the .transitional
class instead.
/**
* Adjust the color theme based on time
*/
var adjustColorMode = function () {
// If it's nighttime, go dark mode
if (now > 20) {
document.documentElement.classList.add('night');
return;
}
// If it's morning or evening, go transitional
if (now > 17 || now < 11) {
document.documentElement.classList.add('transitional');
}
};
Updating throughout the day
If someone visits the site and stays there for a while, I want to periodically check the time and adjust the greeting and them as needed.
To do that, I first moved injecting the greeting and adjusting the color palette into a function, updateUI()
, which I run when the page loads.
/**
* Add a greeting and adjust the color palette
*/
var updateUI = function () {
// Set the greeting
greeting.textContent = getGreeting();
// Update color palette
adjustColorMode();
};
Then, I setup a setInterval()
method to run every 15 minutes. In it, I update the now
variable to the current time, then I run the updateUI()
function again.
// Update the UI on page load
updateUI();
// Check again every 15 minutes
setInterval(function () {
now = new Date().getHours();
updateUI();
}, 1000 * 60 * 15);
Finally, I need to remove any existing .transitional
or .night
classes before trying to update the color palette.
/**
* Adjust the color theme based on time
*/
var adjustColorMode = function () {
// Remove any existing classes
document.documentElement.classList.remove('transitional');
document.documentElement.classList.remove('night');
// If it's nighttime, go dark mode
if (now > 20) {
document.documentElement.classList.add('night');
return;
}
// If it's morning or evening, go transitional
if (now > 17 || now < 11) {
document.documentElement.classList.add('transitional');
}
};
And now, I have a time aware, automatically updating UI.