
Tuto système de notation par étoiles PHP - CSS
Rich Snippets de Google, optimisation SEO, comment construire et intégrer un système de notation par étoiles simple pour se démarquer dans les résultats Google ?





html
css
jquery

Avant toute chose, ce modeste article n'a aucunement vocation à vous convaincre du bien-fondé de son objet (de très bonnes pages s'en chargent avec brio, cf la note en bas de ce tuto par exemple) mais la majorité des études récentes allant dans le sens très clair d'un apport positif chez Google et son référencement SEO, voici en quelques étapes simples, comment coder un système de notation par étoiles.
Loin de l'idée du plugin aux 15 000 options "qui fait tout sauf le café", ou du CSS superbe mais qui vient avec son tube d'aspirine, visons un système simple et qui se tient quand même : c'est le même système qui sert aux pages de ce blog, vous le voyez donc marcher avant même de commencer !
En deux mots : le principe est ultra-simple : on aligne 5 étoiles transparentes comme celle-ci

et on les place sur une div dont la particularité va être de s'allonger suivant la note obtenue, le reste c'est du code basique.
Comme prévu : Simplissime.
/*code CSS */
.tde {height:20px;width:20px;cursor:pointer;}
#value {height:20px; width: <?=$value1;?>px; background:#E0E001;}
#glob {display: flex;}
$value1 ques aco me direz-vous ? En fait c'est tout simplement la transformation de la moyenne des notes entre 0 et 5 en pixels rapportée à la longueur de votre div #glob (en fonction de la taille des étoiles) ; et dans le système de ce blog, la moyenne c'est $value, alors bon... ;-)
<!--div optionnelle pour contenir le tout-->
<div style="float:right;margin-top : 10px;width:100px;">
<!--div en arrière-plan qui s'allongera en fonction de la valeur de $value1-->
<div id="value">
<!--div qui contient les étoiles-->
<div id="glob" >
<img id="tde_1" src="images/star.png" class="tde"/>
<img id="tde_2" src="images/star.png" class="tde"/>
<img id="tde_3" src="images/star.png" class="tde"/>
<img id="tde_4" src="images/star.png" class="tde"/>
<img id="tde_5" src="images/star.png" class="tde"/>
</div>
</div>
</div>
Quelques explications : Il est capital que la div au 2nd plan ne soit ni plus haute ni plus basse que la div qui contient les étoiles, et attention à la valeur de $value1 : basiquement, il faudra transformer la note obtenue de la base de donnée (entre 0 et 5 donc) en longueur en pixel, où 0 = 0px et où 5 = la longueur de #glob (ici 100px) ; notez au passage le "display: flex", de l'excellent Flexbox
Vous obtenez donc ça : ($value1 = 31)

