npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

theme-change

v2.5.0

Published

Change CSS theme with toggle, buttons or select using CSS Variables and localStorage

Downloads

48,619

Readme

🎨 CSS Theme Change

  • A tiny JS script to handle CSS themes
  • Change CSS theme using button, toggle or a <select>
  • It saves chosen theme in browser and uses it again when page reloads


🖥 Demo

image

💿 Use

JS

Use CDN:

<script src="https://cdn.jsdelivr.net/npm/[email protected]/index.js"></script>

Install: npm i theme-change --save and use it in your js file:

import { themeChange } from 'theme-change'
themeChange()

Install: npm i theme-change --save and use it in your js file:

import { useEffect } from 'react'
import { themeChange } from 'theme-change'

useEffect(() => {
  themeChange(false)
  // 👆 false parameter is required for react project
}, [])

Install: npm i theme-change --save and use it in your js file:

import { onMounted } from 'vue'
import { themeChange } from 'theme-change'

export default {
  setup() {
    onMounted(() => {
      themeChange(false)
    })
  },
}

Install: npm i theme-change --save and use it in your js file:

import { themeChange } from 'theme-change'

export default {
  mounted: function () {
    themeChange(false)
  },
}

Install: npm i theme-change --save and use it in your svelte component that uses one theme-change attributes:

import { onMount } from 'svelte'
import { themeChange } from 'theme-change'

// NOTE: the element that is using one of the theme attributes must be in the DOM on mount
onMount(() => {
  themeChange(false)
  // 👆 false parameter is required for svelte
})

Install: npm i theme-change --save and use it in your js/jsx/tsx file:

import { onMount } from 'solid-js'
import { themeChange } from 'theme-change'
onMount(async () => {
  themeChange();
})

Install: npm i theme-change --save and use it in your .astro file(s):

Astro is a bit tricky because of how is rendering html page as a MPA (Multiple Pages Application) Astro projects are therefore subject to FART problem. To prevent this we will use the is:inline astro directive.

If you want to apply themes on a single astro page (remember Astro is an MPA framework) :

src/pages/mypage.astro

---
---

<html lang="en">
  <head>
  <script is:inline>
      // ☝️ This script prevent the FART effect.
      if (localStorage.getItem("theme") === null) {
        document.documentElement.setAttribute("data-theme", "light");
      } else
      document.documentElement.setAttribute("data-theme",localStorage.getItem("theme"));
      // "theme" LocalStorage value is set by the package to remember user preference.
      // The value is checked and applyed before rendering anything.
  </script>
  <script>
      import { themeChange } from "theme-change";
      themeChange();
       // 👆 you could import the CDN directly instead of these two lines
    </script>
    <title>My crazy credit page</title>
  </head>
  <body>
    <h1>Welcome to my credit page!</h1>
  </body>
</html>

If you want to apply themes to all your astro pages, you need to execute both scripts in a Astro layout, it would need to wrap all your astro pages like so:

src/layouts/MyCrazyLayout.astro

---
---

<html lang="en">
  <head>
    <script is:inline>
      // ☝️ This script prevent the FART effect.
      if (localStorage.getItem("theme") === null) {
        document.documentElement.setAttribute("data-theme", "light");
      } else
        document.documentElement.setAttribute(
          "data-theme",
          localStorage.getItem("theme")
        );
      // "theme" LocalStorage value is set by the package to remember user preference.
      // The value is checked and applyed before rendering anything.
    </script>
    <script>
      import { themeChange } from 'theme-change';
      themeChange();
      // 👆 you could import the CDN directly instead of these two lines
    </script>
    <meta charset="utf-8" />
    <title>My Cool Astro Layout Wraping All My Pages</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
  </head>
  <body>
    <nav>
      <a href="#">Home</a>
      <a href="#">Posts</a>
      <a href="#">Contact</a>
    </nav>
    <article>
      <slot />
      <!-- your content from src/pages/index.astro is injected here -->
    </article>
  </body>
</html>

src/pages/index.astro

---
import MyCrazyLayout from '../layouts/MyCrazyLayout.astro';
---
<MySiteLayout>
  <p>My page content, wrapped in a layout!</p>
</MySiteLayout>

CSS

Set your themeable style as custom properties in CSS like this:

:root {
  --my-color: #fff;
  /* or any other variables/style */
}
[data-theme='dark'] {
  --my-color: #000;
}
[data-theme='pink'] {
  --my-color: #ffabc8;
}

then use your variables on any element

body {
  background-color: var(--my-color);
}

HTML

There are 3 options:

  • Using buttons to set a theme

    btn

    Clicking on these buttons, sets the chosen theme and also adds the ACTIVECLASS to the chosen button

    <button data-set-theme="" data-act-class="ACTIVECLASS"></button>
    <button data-set-theme="dark" data-act-class="ACTIVECLASS"></button>
    <button data-set-theme="pink" data-act-class="ACTIVECLASS"></button>
  • Toggle between two themes

    toggle

    Clicking on this element, toggles between dark and light theme and also adds the ACTIVECLASS to the element

    <button data-toggle-theme="dark,light" data-act-class="ACTIVECLASS"></button>
  • <select> menu

    select

    <select data-choose-theme>
      <option value="">Default</option>
      <option value="dark">Dark</option>
      <option value="pink">Pink</option>
    </select>

Advance use

@media (prefers-color-scheme: dark){
  :root{
    --my-color: #252b30;
  }
}

If you're using Purge CSS, you might need to safe list your CSS using the comments below because your secondary themes will be purged

  • Safelist [data-theme] on postcss config

    module.exports = {
      purge: {
        options: {
          safelist: [/data-theme$/],
        },
      },
    }
  • Safelist inside CSS file

    /*! purgecss start ignore */
    
    [data-theme='dark'] {
      --my-color: #252b30;
    }
    
    /*! purgecss end ignore */

If you want to use a custom localStorage key, you can add it to the data-key attribute like this:

<select data-choose-theme data-key="admin-panel">

<button data-key="front-page" data-set-theme="">

<span data-key="premium-user-theme" data-toggle-theme="dark">