How to implement web page theme switching

How to achieve theme effects on the interface, mainly switching between the day and night color schemes of the web page

I recorded several ways

CSS variables

It can be used, but my experience is not very good. The value will be displayed in the label styleattribute.

body {
    
    
  --size: 100px;
  --time: 500ms;
  --color1: #fff;
  --color2: #000;
  margin: 0;
  width: 100vw;
  height: 100vh;
  background: var(--color1);
  transition: background var(--time);
}

div {
    
    
  width: var(--size);
  height: var(--size);
  color: var(--color1);
  background: var(--color2);
  transition: background var(--time);
}
<div>
  文本
</div>
<script>
  const div = document.querySelector("div")
  const style = document.body.style
  div.onclick = (() => {
      
      
    let isDark = false
    return () => {
      
      
      if (isDark) {
      
      
        style.setProperty("--color1", "#fff");
        style.setProperty("--color2", "#000");
      } else {
      
      
        style.setProperty("--color1", "#000");
        style.setProperty("--color2", "#fff");
      }
      isDark = !isDark
    }
  })()
</script>

dynamic writing

When writing this paragraph, I was looking for @keyframesa way to dynamically modify using JavaScript, and I got a solution

Get the tag and modify the content directly

<style id="root">
  :root {
      
      
    --size: 300px;
    --color1: #000;
    --color2: #990;
    --color3: #090;
    --color4: #099;
  }
</style>
<style>
  div {
      
      
    width: var(--size);
    height: var(--size);
    background: var(--color1);
    animation: play 5s infinite;
  }

  @keyframes play {
      
      
    0% {
      
      
      background: var(--color1);
      transform: translate(0, 0);
    }

    25% {
      
      
      background: var(--color2);
      transform: translate(var(--size), 0);
    }

    50% {
      
      
      background: var(--color3);
      transform: translate(var(--size), var(--size));
    }

    75% {
      
      
      background: var(--color4);
      transform: translate(0, var(--size));
    }

    100% {
      
      
      background: var(--color1);
      transform: translate(0, 0);
    }
  }
</style>
<input type="number">
<button>
  修改 size
</button>
<div></div>
<script>
  const btn = document.querySelector("button")
  const input = document.querySelector("input")
  const style = document.querySelector("#root")

  btn.onclick = () => {
      
      
    style.innerText = `
        :root {
          --size: ${ 
        input.value}px;
          --color1: #000;
          --color2: #990;
          --color3: #090;
          --color4: #099;
        }
      `
  }
</script>

CSS variables were used, and a problem was discovered: --sizeafter the change, divthe size changed accordingly, but @keyframesthe rhythm did not change, and it still moved at a distance of 300

This also means that @keyframesit is fixed at the moment of definition and will not track changes in variables and change accordingly.

Of course, there is no problem with responsive animations. When triggered, the latest variable value will be obtained.

@media (min-width: 500px) {
    
    
  :root {
    
    
    --size: 100px;
    --color1: #000;
    --color2: #990;
    --color3: #090;
    --color4: #099;
  }

  @keyframes play {
    
    
    0% {
    
    
      background: var(--color1);
      transform: translate(0, 0);
    }

    25% {
    
    
      background: var(--color2);
      transform: translate(calc(var(--size) / 3), 0);
    }

    50% {
    
    
      background: var(--color3);
      transform: translate(calc(var(--size) / 3), calc(var(--size) / 3));
    }

    75% {
    
    
      background: var(--color4);
      transform: translate(0, calc(var(--size) / 3));
    }

    100% {
    
    
      background: var(--color1);
      transform: translate(0, 0);
    }
  }
}

@media (min-width: 800px) {
    
    
  :root {
    
    
    --size: 300px;
    --color1: #000;
    --color2: #990;
    --color3: #090;
    --color4: #099;
  }

  @keyframes play {
    
    
    0% {
    
    
      background: var(--color1);
      transform: translate(0, 0);
    }

    25% {
    
    
      background: var(--color2);
      transform: translate(var(--size), 0);
    }

    50% {
    
    
      background: var(--color3);
      transform: translate(var(--size), var(--size));
    }

    75% {
    
    
      background: var(--color4);
      transform: translate(0, var(--size));
    }

    100% {
    
    
      background: var(--color1);
      transform: translate(0, 0);
    }
  }
}

However, this cannot be used for dynamic insertion. You need to manually trigger responsive refresh. If you want a good experience, you need to rewrite the variables together @keyframeswith

The JavaScript part is omitted and only the fixed part is added at the end@keyframes

:root {
    
    
  --size: 300px;
  --color1: #000;
  --color2: #990;
  --color3: #090;
  --color4: #099;
}

@keyframes play {
    
    
  0% {
    
    
    background: var(--color1);
    transform: translate(0, 0);
  }

  25% {
    
    
    background: var(--color2);
    transform: translate(var(--size), 0);
  }

  50% {
    
    
    background: var(--color3);
    transform: translate(var(--size), var(--size));
  }

  75% {
    
    
    background: var(--color4);
    transform: translate(0, var(--size));
  }

  100% {
    
    
    background: var(--color1);
    transform: translate(0, 0);
  }
}

Dynamic tags

Write the CSS file in advance, insert it into the HTML when triggered, and use overlay to achieve the effect

:root {
    
    
  --bg-color: #fff;
  --text-color: #000;
}

body {
    
    
  margin: 0;
  width: 100vw;
  height: 100vh;
  font-size: 5em;
  text-align: center;
  color: var(--text-color);
  background: var(--bg-color);
}

body::before {
    
    
  content: 'light';
}
/* dark.css */
:root {
    
    
  --bg-color: #000;
  --text-color: #fff;
}

body::before {
    
    
  content: 'dark';
}
document.body.onclick = (() => {
    
    
  let isDark = false
  return () => {
    
    
    if (isDark) {
    
    
      const link = document.querySelector("#darkTheme")
      link.remove()
    } else {
    
    
      const link = document.createElement('link')
      link.id = "darkTheme"
      link.rel = "stylesheet"
      link.href = "./css/dark.css"
      document.head.append(link)
    }

    isDark = !isDark
  }
})()

This method is very simple, not violent, and is also recommended.

summary

It can be seen that the existence of CSS variables omits many things. Before there are variables, if you want to implement the third solution, you need to rewrite the entire

Dynamicity can be achieved using the CSS-in-JS solution @keyframes, but we have not yet studied how to implement it. Is there a better solution than brute force writing

Guess you like

Origin blog.csdn.net/qq_49661519/article/details/121766316