11497 sujets

JavaScript, DOM et API Web HTML5

salut,

je refait mon site sans framework en dehors de font-awesome et je rencontre un problème pour faire mon changement de thème (par défaut sombre) en clair.
avant tout, je n'y connait rien en javascript donc j'ai demandé à chatgpt d'essayer de me pondre un truc mais ça pose quelques problèmes.

pour commencer, voici les variables concernant le thème sombre que j'utilise dans mon css :
:root {
    --border-black: 1px solid var(--color-black-secondary);
    --border-white: 1px solid var(--color-white-secondary);
    --color-black: #000000;
    --color-black-primary: #101010;
    --color-black-secondary: #1e1e1e;
    --color-white: #ffffff;
    --color-white-primary: #cbcbcb;
    --color-white-secondary: #eeeeee;
}

dans mon menu j'ai ce bouton :
<a href="javascript:void(0);" id="theme-switcher"><span class="fa fa-adjust fa-lg fa-fw" title="Changer la couleur du site"></span></a>

le résultat désiré est le suivant quand on clique sur le bouton :
body {
    background-color: var(--color-black-secondary);
    color: var(--color-white-primary);
}

devient :
body {
    background-color: var(--color-white-secondary);
    color: var(--color-black-primary);
}
autre exemple :
.hamburger-button:hover {
    background-color: var(--color-black-primary);
    color: var(--color-white-primary);
}

devient :
.hamburger-button:hover {
    background-color: var(--color-white-primary);
    color: var(--color-black-primary);
}

ce bon vieux chatgpt m'a fait ceci après plusieurs essais (c'est le meilleur résultat obtenu actuellement bien qu'il ne fonctionne pas très bien) :
(function() {
    var theme = document.cookie.replace(/(? [decu]?:^|.*;\s*)theme\s*\=\s*([^;]*).*$)|^.*$/, "$1");
    if (theme && theme === "dark") {
        document.documentElement.classList.add("dark-theme");
    } else {
        document.documentElement.classList.add("dark-theme");
        document.cookie = "theme=dark";
    }
    document.getElementById("theme-switcher").addEventListener("click", function() {
        var root = document.documentElement;
        var isDarkTheme = root.classList.contains("dark-theme");
        root.classList.toggle("dark-theme", !isDarkTheme);
        var currentColor = root.style.getPropertyValue("--color-black-secondary");
        var newColor = currentColor === "var(--color-black-secondary)" ? "var(--color-white-secondary)" : "var(--color-black-secondary)";
        root.style.setProperty("--color-black-secondary", newColor);
        root.style.setProperty("--color-white-secondary", currentColor);
        var currentTextColor = root.style.getPropertyValue("--color-white-primary");
        var newTextColor = currentTextColor === "var(--color-white-primary)" ? "var(--color-black-primary)" : "var(--color-white-primary)";
        root.style.setProperty("--color-white-primary", newTextColor);
        root.style.setProperty("--color-black-primary", currentTextColor);
        document.cookie = "theme=" + (isDarkTheme ? "light" : "dark");
    });
})();

(function() {
    var theme = document.cookie.replace(/(? [decu]?:^|.*;\s*)theme\s*\=\s*([^;]*).*$)|^.*$/, "$1");
    if (!theme) {
        console.error("Failed to read theme cookie");
    }
})();


maintenant les problèmes :
- il faut que je clique 2 fois sur mon bouton, la 1ère fois ça change le contenu de la page et la seconde fois le menu et pas correctement car ça me met des fond transparent pour mes sous-menus alors que ça devrait tout changer en thème clair au 1er coup et tout changer en thème sombre au 2ème
- le cookie ne fonctionne pas même avec la bibliothèque js-cookie qui précède mon script

quelqu'un aurait une solution ? ça fait 3 jours que je suis là dessus et je devient fou Smiley biggrin si besoin je peux fournit l'intégralité de mon fichier css.
Modifié par Breat (14 May 2024 - 12:56)
Salut,

a priori plusieurs points qui ne m'ont pas l'air terrible :
- cela ne me semble pas une bonne idée de définir des variables avec noir et blanc dans le nom puis d'inverser la variable que tu utilises dans ton css. L’intérêt d'une variable c'est de pouvoir lui changer sa valeur => tu fixes ton css une bonne fois pour toute et tu n'auras que la portion :root à modifier.
- tu peux utiliser un filtre sur @media pour utiliser le thème définit par défaut par le navigateur/os de l'utilisateur : https://developer.mozilla.org/fr/docs/Web/CSS/@media/prefers-color-scheme
- Pour en plus autoriser le toggle manuel en javascript, je suppose qu'on doit pouvoir définir des variantes de :root avec une classe en plus puis rajouter cette classe avec javascript

Petit edit pour rajouter un petit lien vers jsfiddle histoire d'illustrer Smiley lol : https://jsfiddle.net/b6s1vern/
Bon au final c'est un peu pénible d'utiliser le @media (prefers-color-scheme: en même temps que la modification en javascript parce que cela m'oblige à doubler le code Smiley bawling
Modifié par Mathieuu (14 May 2024 - 15:14)
Administrateur
Bonjour,

je confirme pour le nommage, ça pique quand en marque blanche blue est décliné en jaune et red en bleu Smiley biggol
La fois d'après, j'utilisais primary, secondary, ... ou ici -text pour l'avant-plan et -bg pour background Smiley ravi (j'ai du mal avec -fg pour foreground : trop proche visuellement de -bg)

Breat a écrit :
dans mon menu j'ai ce bouton :
<a href="javascript:void(0);" id="theme-switcher"><span class="fa fa-adjust fa-lg fa-fw" title="Changer la couleur du site"></span></a>


Ceci est un lien et c'est bien un bouton dont tu as besoin Smiley cligne
De plus le lien est vide : title (idem avec aria-label) devrait être sur le A. Sur un span, il est ignoré par les navigateurs et lecteurs d'écran ; il serait absent ce serait pareil (à part visuellement avoir une infobulle au survol, mais ça va pas bien loin...)
<button type="button" title="Mode sombre"><span class="des-trucs-css">/span></button>
sera plus accessible.

Comme exemple de style switcher accessible, très bon exemple avec https://fossheim.io/writing/posts/accessible-theme-picker-html-css-js/
Mais elle n'utilise pas prefers-color-scheme. J'ai dans l'idée qu'ici un coup de JS pour récupérer la préférence du navigateur / OS et mettre à jour le composant au chargement est le plus pertinent mais il y a d'autres manières de faire et je n'ai pas d'expérience pratique sur le sujet
Meilleure solution
pour les noms de mes variables effectivement je suis allé au plus simple et oui ça peut en effet poser problème à long terme.
pour lien et non bouton fait le taf mais je n'avais pas pensé aux lecteurs d'écran etc.

merci pour les liens, je vais pouvoir potasser là dessus Smiley smile
Modifié par Breat (14 May 2024 - 16:54)