【问题标题】:Body CSS not updating with .setProperty()正文 CSS 未使用 .setProperty() 更新
【发布时间】:2021-05-20 10:10:07
【问题描述】:
我正在尝试在网站上启用暗模式/亮模式功能,其中我使用 .setProperty 函数来更改变量的 HEX 值。但是,每当我切换开关时,该站点都不会更新。为什么是这样?以下是与问题有关的所有代码:
let color = "#141414";
function changeMode() {
console.log("Switch was toggled. Switching site color scheme...")
let bg = document.querySelector(':root');
// Should switch the value of 'color' from grey to white, and vice versa
if (color === "#141414") { color = "#ffffff"; } else if (color === "#ffffff") { color = "#141414"; }
bg.style.setProperty("--main2", color);
}
:root {
--main1: #ffdb15;
--main2: #141414;
}
html, body {
background-color: var(--main2);
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
left: 20px;
top: 20px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #5d00e2;
}
input:focus + .slider {
box-shadow: 0 0 1px #5d00e2;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
<label class = "switch" onclick = "changeMode()">
<input type = "checkbox" checked>
<span class = "slider round"> </span>
</label>
是color变量的问题,还是在切换值时程序没有更新页面本身的问题?
编辑:另外,如果您知道任何改进我的代码的方法,请告诉我如何。具体来说,有什么方法可以改进切换颜色变量值的方法吗?
【问题讨论】:
标签:
javascript
html
css
toggle
darkmode
【解决方案1】:
如果您在单击输入时查看控制台,您会看到它触发了两个单击事件,一次有效地切换了两次。您可以在changeMode() 中添加console.log(event) 以准确查看正在触发的事件(标签点击和输入点击)。快速解决方法是将其更改为在输入更改时触发,而不是父标签单击:
<label class = "switch">
<input onchange="changeMode()" type = "checkbox" checked>
<span class = "slider round"> </span>
</label>
【解决方案2】:
您的问题实际上是在问如何用 js 更新 css 变量?
下面是例子
<script>
// Get the root element
var r = document.querySelector(':root');
// Create a function for getting a variable value
function myFunction_get() {
// Get the styles (properties and values) for the root
var rs = getComputedStyle(r);
// Alert the value of the --blue variable
alert("The value of --blue is: " + rs.getPropertyValue('--blue'));
}
// Create a function for setting a variable value
function myFunction_set() {
// Set the value of variable --blue to another value (in this case "lightblue")
r.style.setProperty('--blue', 'lightblue');
}
</script>
添加var rs = getComputedStyle(r);就可以了
source: w3school
【解决方案3】:
您是否注意到您的事件被触发了两次?您将事件侦听器放在带有输入复选框的标签上。单击标签就像单击复选框一样。所以你可以做的是改变 onclick 放在输入中。
let color = "#141414";
function changeMode() {
console.log("Switch was toggled. Switching site color scheme...")
let bg = document.querySelector(':root');
// Should switch the value of 'color' from grey to white, and vice versa
if (color === "#141414") {
color = "#ffffff";
} else if (color === "#ffffff") {
color = "#141414";
}
console.log(color);
bg.style.setProperty("--main2", color);
}
:root {
--main1: #ffdb15;
--main2: #141414;
}
html, body {
background-color: var(--main2);
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
left: 20px;
top: 20px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #5d00e2;
}
input:focus + .slider {
box-shadow: 0 0 1px #5d00e2;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
<label class = "switch">
<input type = "checkbox" checked onclick="changeMode()">
<span class = "slider round"> </span>
</label>
【解决方案4】:
你应该使用getComputedStyle来获取document.documentElement,然后你可以在条件中设置变量然后设置document.documentElement的样式 使用 setProperty。
getComputedStyle(element).backgroundColor 和 element.style.backgroundColor 有很大区别。第一个实际上会为您提供样式表中设置的 CSS,而后者将为您提供元素 HTML 标记中设置的内联样式。
因此,您使用 getComputedStyle(element) 获得使用 CSS 文件中的变量设置的设置样式,然后通过条件运行并设置内联ROOT 使用 element.style.backgroundColor 元素设置为 document.documentElement。
let bg = document.documentElement;
let input = document.getElementById('input')
function changeMode() {
let color = '';
currentStyle = getComputedStyle(document.documentElement).backgroundColor
currentStyle === "rgb(20, 20, 20)" ? color = "rgb(255, 219, 21)" : color = "rgb(20, 20, 20)"
bg.style.setProperty("--main2", color);
}
input.addEventListener('click', changeMode)
:root {
--main1: #ffdb15;
--main2: #141414;
}
html,
body {
background-color: var(--main2);
}
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
left: 20px;
top: 20px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #5d00e2;
}
input:focus+.slider {
box-shadow: 0 0 1px #5d00e2;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
<label class="switch">
<input id="input" type="checkbox" checked>
<span class="slider round"> </span>
</label>