A ce stade, vos 5 étoiles sont alignées dans leur div, le tout sur la div de fond (si vous avez mis une valeur valide pour $value1, vous avez déjà obtenu un résultat ;-) mais rien ne bouge, passons donc au JQuery, également tout simple :
//on détecte la présence de la souris sur une étoile
$(".tde").mouseover(function(){
//Grâce à substring(), on récupère le numéro dans l'id de cette étoile et on la stocke dans une variable en ayant supprimé le préfixe "tde_", bonnes pratiques du HTML !
var nbr = $(this).prop('id').substring(4);
//on impose la couleur jaune dans le fond transparent de cette étoile
$(this).css( "backgroundColor", "#E0E001" );
//et en même temps, on met toutes les étoiles en-dessous de nbr en jaune.
$( ".tde").slice(0, nbr).css( "backgroundColor", "#E0E001" );
//et toutes celles au-dessus de nbr en gris
$( ".tde").slice(nbr).css( "backgroundColor", "#A1A1A1" );
})
//et quand la souris s'en va, on annule le fond jaune sous les étoiles pour garder uniquement celui de #value
$("#glob").mouseout(function(){
$(".tde").css('backgroundColor', "" );
})
Mirifique résultat :
Et le tour est joué, au moins pour l'aspect, en quelques lignes simples.
Pour le reste, il suffira de détecter un click() dans une .tde, d'envoyer la variable nbr et un identifiant de la page via un appel ajax() pour updater une base de données qui renverra les infos à insérer dans le Rich Snippet (c'était quand même le but initial) ici sous cette forme par exemple :
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "vM", //vote moyen
"reviewCount": "tV" //total des votes
},
N'oubliez pas de surcharger la valeur "width" de #value via le retour de l'appel Ajax().css('width', 'length'), ainsi vous aurez l'actualisation en "live". Un point à aborder également : qui vote ? Si c'est réservé aux membres inscrits, pas de souci, il suffit de ne faire l'appel que lorsqu'une session est ouverte, sinon, pour limiter les petits malins, passer par un cookie en même temps que l'inscription dans la base ; ce n'est pas le plus efficace, loin s'en faut, mais on dit que c'est l'intention qui compte -)
Note : pour l'intérêt de la notation par étoiles chez Google, on peut consulter cet article complet sur la question et très bien documenté : avis étoiles
Et pour toute question, n'hésitez pas à me contacter
A voter ;-)
Et merci pour le blog, pas beaucoup d'articles, mais très intéressants
Bonne continuation
Merci d'avoir pris le temps de lire ce message même si vous ne pouvez pas m'aider.
Pas de problème, alors dans l’ordre, prenons un ensemble de 20px de haut et 100px de large :
On fait une div d’une hauteur de 20px et d’une longueur de $1. ($1 c’est la valeur des votes que renvoie le serveur, e.g. 4.1, modifiée pour s’adapter à la longueur du système, ici ça fera 82px donc.
On peut faire un truc genre
$1 = ($Noteobtenue * $LongueurDiv) / 5;
On remplit cette div en jaune.
"Au-dessus", on superpose la div avec les étoiles transparentes, également de 20px de haut, ce qui fait qu’on verra à travers les étoiles le fond jaune. S’il est à zéro, on ne verra rien, s’il est à 82px, on verra jusqu’à la 4è étoile.
Si elles ne sont pas de la même hauteur, l’arrière-plan et les étoiles ne seront pas ajustés (en gros, le jaune ne remplira pas les étoiles dans le sens de la hauteur) ça fera très moche. J’ai écrit « pas plus haute », je vais corriger car en effet, ça n’est pas très clair.
Si la div de fond est trop haute, ça fera quelque chose comme ça :

(Encore qu'on peut limiter la casse avec un
overflow:hidden
sur le container.Et si elle est trop basse ça fera

Pour "flexbox", c’est tout simplement un module CSS qui a "révolutionné" la façon de distribuer les emplacements flexibles, cf le lien.
J'espère que ça vous a aidé ; n'hésitez pas à me demander si c'est toujours pas clair, idéalement via mon mail : contact@gb-net.fr
Cordialement
Guillaume
J'ai essayé comme vous faites et ça marche bien, mais je ne vois pas comment récupérer les notes une fois que quelqu'un a voté, ni comment on affiche la moyenne comme dans vos articles. je ne suis pas développeur et j'ai l'impression d'avoir passé une étape.
Cet article ne traite en effet que de ce qu'on voit (le front-end), et en soi, si c'est un bon début, il ne suffit pas à faire un système complet.
Sur ce blog par exemple, le principe est en gros
- de récupérer la valeur de l'étoile au click (comme vu plus haut avec le substring sur l'id)
- d'envoyer cette valeur vers le serveur
- de la stocker (en l'ajoutant au total) dans une Bdd et d'incrémenter le nombre de votes
- de retourner une moyenne (comme au chargement initial de la page) et d'allonger la div en fonction de cette moyenne et de sa longueur propre (cf commentaire au-dessus).
Rien de bien compliqué en fait, mais indispensable ;-)
Bon courage
Guillaume
merci !
C'est pas mal, mais y a t-il une suite de prévue ?
Parce que comme ça, ça ne marche pas chez moi ;-(
Merci
C'est normal, cet article ne traite que de l'aspect à l'écran de l'affaire, et pas du tout de ce qui se passe derrière.
Et non, ça n'était pas prévu, mais bon, je vais faire un petit sujet genre "suite et fin.."
Ce sera mon cadeau de Noël !
A bientôt
Guillaume
Il vaut mieux coder cela aujourd'hui en pure CSS, car c'est tout à fait possible.
En plus, dans l'article, il n'y a que la partie "graphique" de la chose. Ou est la partie "traitement" ?
Merci pour le commentaire.
Le côté traitement n'était pas prévu au début mais vu la demande, je vais le faire (cf msg du dessus).
Pour le 100% CSS, à mon sens c'est valable si on tourne sans JS. Or il y en aura forcément ne serait-ce que pour envoyer tout ceci vers le serveur (et actualiser les étoiles suivant le retour), donc du coup, tout est traité avec 7 lignes de JQ et un appel Ajax, ça ne me paraît pas illogique d'autant que la modification "dynamique" de la div en fonction de la réponse est le principal objet de cet article, alors....
https://css-tricks.com/star-ratings/
Ca marche très bien, très bon tuto, mais je ne trouve pas la suite côté serveur ?