Dark mode switch using HTML5 and CSS - javascript

I have this simple code to turn a webpage into dark/light mode. It works fine on the page you are, but if I click any links or buttons to redirect me from index.html to test.html for example, then the settings resets to default. Let's say I want to browse my page in light mode, and lick test button it goes back to dark mode.
How do I make it remember to stay in the same mode I choose? Here is what I got.
Index.html
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>Dark -Light Mode Switcher</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<body id="body" class="dark-mode">
<h1>Dark/Light Mode Switcher</h1>
<button type="button" name="dark_light" onclick="toggleDarkLight()" title="Toggle dark/light mode">🌛
</button>
<p><button name="test">TEST PAGE</font></button>
<!-- partial -->
<script src="./script.js"></script>
</body>
</html>
Script.js
function toggleDarkLight() {
var body = document.getElementById("body");
var currentClass = body.className;
body.className = currentClass == "dark-mode" ? "light-mode" : "dark-mode";
}
Style.css
body.dark-mode {
background-color: #111;
color: #eee;
}
body.dark-mode a {
color: #111;
}
body.dark-mode button {
background-color: #eee;
color: #111;
}
body.light-mode {
background-color: #eee;
color: #111;
}
body.light-mode a {
color: #111;
}
body.light-mode button {
background-color: #111;
color: #eee;
}

If you update your Script.js like below, you will obtain what you want :
body.className=localStorage.getItem("stateMode");
function toggleDarkLight() {
var body = document.getElementById("body");
var currentClass = body.className;
body.className = currentClass == "dark-mode" ? "light-mode" : "dark-mode";
localStorage.setItem("stateMode",body.className);
}

Related

Load stylesheet with javascript and localStorage

I'm using a Jekyll website, doesn't really matter because this is a static page, I just write it as additional info.
Desired behavior:
I want to load my stylesheet via javascript, so it can depend of a local stored value, let's say dark and light.
I have done a little test of loading it by JS with the following code (which works).
GREEN
<head>
...
<link rel="stylesheet" href="/assets/css/{{'light'}}.css">
...
</head>
This loads the CSS file called "light" as expected.
But now I want to depend of the localStorage, with a variable theme that has light as value. I tried the following:
RED
<head>
...
<script>
var storedTheme = window.localStorage.getItem('theme'); //Tested and working in console
theme = storedTheme ? storedTheme : 'light'; //global variable (also readable in console)
</script>
<link rel="stylesheet" href="/assets/css/{{theme}}.css"> <!-- cant read global variable -->
...
</head>
Using global variables doesn't work, it gives me a 404 error as the stylesheet path is /assets/css/.css.
After that I thought that maybe creating an element would do the trick and I created one manually to test it:
RED
<head>
...
<p id="theme" style="display:none;">dark</p>
<link rel="stylesheet" href="/assets/css/{{document.getElementById('theme').innerHTML}}.css">
...
</head>
And nope, the path still appears as: /assets/css/.css
If you change styles on the <body> you get FOUC (Flash Of Unstyled Content). Try using a close equivalent like <main> and spread it 100% x 100% and <html> and <body> as well, but give them margin and padding of 0 in order to ensure <main> covers them completely.
The [disabled] attribute for the <link> is the best way of toggling them because they are still loaded but inert. Also, in the example there is a function called loadTheme(e) that is loaded on the 'DOMContentLoaded' event which insures that all of the DOM is loaded before hand. The example below will not work because localStorage is blocked on SO. There is a functioning example on Plunker. To test it:
Click the green Preview button.
Another frame should appear on the right. Within the frame is the webpage example click the ☀️ button.
It should be in dark mode now. Next, click the refresh ⟳ button located in the mini-toolbar within the frame or press ctrl+enter for Windows OS or ⌥+return for Mac OS.
The page should still be in dark mode. 👍
/* night.css
main {
background: #000;
color: #fff;
}
*/
/* default.css */
:root {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
font: 1ch/1.5 'Segoe UI';
}
body {
height: 100%;
width: 100%;
margin: 0;
padding: 0;
font-size: 4ch;
}
main {
height: 100%;
width: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
color: #000;
}
form {
width: 80vw;
margin: 20px auto;
}
fieldset {
width: max-content;
min-height: 25px;
margin-left: auto;
padding: 0 1.5px 1.5px;
border-radius: 8px;
background: inherit;
color: inherit;
}
button {
display: block;
width: 100%;
height: 100%;
border: 0;
font-size: 4rem;
text-align: center;
background: transparent;
cursor: pointer;
}
#theme::before {
content: '☀️';
}
.night #theme::before {
content: '🌙';
}
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href='lib/default.css' rel='stylesheet'>
<link class='night' href='lib/night.css' rel='stylesheet' disabled>
<style></style>
</head>
<body>
<main>
<form id='UI'>
<fieldset name='box'>
<legend>Theme</legend>
<button id='theme' type='button'></button>
</fieldset>
<p>Click the "Theme" switch to toggle between `disabled` `true` and `false` on `night.css` and `light.css` `
<link>`s.</p>
</form>
</main>
<script>
const UI = document.forms.UI;
const M = document.querySelector('main');
const L = document.querySelector('.night')
const switchTheme = e => {
const clk = e.target;
if (clk.matches('button')) {
M.classList.toggle('night');
L.toggleAttribute('disabled');
}
let status = M.className === 'night' ? 'on' : 'off';
localStorage.setItem('theme', status);
};
const loadTheme = e => {
let cfg = localStorage.getItem('theme');
if (cfg === 'on') {
M.classList.add('night');
L.removeAttribute('disabled');
} else {
M.classList.remove('night');
L.setAttribute('disabled', true);
}
};
UI.addEventListener('click', switchTheme);
document.addEventListener('DOMContentLoaded', loadTheme);
</script>
</body>
</html>

