Given the below css style, how can I reset the background-color with javascript? Not just for the currently highlighted button, but for all those highlighted in the future?
#bottom_buttons > div.bottom_button.highlighted {
background-color: #343434;
}
For instance:
$("div.bottom_button.highlighted").css("background-color", "#e67300");
this works, but is overwritten as soon as the page changes. IE loses focus or updates.
Similarly
document.getElementById("bottom_button_" + button).style.backgroundColor = "#e67300";
works to change the numbered button on click, but also doesn't last.
It's going to be difficult to have persistent changes in CSS from page to page with a refresh. That being said you can do it with local storage.
Here's how you do it :
function overwriteStyles(styles) {
var styleOverwrites = document.getElementById('style-overwrites');
if (styleOverwrites === null) {
styleOverwrites = document.createElement('style');
styleOverwrites.id = 'style-overwrites';
document.head.appendChild(styleOverwrites);
}
styleOverwrites.innerHTML = styles;
// Save styles to local storage
localStorage.setItem('overridden-styles', styles);
}
// Here styles are grabbed from local storage and loaded for persistence
document.addEventListener("DOMContentLoaded", function(event) {
var styles = localStorage.getItem('overriden-styles');
if(styles != null)
{
overwriteStyles(styles);
}
});
// Example of overwriting styles
overwriteStyles(`
#bottom_buttons > div.bottom_button.highlighted {
background-color: #e67300;
}
`);
Related
Currently I am practicing doing a light/dark mode button for a website I am building with HTML and CSS. The website is in dark mode initially as you open it. But how can I make it that when a user clicks the "light-mode" button for all pages to become dark/light mode based on what he has set?
I am currently running this method:
$(document).ready(function() {
$("#light-mode").click(function() {
$("body").toggleClass("light-mode-bgr");
$("h1").toggleClass("light-mode-text");
$(".message-disc p").toggleClass("light-p");
$("p").toggleClass("light-mode-text");
$(".img-rad label p.maybe").toggleClass("light-mode-btn");
$(".buttons button[type='next']").toggleClass("light", "disabled");
$(".buttons button[type='button']").toggleClass("light-ret");
$("input[type=radio]:checked+label>p").toggleClass("light-radio");
$("input[type=text]").toggleClass("light-inp");
$("input[type=tel]").toggleClass("light-inp");
$("input[type=num]").toggleClass("light-inp");
$("input[type=number]").toggleClass("light-inp");
$("textarea").toggleClass("light-inp");
console.log("clicked");
});
});
but obviously this is not changing the inner css, its only changing classes with the toggle I am using, and if I refresh the page on light-mode, that style is gone back to the default dark-mode style.
How can I make it so that it fully changes the inner css so that it applies to all pages in my website? If so is it possible with JQuery?
found a video https://www.youtube.com/watch?v=wodWDIdV9BY and followed the steps, it required me to change a lot of my css into variables:
:root {
--color-purpe: #FFA14A;
--color-purple-hov: #DE8430;
--body-bgr: #2B3549;
--h1-orange: #ffffff;
--black-labels: #ffffff;
--bas-orange: #7D63DE;
--bas-org-hov: #7D63DE;
--bas-red: #C34437;
--bas-red-hov: #b03628;
--disbaled: #a0a0a0;
}
.lightMode {
--color-purpe: #7D63DE;
--color-purple-hov: #7D63DE;
--body-bgr: #ffffff;
--h1-orange: #E18127;
--black-labels: #000000;
--bas-orange: #FFA14A;
--bas-org-hov: #DE8430;
--bas-red: #C34437;
--bas-red-hov: #b03628;
--disbaled: #a0a0a0;
}
and then I used this function to make it work:
let lightMode = localStorage.getItem('lightMode');
const lightModeToggle = document.querySelector('#light-mode');
// check if light mode enabled
// if off turn on
// if on turn off
const enableLightMode = () => {
document.body.classList.add('lightMode');
localStorage.setItem('lightMode', 'enabled');
}
const disableLightMode = () => {
document.body.classList.remove('lightMode');
localStorage.setItem('lightMode', null);
}
if (lightMode === 'enabled') {
enableLightMode();
}
lightModeToggle.addEventListener('click', () => {
lightMode = localStorage.getItem('lightMode');
if (lightMode !== 'enabled') {
enableLightMode();
console.log(lightMode);
} else {
disableLightMode();
}
});
so when I click the toggle, light mode is applied and changes the :root values into the .lightMode class values and gives me the result I wanted.
The function also stores the value in localStorage so when I refresh the page it doesnt go back to the default "dark mode" style.
I am currently working on adding a dark theme toggle to my website and can't seem to figure out the best way to store the data to LocalStorage. All I am using is a button that toggles the class of "dark" on the main document :root. The actual toggle works perfectly fine, I am only struggling with getting that selected option to stay in LocalStorage.
Here is my code with the LocalStorage that I am trying to add (which does save the key of theme to LocalStorage but not the actual class toggle).
document.addEventListener("DOMContentLoaded", function () {
const theme = localStorage.getItem("theme", "dark");
const darkModeToggle = document.getElementById("modeSwitch");
darkModeToggle.addEventListener("click", function () {
document.documentElement.classList.toggle("dark");
if (document.documentElement.classList.contains("dark")) {
localStorage.setItem("theme", "dark");
}
});
});
Here are my CSS variables as well for reference.
:root {
--main-background: #f8fafb;
--app-background: #ffffff;
--app-background-alt: #fcfcfc;
--app-background-hover: #f8fafb;
--dark-background: #141923;
--main-color: #000000;
--secondary-color: #747987;
}
.dark:root {
--main-background: #141923;
--app-background: #171b2c;
--app-background-alt: #1c2031;
--app-background-hover: #1d213d;
--dark-background: #141923;
--main-color: #ffffff;
--secondary-color: #747987;
}
Thank you so much.
Remove second parameter, should be like that:
const theme = localStorage.getItem("theme");
When you get item from LocalStorage need just key
the way you are storing the theme in the localStore is fine, if want to do it in other way, you could store the theme in an object. Here and example:
localStorage.setItem("theme",JSON.stringify({theme: "dark"}));
To be honest, i think that if your application is not too big you can leave it the way is it.
After playing around a bit, I did figure out a way to successfully store the theme into localStorage. What I am doing is checking to see if the toggle was clicked and "dark" was added to the class list. If it was, I store that in localStorage as "theme", "dark" - and if it "dark" was not added to the class list, I store it in localStorage as "theme", "light".
Then, at the top of the function I check to see if the theme contains "dark" - If the theme contains "dark", I add the class "dark" to the :root, and if it does not I remove it.
I am not sure if this is considered the "correct" way, but it does work!
document.addEventListener("DOMContentLoaded", function () {
const theme = localStorage.getItem("theme", "dark");
const darkModeToggle = document.getElementById("modeSwitch");
if (theme === "dark") {
document.documentElement.classList.add("dark");
} else {
document.documentElement.classList.remove("dark");
}
darkModeToggle.addEventListener("click", function () {
document.documentElement.classList.toggle("dark");
if (document.documentElement.classList.contains("dark")) {
localStorage.setItem("theme", "dark");
} else {
localStorage.setItem("theme", "light");
}
});
});
I'm writing a script that has access to a page's DOM, and I want to know what color would a particular link be if it had been visited. I'm aware that I cannot know whether the link has actually been visited, I don't care about that. I just want to know the color set for a:visited.
You can't get the :visited style with window.getComputedStyle according to the following MDN blog post because of privacy rules. So you can't programmatically tell if a user visited a link or not by checking the color.
But you can do it by walking through the stylesheets and search for a specific selector. Then if the selector is a match return the style.color property of that set style rule. This will not get the computed value but the value as set in the stylesheet.
const getStyleRuleColor = selector => {
for (const { rules } of document.styleSheets) {
for (const { style, selectorText } of rules) {
if (selectorText === selector) {
return style.color;
}
}
}
return null;
}
const selectorElement = 'a:visited';
const selectorId = '#someid:visited';
const elementVisitedColor = getStyleRuleColor(selectorElement);
const idVisitedColor = getStyleRuleColor(selectorId);
console.log(`${selectorElement} :`, elementVisitedColor);
console.log(`${selectorId} :`, idVisitedColor);
a {
color: black;
}
a:visited {
color: red;
}
#someid:visited {
color: green;
}
<a id="someid" href="http://someurl.com">I have a color</a>
Local storage value saved but how to use the saved local storage used. I tried creating a function apply but the class is not applying
document.querySelectorAll("#abc, #xyz").forEach(btn => {
btn.addEventListener("click", () => {
const e = document.querySelectorAll(".dog,.cat, #abc, #xyz");
e.forEach(el => {
el.classList.toggle("red");
var xyz = document.getElementById("xyz").className;
localStorage.setItem("vovo", xyz);
});
});
})
function apply(){
var xy = localStorage.getItem('vovo');
if (xy) {
var single = document.querySelectorAll(".dog,.cat, #abc, #xyz");
single.forEach(el => {
el.classList.add(xy);
});
}
};
The functionality logic :
when a button is pressed we check if it has the red class (as all the elements, buttons and the other divs, will receive the red class at some point).
if it has that class then it will be toggled (it will be removed from all the buttons and the other divs) thus the localStorage will store something like "No the elements don't have the red class".
if it doesn't has it the it will be toggled (it will be added to all the buttons and the other divs) thus the localStorage will store something like "Yes the elements have the red class".
basically, the localStorage will store '0' if the class isn't applied, '1' if the class is applied.
now, when the page gets refreshed, we check if the localStorage item that stores the red class' state is there (not null) and has the value of '1' then apply that class to all the elements (the buttons and the other divs).
remove the item that holds the red class' state from the localStorage.
Here's the update JavaScript code :
Sorry for everyone as I can't make a live demo using SO's snippets as the localStorage can't be reached because the code is sandboxed.
Anyway, here's a CodePen demo illustrating the required functionality.
const els = document.querySelectorAll('.dog,.cat, #abc, #xyz');
/** when the page finishes loading **/
document.addEventListener('DOMContentLoaded', () => {
/** check if the 'red' class was applied **/
applied = window.localStorage.getItem('class-applied') === '0' ? false:true;
/** remove "class-applied" item from the localStorage **/
window.localStorage.removeItem('class-applied');
/** if the "red" class was applied just apply it on document load **/
applied && els.forEach(el => el.classList.add('red'));
});
els.forEach(btn => {
btn.addEventListener('click', () => {
/** store the "red" class' state : '1' means it is applied, '0' means it isn't apllied **/
window.localStorage.setItem(
'class-applied',
!btn.classList.contains('red') ? '1' : '0'
);
els.forEach(el => el.classList.toggle('red'));
});
});
The above code should be placed just before </body>.
just use the following syntax:
localStorage.setItem('myLocalStorageVariable', 'myValue');
If you want to read the value instead:
localStorage.getItem('myLocalStorageVariable')
Alright, I'm creating a system for my webpage that allows users to change the theme. How I want to accomplish this is by having all the colors as variables, and the colors are set in the :root part of the CSS.
What I want to do is change those colors via JavaScript. I looked up how to do it, but nothing that I attempted actually worked properly. Here's my current code:
CSS:
:root {
--main-color: #317EEB;
--hover-color: #2764BA;
--body-color: #E0E0E0;
--box-color: white;
}
JS:
(Code to set the theme, it's ran on the click of a button) - I didn't bother adding the :root change to the other 2 themes since it doesn't work on the Dark theme
function setTheme(theme) {
if (theme == 'Dark') {
localStorage.setItem('panelTheme', theme);
$('#current-theme').text(theme);
$(':root').css('--main-color', '#000000');
}
if (theme == 'Blue') {
localStorage.setItem('panelTheme', 'Blue');
$('#current-theme').text('Blue');
alert("Blue");
}
if (theme == 'Green') {
localStorage.setItem('panelTheme', 'Green');
$('#current-theme').text('Green');
alert("Green");
}
}
(Code that is ran when the html is loaded)
function loadTheme() {
//Add this to body onload, gets the current theme. If panelTheme is empty, defaults to blue.
if (localStorage.getItem('panelTheme') == '') {
setTheme('Blue');
} else {
setTheme(localStorage.getItem('panelTheme'));
$('#current-theme').text(localStorage.getItem('panelTheme'));
}
}
It shows the alert, but does not actually change anything. Can someone point me in the right direction?
Thank you #pvg for providing the link. I had to stare at it for a little to understand what was going on, but I finally figured it out.
The magical line I was looking for was this:
document.documentElement.style.setProperty('--your-variable', '#YOURCOLOR');
That did exactly what I wanted it to do, thank you very much!
For those who want to modify the actual style sheet the following works:
var sheet = document.styleSheets[0];
sheet.insertRule(":root{--blue:#4444FF}");
More info at here: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet/insertRule
I think this is cleaner and easier to remember.
to set/get css variables to/from :root
const root = document.querySelector(':root');
// set css variable
root.style.setProperty('--my-color', 'blue');
// to get css variable from :root
const color = getComputedStyle(root).getPropertyValue('--my-color'); // blue
Example: setting multiple variables all at once
const setVariables = vars => Object.entries(vars).forEach(v => root.style.setProperty(v[0], v[1]));
const myVariables = {
'--color-primary-50': '#eff6ff',
'--color-primary-100': '#dbeafe',
'--color-primary-200': '#bfdbfe',
'--color-primary-300': '#93c5fd',
'--color-primary-400': '#60a5fa',
'--color-primary-500': '#3b82f6',
'--color-primary-600': '#2563eb',
'--color-primary-700': '#1d4ed8',
'--color-primary-800': '#1e40af',
'--color-primary-900': '#1e3a8a',
};
setVariables(myVariables);
To use the values of custom properties in JavaScript, it is just like standard properties.
// get variable from inline style
element.style.getPropertyValue("--my-variable");
// get variable from wherever
getComputedStyle(element).getPropertyValue("--my-variable");
// set variable on inline style
element.style.setProperty("--my-variable", 4);
I came here looking how to toggle the :root color-scheme with JavaScript, which sets the browser to dark mode (including the scroll bars) like this:
:root {
color-scheme: dark;
}
using the #Daedalus answer above, this is how I implemented my dark mode detection from user preference:
const userPrefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
const preferredTheme = userPrefersDarkMode ? 'dark' : 'light';
document.documentElement.style.setProperty("color-scheme", preferredTheme);
or with saved toggle:
const savedTheme = localStorage.getItem('theme');
if (savedTheme == 'dark') {
thisTheme = 'light'
}
else {
thisTheme = 'dark'; // the default when never saved is dark
}
document.documentElement.style.setProperty("color-scheme", thisTheme);
localStorage.setItem('theme', thisTheme);
see also the optional meta tag in the header:
<meta name="color-scheme" content="dark light">
old jquery magic still working too
$('#yourStyleTagId').html(':root {' +
'--your-var: #COLOR;' +
'}');
TL;DR
A solution to the problem could be the below code:
const headTag = document.getElementsByTagName('head')[0];
const styleTag = document.createElement("style");
styleTag.innerHTML = `
:root {
--main-color: #317EEB;
--hover-color: #2764BA;
--body-color: #E0E0E0;
--box-color: white;
}
`;
headTag.appendChild(styleTag);
Explanation:
Although #Daedalus answer with document.documentElement does the job pretty well, a slightly better approach is to add the styling into a <style> HTML tag (solution proposed).
If you add document.documentElement.style then all the CSS variables are added into the html tag and they are not hidden:
On the other hand, with the proposed code:
const headTag = document.getElementsByTagName('head')[0];
const styleTag = document.createElement("style");
styleTag.innerHTML = `
:root {
--main-color: #317EEB;
--hover-color: #2764BA;
--body-color: #E0E0E0;
--box-color: white;
}
`;
headTag.appendChild(styleTag);
the HTML tag will be cleaner and if you inspect the HTML tag you can also see the :root styling as well.
Read only, retrieve all CSS --root rules in an array, without using .getComputedStyle().
This may allow to retrieve values before full DOM content load, to create modules that use global root theme variables, but not via CSS. (canvas context...)
/* Retrieve all --root CSS variables
* rules into an array
* Without using getComputedStyle (read string only)
* On this example only the first style-sheet
* of the document is parsed
*/
console.log(
[...document.styleSheets[0].rules]
.map(a => a.cssText.split(" ")[0] === ":root" ?
a.cssText.split("{")[1].split("}")[0].split("--") : null)
.filter(a => a !== null)[0]
.map(a => "--"+a)
.slice(1)
)
:root {
--gold: hsl(48,100%,50%);
--gold-lighter: hsl(48,22%,30%);
--gold-darker: hsl(45,100%,47%);
--silver: hsl(210,6%,72%);
--silver-lighter: hsl(0,0%,26%);
--silver-darker: hsl(210,3%,61%);
--bronze: hsl(28,38%,67%);
--bronze-lighter: hsl(28,13%,27%);
--bronze-darker: hsl(28,31%,52%);
}
/*My style*/
:root {
--hl-color-green: green;
}
/*My update*/
* {
--hl-color-green: #0cc120;
}