Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Recherche sur les couleurs & préférences utilisateur #1

Open
marcimat opened this issue Dec 12, 2017 · 8 comments
Open

Recherche sur les couleurs & préférences utilisateur #1

marcimat opened this issue Dec 12, 2017 · 8 comments

Comments

@marcimat
Copy link
Collaborator

Constat

  • Passer les couleurs utilisateur de SPIP à SCSS pour le compiler par GULP, c’est pas vraiment faisable.
  • Par ailleurs, ça permet pas à des plugins de réutiliser les couleurs de base (autre que couleur_claire & couleur_foncée actuellement envoyées) dans les fichiers prive/style_prive_plugin_xx.html
  • L’utilisateur est limité aux couleurs qu’on a choisi : on pourrait certainement faire mieux que ça.

Proposition

Utiliser les variables CSS. C’est le top (modifiables en JS, suivent aussi l’effet de cascade...)

  • Les préférences utilisateur pourraient permettre de choisir comme actuellement un panel de couleurs, et en plus de choisir explicitement une couleur désirée avec un picker
  • Ces couleurs sont déclarées dans :root ensuite en variables CSS au tout début du head dans l’espace privé (juste avant les autres styles CSS). Elles deviennent alors utilisables dans tout fichier CSS (dans les navigateurs assez récents).
  • On pourrait aussi déclarer une taille de police de base (sur la balise html), qui pourrait être définie dans les préférences utilisateurs. En utilisant des rem ensuite partout ça devrait être assez sympa.
    Ça donne donc par exemple :
<style type="text/css">
:root {
	--couleur-foncee: #fa9a00;
	--couleur-claire: #ffc000;
	--couleur-lien: #FF5B00;
	--couleur-lien-off: #B49280;
	--html-font-size: 1.2em;
}
</style>
  • Ensuite on utilise directement dans le scss une déclaration de type :
:root {
	--couleur-defaut: var(--couleur-foncee, #8F8FBD);
}

Et on peut alors utiliser à différents endroits var(--couleur-defaut) simplement.

Problèmes rencontrés

J’ai fait quelques tests en partie concluants, mais je suis à demi bloqué

  • CSS ne sait pas encore faire de calcul de couleurs pour augmenter ou baisser la luminosité par exemple. Ça sera un jour fait avec https://drafts.csswg.org/css-color/#funcdef-color-mod mais on n’en est pas là.
  • SCSS sait le faire, mais évidemment pas avec des variables CSS (dont il ne connait pas la valeur en plus).

Solutions possibles

Comme alternative à l’impossibilité de modifier les couleurs en CSS depuis une variable, je me dis qu’une possibilité serait de faire générer un panel de couleurs par SPIP depuis les couleurs choisies de l’utilisateur. C’est pas extrêmement compliqué, mais ça serait bien de pouvoir le faire approximativement aussi en JS (https://stackoverflow.com/questions/5833624/increase-css-brightness-color-on-click-with-jquery-javascript) pour que les couleurs se modifient instantanément dans les préférences utilisateur.

On pourrait avoir quelque chose comme :

--couleur-principale-10: #nnnnnn; // lumineux
--couleur-principale-20: #nnnnnn;
--couleur-principale-30: #nnnnnn;
...
--couleur-principale-90: #nnnnnn; // sombre

Et ceci pour chaque couleur.

Est-ce que ça suffirait ? Est-ce qu’on aurait une plage suffisante de choix ?

@marcimat marcimat added the css label Dec 12, 2017
@tcharlss
Copy link
Owner

tcharlss commented Dec 12, 2017

Hop, intéressant tout ça, je répondrai ce soir :)

@marcimat
Copy link
Collaborator Author

J’ai continué des tests donc avec des variables en sus aux nommages abscons (marre)

<style type="text/css">
:root {
<BOUCLE_couleurs(DATA){source tableau, #ARRAY{
	couleur_foncee,couleur-principale,
	couleur_claire,couleur-secondaire,
	couleur_lien,couleur-lien,
	couleur_lien_off,couleur-lien-off,
}}>
	--#VALEUR: #EVAL{$GLOBALS['#CLE']};
	--#VALEUR-p10: [#(#EVAL{$GLOBALS\['#CLE'\]}|couleur_foncer{0.1})];
	--#VALEUR-p20: [#(#EVAL{$GLOBALS\['#CLE'\]}|couleur_foncer{0.2})];
	--#VALEUR-p30: [#(#EVAL{$GLOBALS\['#CLE'\]}|couleur_foncer{0.3})];
	--#VALEUR-m10: [#(#EVAL{$GLOBALS\['#CLE'\]}|couleur_eclaircir{0.1})];
	--#VALEUR-m20: [#(#EVAL{$GLOBALS\['#CLE'\]}|couleur_eclaircir{0.2})];
	--#VALEUR-m30: [#(#EVAL{$GLOBALS\['#CLE'\]}|couleur_eclaircir{0.3})];
</BOUCLE_couleurs>
}
</style>