JavaScript background color change function does not interact with the html button

this is my first time using StackOverflow, so I still don't know how to use the code snippets properly.
I am still a beginner into programming and chose to start with the front-end side, i've done an orange background with "this is the red heading" written in red, it worked.
however, I'm trying to make a button that when it's clicked, only the background color changes from orange to yellow, but the button doesn't do anything at all.
here's the code("estilo" is the name of the CSS file and "responsividade" is the name of the JS file):
function changeColor() {
document.getElementById("redhead").style.backgroundColor = "yellowbg";
}
#redhead {
background-color: orange;
color: red;
padding: 40px;
text-align: center;
}
#yellowbg {
background-color: yellow;
padding: 40px;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
<body>
<link rel="stylesheet" href="estilo.css">
<script src="responsividade.js"></script>
<h1 id="redhead">this is the red heading</h1>
<button type="button" onclick="changeColor()">Click Here</button>
</body>
</head>
</html>
Here: document.getElementById("redhead").style.backgroundColor = "yellow"; you are trying to assign a css class name to the backgroun color property.
function changeColor() {
document.getElementById("redhead").style.backgroundColor = "yellow";
}
#redhead {
background-color: orange;
color: red;
padding: 40px;
text-align: center;
}
#yellowbg {
background-color: yellow;
padding: 40px;
text-align: center;
}
<!DOCTYPE html>
<html>
<head> </head>
<body>
<link rel="stylesheet" href="estilo.css">
<script src="responsividade.js"></script>
<h1 id="redhead">this is the red heading</h1>
<button type="button" onclick="changeColor()">Click Here</button>
</body>
</html>
if you want to change color try document.getElementById("redhead").style.backgroundColor = "yellow";
or if you want to set another id try
document.getElementById("redhead").setAttribute('id', 'yellowbg');
You have written your code in the head tag.
In background-color value given as yellowbg.
function changeColor() {
document.getElementById("redhead").style.backgroundColor = "yellow";
}
#redhead {
background-color: orange;
color: red;
padding: 40px;
text-align: center;
}
#yellowbg {
background-color: yellow;
padding: 40px;
text-align: center;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<link rel="stylesheet" href="estilo.css">
<script src="responsividade.js"></script>
<h1 id="redhead">this is the red heading</h1>
<button type="button" onclick="changeColor()">Click Here</button>
</body>
</html>
#yellowbg ruleset all properties are there in #readhead ruleset except background-color so in js, you can just update background color only.
const colorChanger = {
'eq' : 0,
'change' : function(targetID, colorCircles) {
document.getElementById(targetID).style.backgroundColor = colorCircles[this.eq];
this.eq = (this.eq === colorCircles.length-1) ? 0:this.eq += 1;
}
}
#test{
border :1px solid #000;
width :100px;
height :100px;
}
<div id="test"></div>
<button onclick="colorChanger.change('test', ['red','yellow', 'green', 'blue', 'purple'])">Change Color</button>
<!--
colorChanger.change('test', ['red','yellow', 'green', 'blue', 'purple']
------------------------------------------------------
>target is something with id 'test'
>and background color of target ID will be change using this circles ['red','yellow', 'green', 'blue', 'purple']
-->
In your Js function you need to a background color as you trying to do.
document.getElementById("redhead").style.backgroundColor = "yellowbg";
"yellowbg" is not a color but an Id.
So you need to change that to
document.getElementById("redhead").style.backgroundColor = "yellow";
You can add css property to a class of an element and with js change the class name to add different property to that element.
document.getElementById("redhead").className = "newClass";

Change form values using JavaScript

I have been asked to change text and style of a specific button within a form after a submit.
JavaScript
openWarningBox(
"/URL",
[{
'classNames':'button sec',
'text':'Continue',
'clickEvent': function() {
$(document.forms.button).trigger('submit');
}
}]
);
HTML
<form name="button" onsubmit="location.href='/URL'; return false;"></form>
I am aware this is done in a weird/wrong way and if it was written properly it would not have been an issue, but is there some way for me to change that button's classNames and text after it is being submitted?
I am not sure if this is what you are looking for but I used the DOM to change the button text and style you can also change the font that way. The DOM seems like a good option to accomplish this task.
var btn = document.getElementById('btn')
btn.addEventListener('click', change)
function change(e){
e.preventDefault()
btn.style.backgroundColor = 'blue';
btn.style.border = 'blue';
btn.style.colr = 'black';
btn.style.borderRadius = '26px';
btn.innerHTML = 'Submitted'
}
button{
background-color: #4CAF50; /* Green */
border: none;
color: white;
padding: 15px 32px;
text-align: center;
text-decoration: none;
display: inline-block;
font-size: 16px;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<button type="submit" id='btn'>Submit</button>
</body>
</html>

Why doesn't this code display the button after I hide it?

When I run this JavaScript code, button2 doesn't get displayed again. I'm not sure why this is happening. I am trying to use this in a game I am creating. I searched this up on Google multiple times and couldn't find an answer.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style type="text/css">
.btn1 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
}
.btn2 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
display: none;
}
</style>
</head>
<body>
<button class="btn1" onclick="showBtn2()">
Show Button 2
</button>
<button class="btn2" id="btn2"></button>
</body>
<script type="text/javascript">
const btn2 = document.getElementById("btn2");
function showBtn2() {
btn2.style.display = "auto";
}
</script>
</html>
A good way to handle this and provide more reusable code is to use <element>.classList.remove() and <element>.classList.add() to set or unset a hidden class. This can also be useful for toggling with <element>.classList.toggle().
This has the added advantage of being able to set your default display style in the CSS rather than burying it in the javascript.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style type="text/css">
.btn1 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
}
.btn2 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
/* allows setting preferred display in CSS */
display: block;
}
.hidden {
display: none;
}
</style>
</head>
<body>
<button class="btn1" onclick="showBtn2()">
Show Button 2
</button>
<button class="btn1" onclick="toggleBtn2()">
Toggle Button 2
</button>
<button class="btn2 hidden" id="btn2">Button 2</button>
</body>
<script type="text/javascript">
const btn2 = document.getElementById("btn2");
function showBtn2() {
btn2.classList.remove("hidden");
}
function toggleBtn2() {
btn2.classList.toggle("hidden");
}
</script>
</html>
There is no auto display is CSS. As tarkh mentioned in his answer, display block would insert the new button below the initial button, and other display options would have other behaviors. But the display property does not have a value auto.
This may be my opinion, but I think modern websites shouldn't use the onclick function for events. We should separate our HTML, JS and CSS. This helps with reusability. https://en.wikipedia.org/wiki/Unobtrusive_JavaScript
So I would create a solution that uses an event handler in the Javascript. Something like:
window.onload = function(){
const btn2 = document.getElementById("btn2");
const btn1 = document.getElementsByClassName("btn1");
for(let i = 0; i < btn1.length; i++) {
btn1[i].addEventListener('click', function(){
btn2.style.display = "block";
})
}
}
Maybe btn2.style.display = "block";?
Or, as #charlietfl added, btn2.style.display = "inline"; since that is what browser default is for a button
display: block means that the element is displayed as a block, as
paragraphs and headers have always been. A block has some whitespace
above and below it and tolerates no HTML elements next to it, except
when ordered otherwise (by adding a float declaration to another
element, for instance).
display: inline means that the element is displayed inline, inside the
current block on the same line. Only when it's between two blocks does
the element form an 'anonymous block', that however has the smallest
possible width.
.btn1 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
}
.btn2 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
</head>
<body>
<button class="btn1" onclick="showBtn2()">
Show Button 2
</button>
<button class="btn2" id="btn2">new button here</button>
</body>
<script type="text/javascript">
const btn2 = document.getElementById("btn2");
function showBtn2() {
btn2.style.display = "block";
}
</script>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style type="text/css">
.btn1 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
}
.btn2 {
background-color: white;
border: 2px solid black;
border-radius: 12px;
display: none;
}
</style>
</head>
<body>
<button class="btn1" onclick="showBtn2()">
Show Button 2
</button>
<button class="btn2" id="btn2">Button 2</button>
<script type="text/javascript">
const btn2 = document.getElementById("btn2");
function showBtn2() {
btn2.style.display = "inline";
}
</script>
</body>
</html>
Use display = inline or block instead of auto.
Add some text content to button 2 like this:
<button class="btn2" id="btn2">Button 2</button>
CSS: "display: auto;"?
display does not have an auto attribute.
you can try "inline" or "block".
'''
function showBtn2() {
btn2.style.display = "inline";
}
'''
Try using
btn2.style.display = "block";
for your script because css display doesn't have that kind of attribute you
you can read it more here : more
you'll see there's no such thing as display:auto

