在页面刷新时保持切换位置
Keeping toggle position on page refresh
我对 HTML/CSS/JS 很陌生...我有一个 light/dark 模式切换开关,可以在我的 asp.net 核心站点上激活暗模式。一切正常,我正在使用本地主机在页面刷新或加载时保存 dark/light 主题。问题是我的拨动开关一直恢复到灯光模式。我尝试了几个选项,但我似乎无法弄清楚需要做什么才能在页面加载时将切换开关保持在正确的位置。
这是我的代码
HTML 复选框:
<div class="toggle-container">
<input type="checkbox" id="dark-mode-switch" name="theme" /><label for="dark-mode-switch">Toggle</label>
</div>
CSS:
.switch {
align-self: self-end;
margin: inherit;
padding: inherit;
border-radius: 15px;
display: grid;
grid-template-columns: 90px auto;
grid-template-rows: auto auto;
grid-template-areas: "title switch" "content content";
}
.switch h1 {
margin: auto;
color: var(--color-headings);
font-size: 16px;
line-height: inherit;
}
input[type=checkbox] {
height: 0;
width: 0;
visibility: hidden;
}
label {
cursor: pointer;
text-indent: -9999px;
width: 52px;
height: 27px;
background: grey;
float: right;
border-radius: 100px;
position: relative;
}
label:after {
content: '';
position: absolute;
top: 3px;
left: 3px;
width: 20px;
height: 20px;
background: #fff;
border-radius: 90px;
transition: 0.4s;
}
input:checked + label{
background: var(--color-headings);
}
input:checked + label:after {
left: calc(100% - 5px);
transform: translateX(-100%);
}
label:active:after {
width: 45px;
}
html.transition,
html.transition *,
html.transition *:before,
html.transition *:after {
transition: all 750ms !important;
transition-delay: 0 !important;
JS
let darkMode = localStorage.getItem('data-theme');
const checkbox = document.querySelector('input[name=theme]');
if (darkMode === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark')
localStorage.setItem('data-theme', 'dark')
}
checkbox.addEventListener('change', function () {
if (this.checked) {
trans()
document.documentElement.setAttribute('data-theme', 'dark')
localStorage.setItem('data-theme', 'dark')
} else {
trans()
document.documentElement.setAttribute('data-theme', 'light')
localStorage.setItem('data-theme', 'light')
}
})
let trans = () => {
document.documentElement.classList.add('transition');
window.setTimeout(() => {
document.documentElement.classList.remove('transition')
}, 1000)
}
我认为问题在于您没有重新分配复选框的“选中”属性。您有代码可以根据复选框值更新深色模式,但反之则不行。
解决此问题的一种方法是修改您的 if (darkmode === 'dark')
代码以设置 checkbox
的 checked
属性 而不是直接更新 data-theme
和本地存储。这应该有效:
if (darkMode === 'dark') {
checkbox.checked = true;
}
您还应该稍微重新安排您的 JS 以确保您没有未定义的引用。我个人会这样安排:
const checkbox = document.querySelector('input[name=theme]');
let trans = () => {
...
}
checkbox.addEventListener('change', function () {
...
})
let darkMode = localStorage.getItem('data-theme');
if (darkMode === 'dark') {
...
}
至少,必须在更新checked
的值之前定义更改事件侦听器,否则事件不会在您从本地存储加载时触发。
此外,此代码需要位于 HTML 的末尾,或者包含在 domready 事件处理程序中。否则,checkbox
可能未定义,您的代码将无法运行。
更新:我刚刚看到您正在使用 ASP.NET,因此以下内容不适用。但我会把它留在这里供参考,因为它可能对其他人有帮助。这是 localstorage 的一个很常见的问题。
最后,本地存储不会为通过 file://
URL 加载的文件保存。如果您将它放在一个文件中并直接加载到网络浏览器(没有服务器),那么每次您离开页面时本地存储都会被重置。
我对 HTML/CSS/JS 很陌生...我有一个 light/dark 模式切换开关,可以在我的 asp.net 核心站点上激活暗模式。一切正常,我正在使用本地主机在页面刷新或加载时保存 dark/light 主题。问题是我的拨动开关一直恢复到灯光模式。我尝试了几个选项,但我似乎无法弄清楚需要做什么才能在页面加载时将切换开关保持在正确的位置。
这是我的代码
HTML 复选框:
<div class="toggle-container">
<input type="checkbox" id="dark-mode-switch" name="theme" /><label for="dark-mode-switch">Toggle</label>
</div>
CSS:
.switch {
align-self: self-end;
margin: inherit;
padding: inherit;
border-radius: 15px;
display: grid;
grid-template-columns: 90px auto;
grid-template-rows: auto auto;
grid-template-areas: "title switch" "content content";
}
.switch h1 {
margin: auto;
color: var(--color-headings);
font-size: 16px;
line-height: inherit;
}
input[type=checkbox] {
height: 0;
width: 0;
visibility: hidden;
}
label {
cursor: pointer;
text-indent: -9999px;
width: 52px;
height: 27px;
background: grey;
float: right;
border-radius: 100px;
position: relative;
}
label:after {
content: '';
position: absolute;
top: 3px;
left: 3px;
width: 20px;
height: 20px;
background: #fff;
border-radius: 90px;
transition: 0.4s;
}
input:checked + label{
background: var(--color-headings);
}
input:checked + label:after {
left: calc(100% - 5px);
transform: translateX(-100%);
}
label:active:after {
width: 45px;
}
html.transition,
html.transition *,
html.transition *:before,
html.transition *:after {
transition: all 750ms !important;
transition-delay: 0 !important;
JS
let darkMode = localStorage.getItem('data-theme');
const checkbox = document.querySelector('input[name=theme]');
if (darkMode === 'dark') {
document.documentElement.setAttribute('data-theme', 'dark')
localStorage.setItem('data-theme', 'dark')
}
checkbox.addEventListener('change', function () {
if (this.checked) {
trans()
document.documentElement.setAttribute('data-theme', 'dark')
localStorage.setItem('data-theme', 'dark')
} else {
trans()
document.documentElement.setAttribute('data-theme', 'light')
localStorage.setItem('data-theme', 'light')
}
})
let trans = () => {
document.documentElement.classList.add('transition');
window.setTimeout(() => {
document.documentElement.classList.remove('transition')
}, 1000)
}
我认为问题在于您没有重新分配复选框的“选中”属性。您有代码可以根据复选框值更新深色模式,但反之则不行。
解决此问题的一种方法是修改您的 if (darkmode === 'dark')
代码以设置 checkbox
的 checked
属性 而不是直接更新 data-theme
和本地存储。这应该有效:
if (darkMode === 'dark') {
checkbox.checked = true;
}
您还应该稍微重新安排您的 JS 以确保您没有未定义的引用。我个人会这样安排:
const checkbox = document.querySelector('input[name=theme]');
let trans = () => {
...
}
checkbox.addEventListener('change', function () {
...
})
let darkMode = localStorage.getItem('data-theme');
if (darkMode === 'dark') {
...
}
至少,必须在更新checked
的值之前定义更改事件侦听器,否则事件不会在您从本地存储加载时触发。
此外,此代码需要位于 HTML 的末尾,或者包含在 domready 事件处理程序中。否则,checkbox
可能未定义,您的代码将无法运行。
更新:我刚刚看到您正在使用 ASP.NET,因此以下内容不适用。但我会把它留在这里供参考,因为它可能对其他人有帮助。这是 localstorage 的一个很常见的问题。
最后,本地存储不会为通过 file://
URL 加载的文件保存。如果您将它放在一个文件中并直接加载到网络浏览器(没有服务器),那么每次您离开页面时本地存储都会被重置。