1. Original Question & First Bounty
Given a very basic color scheme.
One that allows the website user to set a desired theme from a predefined set of CSS root variable definitions.
Is there an easy way to let the browser remember the theme, it set by the user, so that the user's input is carried over to the next pages? Thus eliminating the need for setting the color scheme on every new page!
const setTheme = theme => document.documentElement.className = theme;
document.getElementById('scheme').addEventListener('click', ({target}) => {
setTheme(target.getAttribute('id'));
});
html{margin: 10px}
#scheme p{ /* User Interface */
display: inline-block;
text-decoration: underline;
}#scheme p:hover{cursor: pointer}
:root{ /* Default Theme */
--bgr: #eee;
--txt: #000;
}
:root.light {
--bgr: #ddc;
--txt: #466;
}
:root.dark {
--bgr: #222;
--txt: #A75;
}
:root.blue{
--bgr: #246;
--txt: #eec;
}
body { /* Have something to test */
background: var(--bgr);
color: var(--txt);
}
<div id="scheme">
<p id="light">Light</p>
<p id="dark">Dark</p>
<p id="blue">Blue</p>
<p id="etc">Etc</p>
</div>
<h1>Click on a theme to change the color scheme!</h1>
2. Updated Precision & Second Bounty
Attention to the Original Question and Improvements Needed
The current two answers have some problems from the point of view of the original question: one answer has A)diverged away from the css root: {}/* Default Theme */
by introducing root.default{}
and B) has implemented automatic theme selection with "light"/"dark" an and added "auto" theme, which though awesome for some, is the opposite of what is asked in the question: a simple manual user choice, overruling just one "unset" root: {}
default theme.
The other answer thought nice and basic C) necessitates manually setting the optional CSS theme names in an JavaScript array, making it prone to future errors and would be nice not need setting because all manual theme options are consistently named like :root.themename{}
. D) Also this solution causes a second or so delay when setting themes in mobile iOS devices!?
2nd Bounty goes to new answers that check the most of these points:
- Stick to the original questions
root:{}
as the only default (unset theme). *1) - Nothing beyond the basics, no automatic theme selection please.
- Do not necessitate css theme names in JavaScript code.
- Allow SVG boxes as buttons for more design flexibility. *2)
*1) The reason why I want root: {}
as default theme, is because I would like to set CSS Filters like saturation and grayscale on the themes that impact the entire page, images, logos, everything!
*2) Simpler cleaner html with svg buttons for setting the themes. In this future third and last bounty, plain SVG boxes (with one or more colours) serve as buttons for setting the themes! How awesome would that be?! Wordless, Timeless! See snippet below.
:root{ /* Default Theme, if no theme is manually selected by user */
--bgr: #eee;
--txt: #000;
--flt: none;
}
:root.blackwhite{
--bgr: #fff;
--txt: #000;
--flt: contrast(100%) grayscale(100%);
}
:root.sepia {
--bgr: lightblue;
--txt: red;
--flt: sepia(75%);
}
:root.holiday{
--bgr: #fba;
--txt: #269;
--flt: blur(.25px) saturate(4);
}
:root.moody{
--bgr: green;
--txt: yellow;
--flt: drop-shadow(16px 16px 20px yellow) blur(1px);
}
html { /* Have something to test */
background: var(--bgr);
color: var(--txt);
filter: var(--flt); /* important filter that affects everything */
}
h1{
background: var(--bgr);
color: var(--txt);
}
theme{ /* html element div that contains only SVG graphics */
display: flex;
flex-direction: row;
}
<!--I prefer a custom more logical `<theme>` over an equally
meaningless <div id="theme"> as container, since both do not
carry any semantic meaning. But, if you prefer a standard div,
then that's fine! Just explain why that's better.-->
<theme>
<svg id="blackwhite"><rect width="100" height="50" /></svg>
<svg id="sepia" ><rect width="100" height="50" /></svg>
<svg id="holiday" ><rect width="100" height="50" /></svg>
<svg id="moody" ><rect width="100" height="50" /></svg>
</theme>
<h1>Click on a theme to change the color scheme!</h1>
<p>Some Paragraph texts.</p>
<img src="\clouds.jpg" alt="clouds"/>
3. Updated User Interface Feedback & Third Bounty
Show the user which theme he has manually clicked on.
Add a class .chosentheme
to the svg element that is currently chosen or active, so that the user can see which one of the theme buttons is currently active/chosen/selected!
<theme id="scheme">
<svg id="blackwhite"><rect/></svg>
<svg id="midnight"><rect/></svg>
<svg id="beach"><rect/></svg>
<svg ><rect/></svg><!-- currently works as a (dummy) button to activate the :root{} Default Theme -->
</theme>
If no svg is selected yet, or if the memory is empty, then the last svg could be automatically selected via CSS or via setting an exception for this one id in the code like "defaulttheme", <svg id="defaulttheme">
, which already works as a (dummy) button to load the default theme :root{}
.
(It's okay if by default, when the memory is empty, nothing is selected, even not the last default theme svg).
Then, if any of the svg's is clicked or if a theme is loaded from memory, then the .chosentheme
styling should be applied via JavaScript dynamically, and added to that svg element's list of class names, letting the user know that he has manually clicked on that theme or that that theme is currently already loaded and showing.
theme svg.chosentheme { border: 1px solid black }
/* Sets a border around the currently activated theme */
/* Because someone clicked on it or because its stored in memory */