Note: faudra virer cet usage de eval + $globals… grml que c’est moche

En js je l’ai aussi avec :

$('.formulaire_#FORM .editer_couleur input[type=radio]').on('change', function(){
	if (this.checked) {
		var $me = $(this);
		$.each(['couleur-principale', 'couleur-secondaire', 'couleur-lien', 'couleur-lien-off'], function(i, key){
			var value = $me.data(key);
			$(':root')
				.css('--' + key, value)
				.css('--' + key + '-p10', ColorLuminance(value, -.1))
				.css('--' + key + '-p20', ColorLuminance(value, -.2))
				.css('--' + key + '-p30', ColorLuminance(value, -.3))
				.css('--' + key + '-m10', ColorLuminance(value, .1))
				.css('--' + key + '-m20', ColorLuminance(value, .2))
				.css('--' + key + '-m30', ColorLuminance(value, .3))
			;
		});
	}
});

function ColorLuminance(hex, lum) {
	// validate hex string
	hex = String(hex).replace(/[^0-9a-f]/gi, '');
	if (hex.length < 6) {
		hex = hex[0]+hex[0]+hex[1]+hex[1]+hex[2]+hex[2];
	}
	lum = lum || 0;

	// convert to decimal and change luminosity
	var rgb = "#", c, i;
	for (i = 0; i < 3; i++) {
		c = parseInt(hex.substr(i*2,2), 16);
		c = Math.round(Math.min(Math.max(0, c + (c * lum)), 255)).toString(16);
		rgb += ("00"+c).substr(c.length);
	}

	return rgb;
}

Dans le variable.css

:root {
	--couleur-defaut: var(--couleur-principale, $couleur-fallback);
	--couleur-lightest: var(--couleur-principale-m30, ajuster-couleur($couleur-fallback, (lightness: +30%)));
	--couleur-lighter: var(--couleur-principale-m20, ajuster-couleur($couleur-fallback, (lightness: +20%)));
	--couleur-light: var(--couleur-principale-m10, ajuster-couleur($couleur-fallback, (lightness: +10%)));
	--couleur-dark: var(--couleur-principale-p10, ajuster-couleur($couleur-fallback, (lightness: -10%)));
	--couleur-darker: var(--couleur-principale-p20, ajuster-couleur($couleur-fallback, (lightness: -20%)));
	--couleur-darkest: var(--couleur-principale-p30, ajuster-couleur($couleur-fallback, (lightness: -30%)));
}
// ...
// Couleurs fonctionnelles
$couleur-defaut:              var(--couleur-defaut);
// ...
// Variantes de la couleur du thème
$couleur-lightest: var(--couleur-lightest);
$couleur-lighter: var(--couleur-lighter);
$couleur-light: var(--couleur-light);
$couleur-dark: var(--couleur-dark);
$couleur-darker: var(--couleur-darker);
$couleur-darkest: var(--couleur-darkest);

Et j’ai enlevé plein d’utilisation de calculs du coup.
Bah avec ça, ça marche drôlement bien déjà.

Je suis sûr qu’avec un peu de volonté ça peut être utilisé. Reste à savoir si c’est pertinent !
Notamment est-ce qu’il faudrait pas plutôt faire écrire les variables directement avec -dark, -darker, -darkest... plutôt que des p30 ... (ma réponse est «certainement»).

Le problème principal arrive dès que tu veux utiliser une couleur spécifique issue de la couleur principale de l’utilisateur… bah… tu peux pas c’est con :)

Il y aurait peut être une possibilité de pipeline qui ajouterait des variables CSS à destination des thèmes pour compléter. Ou pas. Peut être qu’il suffit d’ajouter les couleurs qui manquent importantes. Ici une couleur-principale-fond-clair couleur-principale-fond-sombre peut être.

Toujours est-il que c’est rigolo. J’ai ça dans une branche expérimentale si tu veux que je la commite tu dis.

@marcimat marcimat changed the title Réflexion / Recherche sur les couleurs & préférences utilisateur Recherche sur les couleurs & préférences utilisateur Dec 12, 2017
@marcimat
Copy link
Collaborator Author