When I click the dark mode button, I want to apply the dark mode to the iframe tag as well

Currently I am studying the dark mode function.
I have a question while studying the dark mode feature.
Clicking the dark mode button changes other tags, but not the iframe tag.
I want to apply dark mode to iframe tag as well.
What should I do?
The source below is the source in the file.
01. file : index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<style>
iframe {
margin:0;
padding:0;
}
.layout-01 {
border: 1px solid #ddd;
padding:10px;
margin-bottom: 20px;
background: var(--bg-color);
color: var(--font-color);
}
.iframe-layout {
border: 1px solid #ddd;
background: var(--bg-color);
color: var(--font-color);
}
.iframe-layout iframe html p {
color: var(--font-color);
}
:root {
--bg-color: #fff;
--font-color: #000;
}
html.darkmode:root {
--bg-color: #000;
--font-color: #fff;
}
</style>
</head>
<body>
<div>
<button onClick="userTheme(true);">Toogle Theme</button>
</div>
<script>
function userTheme(toggle = false) {
let userMode = localStorage.userThemeMode || 'auto';
const osMode = !!window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? 'dark' : 'light';
if(toggle) {
switch(userMode) {
case 'auto':
userMode = 'dark'; break;
case 'dark':
userMode = 'light'; break;
default:
userMode = 'auto';
}
localStorage.userThemeMode = userMode;
}
console.log(`current mode : ${userMode}`);
window.__THEME_MODE = userMode === 'auto' ? osMode : userMode;
document.getElementsByTagName('html')[0].classList[window.__THEME_MODE === 'dark' ? 'add' : 'remove']('darkmode');
//document.querySelectorAll('iframe')[0].classList[window.__THEME_MODE === 'dark' ? 'add' : 'remove']('darkmode');
}
if (!!window.matchMedia) {
['light', 'dark'].forEach(mode => {
window.matchMedia(`(prefers-color-scheme: ${mode})`).addListener(e => {
if(!!e.matches) {
userTheme();
}
});
});
}
userTheme();
</script>
<div>
<div class="layout-01">
<p>text</p>
</div>
<div i="iframe-layout">
<iframe src="test.html" frameborder="0" sandbox="allow-same-origin allow-scripts" seamless></iframe>
</div>
</div>
</body>
</html>
02. test.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<style>
iframe {
margin:0;
padding:0;
}
.layout-01 {
border: 1px solid #ddd;
padding:10px;
margin-bottom: 20px;
background: var(--bg-color);
color: var(--font-color);
}
.iframe-layout {
border: 1px solid #ddd;
background: var(--bg-color);
color: var(--font-color);
}
.iframe-layout iframe html p {
color: var(--font-color);
}
:root {
--bg-color: #fff;
--font-color: #000;
}
html.darkmode:root {
--bg-color: #000;
--font-color: #fff;
}
</style>
</head>
<body>
<div>
<button onClick="userTheme(true);">Toogle Theme</button>
</div>
<script>
function userTheme(toggle = false) {
let userMode = localStorage.userThemeMode || 'auto';
const osMode = !!window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches ? 'dark' : 'light';
if(toggle) {
switch(userMode) {
case 'auto':
userMode = 'dark'; break;
case 'dark':
userMode = 'light'; break;
default:
userMode = 'auto';
}
localStorage.userThemeMode = userMode;
}
console.log(`current mode : ${userMode}`);
window.__THEME_MODE = userMode === 'auto' ? osMode : userMode;
document.getElementsByTagName('html')[0].classList[window.__THEME_MODE === 'dark' ? 'add' : 'remove']('darkmode');
//document.querySelectorAll('iframe')[0].classList[window.__THEME_MODE === 'dark' ? 'add' : 'remove']('darkmode');
}
if (!!window.matchMedia) {
['light', 'dark'].forEach(mode => {
window.matchMedia(`(prefers-color-scheme: ${mode})`).addListener(e => {
if(!!e.matches) {
userTheme();
}
});
});
}
userTheme();
</script>
<div>
<div class="iframe-layout">
<p>sdfsdfsdf</p>
</div>
</div>
</body>
</html>
You can take the following approach:
On click of the dark mode button, change the URL of iframe by passing a query parameter. For eg: www.example.com?theme=dark.
Within iframe, use JS to retrieve the query parameter. Based on the parameter, add/remove the css class which would affect the theme of the iframe. For eg:
let theme = 'dark' //Get this from URL
let class = theme=='dark'?'dark-theme-class':'default-theme';
document.body.classList.toggle(class);
This should work in your case.
Use the CSS filter: invert() property.
Check out
the CSS invert,
CSS invert summary &
the CSS filter on MDN.
This snippet should show what I mean.
const iframes = document.querySelectorAll('iframe');
function toggleTheme() {
for (i = 0; i < iframes.length; i++) {
iframes[i].classList.toggle('is-dark');
}
}
.is-dark {
filter: invert(80%);
}
<!doctype html>
<html lang="en">
<body>
<button onClick="toggleTheme();">Toogle Theme</button>
<iframe id="the-iframe" src="https://wikipedia.org/"></iframe>
</body>
</html>
In a similar fashion, you can apply a sepia filter as shown in the following snippet.
const iframes = document.querySelectorAll('iframe');
function toggleTheme() {
for (i = 0; i < iframes.length; i++) {
iframes[i].classList.toggle('is-sepia');
}
}
.is-sepia {
filter: sepia(100%);
}
<!doctype html>
<html lang="en">
<body>
<button onClick="toggleTheme();">Toogle Theme</button>
<iframe id="the-iframe" src="https://wikipedia.org/"></iframe>
</body>
</html>

Categories

Resources