כפתורי דירוג הפכו פופולריים באתרים רבים. כפתורים אלו מאפשרים לגולשים לדרג עד כמה אהבו את המאמר, נהנו ממנו או כמה הוא ענה על ציפיותיהם. הוא מאפשר למנהלי התוכן באתר לקבל פידבק מיידי ופשוט לניטור וניתוח.
יצירת כפתורי דירוג דורשים שימוש בHTML + CSS לצורך הצגת הכפתורים, JS כדי להפעיל אותם, וקוד בצד שרת שישמור את הנתונים לDB.
בפוסט הזה נדבר על יצירת 5 כוכבים לדירוג מצד הHTML + CSS, תוך שימוש באייקונים של הספריה הנפלאה fontAwesome, שהיא מאגר עצום ופופולרי מאד של אייקונים מכל תחום שרק אפשר לחשוב עליו. (הזכרנו את fontAwesome בפוסט על כפתורי שיתוף, רוצו לקרוא אותו 🙂
הHTML
בשלב הראשון ניצור את הHTML. באופן אישי אני מעדיפה להשתמש בכפתורי רדיו ולא בתגיות כפתור או a. בעיני זה נכון יותר גם מבחינת נגישות וגם מבחינת זה שעל הגולש לבחור אחת מהאפשרויות ולא יותר, בדיוק כמו בכל רשימת כפתורי רדיו סטנדרטית.
לכל אינפוט נגדיר גם label. האינפוטים עצמם יהיו מוסתרים מהעין ומה שהגולש יראה יהיו הlabel'ים בלבד. להלן כמה דגשים חיוניים נוספים:
- על הlabel להיות כתוב אחרי האינפוט ולא לפניו. אחרת לא נוכל לעצב את הרכיב כמו שצריך
- לכל האינפוטים יהיה אותו name, אבל לכל אחד יהיה id שונה. בנוסף – כל לייבל מקבל for עם הid של האינפוט שאליו הוא שייך. לדוגמה אם הID של האינפוט הראשון הוא star1 – הרי שזה יהיה גם הfor של הלייבל הראשון, כדי שהוא יזוהה על ידי הדפדפן כלייבל של אותו אינפוט.
- כל האינפוטים והלייבלים עומדים אחד אחרי השני בHTML תחת אותו אב. שימו לב שלא לעטוף כל צמד של אינפוט + לייבל באלמנט נוסף. שוב – המבנה הזה חיוני ביותר לעיצוב של הרכיב באמצעות CSS בלבד ללא צורך בJS.
- יש למקם את האינפוטים בסדר יורד בHTML – קודם אינפוט מספר 5 והלייבל שלו, אחריהם אינפוט מספר 4 והלייבל שלו וכן הלאה. בCSS נסדר אותם שיעמדו בסדר הנכון, אבל חיוני שהסדר הHTMLי של הפריטים יהיה כזה.
הנה HTML שאמור להיות לכם נכון לשלב הזה:
<div id="rating_stars_container">
<input type="radio" name="rating" id="star_5" value="5" />
<label for="star_5">5 כוכבים</label>
<input type="radio" name="rating" id="star_4" value="4" />
<label for="star_4">4 כוכבים</label>
<input type="radio" name="rating" id="star_3" value="3" />
<label for="star_3">3 כוכבים</label>
<input type="radio" name="rating" id="star_2" value="2" />
<label for="star_2">2 כוכבים</label>
<input type="radio" name="rating" id="star_1" value="1" />
<label for="star_1">כוכב אחד</label>
</div>
נתתי ללייבלים טקסטים שכוללים הסבר על מה האינפוט מסמל. זה מיועד עבור גולשים שמשתמשים בקוראי מסך. (קראו עוד על הנגשת האתר כאן)
הCSS הבסיסי להצגת הכוכבים
ראשית כל יש להטמיע בעמוד את הCSS של fontAwesome במידה ועדיין לא הטמעתם אותו. תעקבו אחרי ההוראות שלהם כאן. הפוסט הזה מדבר על גרסה 5 של fontAwesome, יכול להיות שבגרסאות האחרות שלהם הקודים של האייקונים מעט שונה. תוכלו לעקוב ולוודא את זה באתר שלהם.
כעת נתחיל את המשחק של הכוכבים. שימו לב שבשלב הראשון אני משאירה את האינפוטים גלויים לעין, כדי לוודא שהכל מתפקד כשורה מבחינת ההתנהגות. נסתיר אותם בשלב האחרון.
אנחנו נעשה שימוש ומשחק בין 2 אייקונים שונים של fontAwesome – האחד של כוכב מלא, והשני של כוכב ריק. נכון להיום (גרסה 5 של fontAwesome כאמור למעלה) – הקוד של שתיהם זהה, ומה ששונה ביניהם הוא עובי הפונט שיש לתת. נגדיר ללייבלים שלנו גודל פונט 0 – כדי שלא יראו את הטקסט של מספר הכוכבים (כזכור – משמש רק לקוראי מסך, והם קוראים את הטקסט גם אם הוא בגודל פונט 0 ולא נראה לעין), ואז נוסיף before עם ההגדרות הבאות:
content: "\f005";
font-family: "Font Awesome 5 Free"; /* זה שם הפונט לאייקונים הללו */
font-weight: normal;
font-size: 16px; /* זו ההגדרה שתקבע את גודל הכוכבים. הגדירו אותה לפי העיצוב שאתם רוצים */
התוצאה בשלב הזה אמורה להיות משהו כזה:
המשחק בין כוכב מלא וריק
כדי להפוך כוכב ריק למלא – כל מה שצריך זה להגדיר לbefore של הלייבל שעובי הפונט יהיה בולד במקום נורמל.
יש לנו כמה מצבים שבהם אנחנו רוצים להפוך את הכוכב לכוכב מלא.
- כאשר האינפוט של אותו כוכב מסומן, כלומר – הגולש בחר את הדרגה הזו בדירוג שלו.
- כאשר הגולש עובר עם העכבר על הכוכב – נרצה גם כן לתת סימון של כוכב מלא.
ישנו עוד מצב, שעליו נדבר בהמשך.
כדי לסמן כוכב מלא עבור מעבר עכבר – זה ממש פשוט – label:hover:before מגדיר לנו עיצוב עבור before של לייבל שיש עליו כרגע מעבר עכבר. אבל כדי לסמן כוכב מלא עבור אינפוט מסומן – כאן אנחנו צריכים לתפוס before של לייבל שהאינפוט שלפניו מוגדר :checked.
כדי לבצע את זה נשתמש בסלקטורים של siblings (אלמנטים אחים) שעליו מפורט בפוסט הזה. נגדיר באופן הבא:
אינפוט במצב :checked, הלייבל שאחריו, הbefore שלו. כך:
input:checked + label:before
כך שהCSS שלנו בסוף השלב הזה אמור להיות כזה:
label:hover:before,
input:checked + label:before{
font-weight: bold;
}
וזו התוצאה שנקבל, שימו לב שכאשר אני מסמנת כוכב – הוא נשאר מסומן גם כאשר אני מורידה את העכבר.
סימון הכוכבים הנמוכים יותר בעת סימון כוכב
לרוב מקובל, שכאשר הגולש מסמן את אחד הכוכבים – כל הכוכבים במספור נמוך יותר ממנו מסומנים גם כן. לדוגמה אם סימנתי את כוכב מספר 3 – הרי שכעת מלאים הכוכבים 1-2-3 ולא רק כוכב מספר 3.
כדי לבצע את זה – נחזור למבנה הHTML'י שעליו הקפדנו. שימו לב שכוכב מספר 1 כתוב אחרי כוכב מספר 2 וכן הלאה, ולא להיפך. בזכות העובדה הזו אנחנו יכולים שוב להשתמש בסלקטור של siblings, רק שהפעם במקום לומר שרק לייבל שנמצא מיד אחרי האינפוט המסומן יהיה מודגש – נגדיר שכל לייבל שנמצא אחרי האינפוט המסומן יהיה מודגש. נצטרך רק להחליף את הפלוס (+) בסימן הזה ~. שמשמעותו – כל מי שאחרי ולא רק מי שמיד אחרי.
והנה התוצאה:
הדגשת כל הכוכבים גם בעת מעבר עכבר
אם רוצים להדגיש את הכוכבים בדירוג נמוך יותר גם במעבר עכבר, צריך להוסיף סלקטור נוסף ל2 הסלקטורים של הדגשת הbefore עם bold:
label:hover ~ label:before
משמעות הסלקטור הזה היא שכאשר עוברים עם העכבר על כוכב (הלא הוא לייבל) – לא רק הכוכב שלו עצמו יהיה מודגש, אלא גם הכוכבים (before) של כל הלייבלים שנמצאים אחריו בHTML, הווי אומר – כל הכוכבים שבדירוג נמוך יותר.
במקרה שאכן מבצעים את זה, עלולה להווצר התנהגות מוזרה בעין, שכאשר אני נמצאת עם העכבר בין 2 כוכבים – שום כוכב לא מודגש, זה קורה כי עוברים על המרווח שבין כוכבים שעליו לא הוגדרה התנהגות בולד לסימון. לכן במקרה כזה יש להקפיד שהרווח שבין הכוכבים לא יגיע מההגדרה margin אלא מההגדרה padding, שמשמעותה שוליים פנימיים בתוך האלמנט. אפשר להגדיר padding עבור הלייבל או עבור הbefore. זה לא משנה.
בנוסף מומלץ להגדיר לאלמנט שעוטף את כל הכוכבים את ההגדרה font-size: 0;, כדי למנוע רווחים של פיקסלים ספורים בין הכוכבים שאינם ניתנים לשליטה של margin או padding, כפי שתוכלו ללמוד בפוסט שמדבר על ההגדרה inline-block.
סגירת קצוות וסניפט מוכן להעתקה
נותרו לנו 2 דברים אחרונים בלבד: להסתיר את האינפוטים עצמם ולהגדיר יישור הפוך לכוכבים, כך שמספר 1 יהיה בימין ומספר 5 בשמאל ולא כמו שקורה כרגע.
כדי להסתיר את האינפוטים – במידה והאתר שלכם משתמש בCSS של bootstrap – אפשר פשוט להוסיף את הקלאס sr-only לאינפוטים והם יוסתרו מהעין. במידה ולא – תוכלו לקחת את הCSS שכאן כדי להסתיר אותם.
שימו לב לא להגדיר להם display: none; כי זה עשוי לגרום לבעיות שונות, אלא לקחת את ההגדרות הללו:
input{
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
סיימנו!
להלן קוד מוכן שתוכלו להעתיק לאתר שלכם ולהתחיל לשחק איתו מבחינת גודל הכוכבים, הצבע שלהם והמרווח ביניהם.
<div id="rating_stars_container">
<input type="radio" name="rating" id="star_5" value="5" />
<label for="star_5">5 כוכבים</label>
<input type="radio" name="rating" id="star_4" value="4" />
<label for="star_4">4 כוכבים</label>
<input type="radio" name="rating" id="star_3" value="3" />
<label for="star_3">3 כוכבים</label>
<input type="radio" name="rating" id="star_2" value="2" />
<label for="star_2">2 כוכבים</label>
<input type="radio" name="rating" id="star_1" value="1" />
<label for="star_1">כוכב אחד</label>
</div>
<style>
#rating_stars_container{
font-size: 0; /* מיועד כדי למנוע רווחים מיותרים בין הכוכבים */
direction: ltr; /* מיועד ליישור הכוכבים בסדר הנכון */
}
#rating_stars_container input{ /* הגדרות להסתרת האינפוטים מהעין */
border: 0;
clip: rect(0,0,0,0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
#rating_stars_container label:before{
content: "\f005";
font-family: "Font Awesome 5 Free";
font-weight: normal;
font-size: 20px; /* זו ההגדרה שתקבע את גודל הכוכבים. הגדירו אותה לפי העיצוב שאתם רוצים */
color: gold; /* תנו איזה צבע שאתם רוצים :) */
padding: 0 5px; /* יצירת מרווח בין הכוכבים */
}
#rating_stars_container label:hover:before,
#rating_stars_container label:hover ~ label:before, /* שורה זו נועדה להדגיש במעבר עכבר את כל הכוכבים בדירוג נמוך יותר */
#rating_stars_container input:checked ~ label:before{
font-weight: bold;
}
</style>
בהצלחה רבה וקידוד נעים 🙂