Après différentes tergiversations, j’ai fini par créer un fichier variables_couleurs_espace_prive.css.html qui déclare toutes les variables et déclinaisons de couleurs calculées par SPIP. Grosso modo dedans il y a des variables dans :root (le thème par défaut) et dans chaque .couleur_NN. On perd la personnalisation éventuelle d’une préférence de couleur réellement individualisé (avec un input couleur) (quoi que ce serait possible encore d’avoir un .couleur_perso {} par exemple avec ses couleurs).

Mais en fait ça me gène finalement si y a des couleurs spécifiques, ça va générer un favicon image pour chaque couleur testée par le bonhomme… et bof. (excuse bidon ok !).

Il y a quand même quelques subtilités à savoir.
Ainsi au début je déclarais des --couleur-principale: #xxxxx;
Et dans le scss j’indiquais --couleur-defaut: var(--couleur-principale). Eh bien dans ce cas le comportement de cascade de couleur n’est pas ce que j’imaginais.

Benoîtement, imaginons :

<style type='text/css'>
:root {
  --cp: blue;
  --couleur: var(--cp);
}
span {
  color: var(--couleur);
  border-bottom: 1px solid var(--cp);
}
.perso {
  --cp: red;
  color: var(--couleur);
  border-bottom: 1px solid var(--cp);
}
</style>

<span>Coucou</span> 
<span class="perso">par ici</span>

Bah, j’imaginais que «par ici» dans .perso serait écrit en rouge, car --couleur indique var(--cp) et que --cp dans .perso est rouge. Mais… il semble prendre --cp au niveau de cascade d’où est déclaré le --couleur (ici dans :root donc).

Bref… du coup, j’ai directement déclaré dans SPIP les --couleur-dark etc. Et ça marche pas mal.

@marcimat
Copy link
Collaborator Author

Ah ! Y a un moyen de pouvoir gérer plein de couleurs en plus dans SCSS…
https://stackoverflow.com/a/41265350

Déclarer non pas des couleurs complètes, mais des morceaux de rgb...

:root {
  /* #f0f0f0 in decimal RGB */
  --color: 240, 240, 240;
}
body {
  color: #000;
  background-color: #000;
}
#element {
  background-color: rgba(var(--color), 0.5);
}

Du coup, dans le SCSS on peut avoir tout un gradient d’une couleur en adaptant l’opacité.

@marcimat
Copy link
Collaborator Author

On a bien avancé dessus avec Tcharles, grâce à une super idée : utiliser hsl().

Donc actuellement du coup :

  • le formulaire de configuration des préférences ne stocke plus une couleur, mais une teinte et une saturation (par saut de 10 en 10), et offre des curseurs pour créer la couleur souhaitée.
  • la balise <body> reçoit maintenant une classe CSS teinte-30 saturation-60 par exemple, ainsi que des attributs data correspondants.
  • Un squelette SPIP génère les relations entre .teinte-XX et une variable --teinte: XX;. En fait je pense que SCSS pourrait s’en occuper maintenant vu qu’on n’a plus de calcul de couleur fait en PHP.
  • On utilise ensuite ces varibles dans SCSS. Contrainte, écrire hsl() en SCSS correspond à une fonction qui attend de pouvoir parser la couleur (hors, c’est ici une variable CSS). Donc j’ai créé une fonction _hsl et _hsla qui écrit le code CSS hsl.... qui va bien (on n’est pas les seuls à y être confronté).

Il reste un souci avec les feuilles de styles calculées qui attendent une "couleur_foncee" et "couleur_claire". Faut il leur en envoyer une ? Faut il au contraire ne pas leur en envoyer (pour mutualiser le cache CSS, vu que c’est les variables qui sont importantes maintenant ?
Et le favicon dont on génère la couleur, il faudrait limiter à quelques teintes pour pas en avoir 50, vu que les favicon SVG ne sont pas encore du tout reconnus.
À suivre.

@tcharlss
Copy link
Owner

Un pen pour visualiser les options possibles pour la palette de couleurs : https://codepen.io/tcharlss/pen/ypyVpe

@marcimat
Copy link
Collaborator Author

Comment gérer les fallback des variables en CSS et SASS
https://vgpena.github.io/winning-with-css-variables/#providing-fallbacks

@nd-
Copy link
Collaborator

nd- commented Dec 20, 2017

Dans le codepen, je trouve le dernier cas le plus intéressant (lum 50%, sat 80% max).
Les couleurs sont moins saturées que par SPIP, c'est plus homogène sur la palette.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants