I am new to React and Gatsby.js. I am building a blog with Gatsby and my blog has a toggle to switch between light and dark modes. I am achieving this by toggling a class on the <body>
tag with JavaScript. Essentially, if it is light mode, the tag will be <body>
and if it is dark mode, the tag will be <body class="darkMode">
.
I have managed to get this to work just fine by using vanilla JavaScript to set and remove the .darkMode
class on the <body>
tag. However, I am having some trouble styling elements based on body.darkMode
in my CSS modules.
In my index.module.css file, I have the following classes:
.section {
color: #141414;
}
body.darkMode .section {
color: #ebebeb;
}
In my index.js ponent, I have imported the CSS module and applied the style like this:
<section className={indexStyles.section}></section>
While the color property in the .section
class does work, I notice that the body.darkMode .section
declaration does not work when I add the .darkMode
CSS class to the <body>
tag. Why is this? Help appreciated. Thanks.
I am new to React and Gatsby.js. I am building a blog with Gatsby and my blog has a toggle to switch between light and dark modes. I am achieving this by toggling a class on the <body>
tag with JavaScript. Essentially, if it is light mode, the tag will be <body>
and if it is dark mode, the tag will be <body class="darkMode">
.
I have managed to get this to work just fine by using vanilla JavaScript to set and remove the .darkMode
class on the <body>
tag. However, I am having some trouble styling elements based on body.darkMode
in my CSS modules.
In my index.module.css file, I have the following classes:
.section {
color: #141414;
}
body.darkMode .section {
color: #ebebeb;
}
In my index.js ponent, I have imported the CSS module and applied the style like this:
<section className={indexStyles.section}></section>
While the color property in the .section
class does work, I notice that the body.darkMode .section
declaration does not work when I add the .darkMode
CSS class to the <body>
tag. Why is this? Help appreciated. Thanks.
- Can you show what styles are applied to the section when in dark mode from your dev tools? – Zlatko Commented May 19, 2019 at 19:24
-
Turns out that the
body.darkMode .section
line is also getting piled into a long class name likedarkMode: "index-module--darkMode--3BMQh"
. Is there any way to prevent Gatsby from converting specific CSS declarations into its own random class names? – JackH Commented May 20, 2019 at 12:20 - 1 @Zlatko I managed to resolve this. See my answer in this thread. Thanks! – JackH Commented May 20, 2019 at 13:05
2 Answers
Reset to default 7I figured out the solution. It turns out, Gatsby was piling the body.darkMode .section
into some arbitrary classnames. In reality, I wanted it to ignore body.darkMode
but reference the local generated class name for .section
.
I found the answer here - https://github./webpack-contrib/css-loader#scope. I was able to solve my specific issue by converting the original CSS to:
.section {
color: #141414;
}
body:global(.darkMode) :local(.section) {
color: #ebebeb;
}
As you can see, the :global and :local selectors allow you to target your HTML correctly.
if u want switch between Dark and Light Mode see this code
var checkbox = document.querySelector('input[name=mode]');
checkbox.addEventListener('change', function() {
if(this.checked) {
trans()
document.documentElement.setAttribute('data-theme', 'dark')
} else {
trans()
document.documentElement.setAttribute('data-theme', 'light')
}
})
let trans = () => {
document.documentElement.classList.add('transition');
window.setTimeout(() => {
document.documentElement.classList.remove('transition');
}, 1000)
}
@import url("https://fonts.googleapis./css?family=Poppins:300,400,900&display=swap");
html {
width: 100%;
height: 100vh;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
background: var(--lightBg);
--lightBtn: #FE016C;
--lightBg: #fff;
--lightColor: #232323;
}
html[data-theme='dark'] {
background: var(--lightBg);
--lightBtn: #FFBD07;
--lightBg: #232323;
--lightColor: #fff;
}
h1 {
font-family: 'Poppins', sans-serif;
font-weight: 300;
color: var(--lightColor);
}
input[type=checkbox] {
height: 0;
width: 0;
visibility: hidden;
}
label {
cursor: pointer;
text-indent: -9999px;
width: 55px;
height: 30px;
background: var(--lightBtn);
margin: 0 auto;
display: flex;
justify-content: center;
align-items: center;
-webkit-border-radius: 100px;
-moz-border-radius: 100px;
border-radius: 100px;
position: relative;
}
label:after {
content: '';
background: #fff;
width: 20px;
height: 20px;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
position: absolute;
top: 5px;
left: 4px;
-webkit-transition: ease-in-out 200ms;
-moz-transition: ease-in-out 200ms;
-ms-transition: ease-in-out 200ms;
-o-transition: ease-in-out 200ms;
transition: ease-in-out 200ms;
}
input:checked + label {
background: #FFBD07;
}
input:checked + label:after {
left: calc(100% - 5px);
-webkit-transform: translateX(-100%);
-moz-transform: translateX(-100%);
-ms-transform: translateX(-100%);
-o-transform: translateX(-100%);
transform: translateX(-100%);
}
html.transition,
html.transition *,
html.transition *:before,
html.transition *:after {
-webkit-transition: ease-in-out 200ms !important;
-moz-transition: ease-in-out 200ms !important;
-ms-transition: ease-in-out 200ms !important;
-o-transition: ease-in-out 200ms !important;
transition: ease-in-out 200ms !important;
transition-delay: 0 !important;
}
<div class="container">
<h1>Light / Dark Mode</h1>
<input class="container_toggle" type="checkbox" id="switch" name="mode">
<label for="switch">Toggle</label>
</div>