• Stars
    star
    1,243
  • Rank 36,396 (Top 0.8 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created about 4 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

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

🎨 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>
Or use NPM:

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

import { themeChange } from 'theme-change'
themeChange()
or if it's a React project:

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
}, [])
or if it's a Vue 3 project (using composition API):

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)
    })
  },
}
or if it's a Vue 2 project (using options API):

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

import { themeChange } from 'theme-change'

export default {
  mounted: function () {
    themeChange(false)
  },
}
or if it's a Svelte project:

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
})
or if it's a SolidJS project:

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();
})
or if it's a Astro project:

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

Set theme based on OS color-scheme
@media (prefers-color-scheme: dark){
  :root{
    --my-color: #252b30;
  }
}
Use with PurgeCSS

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 */
Using custom localStorage key

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">

More Repositories

1

daisyui

🌼 🌼 🌼 🌼 🌼  The most popular, free and open-source Tailwind CSS component library
Svelte
31,000
star
2

design-systems

A list of famous design systems, design languages and guidelines
629
star
3

browser-hack-sass-mixins

Browser hack sass mixin - Apply your SCSS to a specific browser - CSS hacks for: IE, Chrome, Firefox, Edge, Opera
SCSS
177
star
4

daisy-blog

Astro
58
star
5

tailwindcss-document-cli

Tailwind CSS Document for CLI
JavaScript
46
star
6

saadeghi

36
star
7

tailwindcss-postcss-browsersync-boilerplate

Tailwind CSS + PostCSS + BrowserSync boilerplate
JavaScript
31
star
8

curse

Use this blacklist on your softwares and apps
28
star
9

svelte-countup

Svelte
17
star
10

saadeghi.github.io

Svelte
17
star
11

daisyui-nextjs-nextthemes

JavaScript
15
star
12

create-react-app-tailwindcss

create react app with tailwindcss configed
JavaScript
11
star
13

svelte-component-template

JavaScript
11
star
14

daisyui-demo

Vue
10
star
15

remix-daisyui

TypeScript
10
star
16

vite-and-run

Starts a Vite server and runs a custom command when files are changed and triggers a hot reload
JavaScript
10
star
17

smart-grid

Smart and minimal Sass grid mixin that doesn't need HTML class names!
CSS
9
star
18

tailwindcss-parceljs-typescript-boilerplate

Tailwind CSS + ParcelJS + TypeScript boilerplate
HTML
8
star
19

daisyui-starter

HTML
8
star
20

nextjs-daisyui-headlessui

JavaScript
5
star
21

border1pxred

For the lulz
JavaScript
5
star
22

cra-tailwind3-daisyui-example

HTML
5
star
23

vuejs-daisyui-modal

Vue
4
star
24

daisyui-bidirectional-builds

CSS
4
star
25

svelte-starter

Svelte
3
star
26

daisy-blog-astro

Astro
3
star
27

pouya

JavaScript
3
star
28

testing-daisyui-size-with-tailwind

JavaScript
3
star
29

tailwindcss-design-systems

JavaScript
3
star
30

svelte-preprocess-postcss-bug

Svelte
3
star
31

daisyui-old-examples

HTML
3
star
32

windicss-daisyui-weird-responsive-style-issue

CSS
3
star
33

astro-starter

Astro
3
star
34

nextjs14-daisyui4

TypeScript
2
star
35

daisyui-parcel-table-issue

HTML
2
star
36

daisyui-prefix-example

CSS
2
star
37

hbs-test

HTML
2
star
38

windi-vs-tailwind-daisyui-class-order-issue

JavaScript
2
star
39

css-in-readme-like-wat

Style your readme using CSS with this simple trick
2
star
40

daisyui-images

1
star
41

daisy-test

TypeScript
1
star
42

files

1
star