חיפוש ]

הוספת מצב כהה (Dark Mode) לאתר בעזרת localStorage

Dark Mode הפך לסטנדרט באתרים ובאפליקציות. כש-iOS, macOS, Windows ו-Android מציעים תמות כהות ברמת המערכת, משתמשים מצפים שגם אתרים יתמכו בזה.

מתג מצב כהה הופך את האתר שלכם לנגיש יותר למשתמשים שמעדיפים צבעים כהים, ואפשרות מעבר בין תמה בהירה לתמה כהה משפרת את חוויית המשתמש הכוללת.

בפוסט זה אראה שתי גישות להוספת Dark Mode לאתר שלכם: החלפת קבצי CSS פשוטה, והגישה המודרנית עם משתני CSS ותכונת data-theme.

גישה 1: החלפת קובצי CSS עם localStorage

גישה זו עובדת על ידי החלפה בין שני קבצי CSS ושמירת הבחירה של המשתמש ב-localStorage.

יצירת קבצי ה-CSS

צרו שני קבצי CSS: light-theme.css (ריק) ו-dark-theme.css שמכיל את כל דריסות ה-CSS עבור המצב הכהה.

הקובץ light-theme.css נשאר ריק מכיוון שהתמה הבהירה היא ה-stylesheet ברירת המחדל של האתר. הוסיפו קישור לקובץ ה-CSS ב-<head> של האתר:

<link id="themeCssLink" rel="stylesheet" type="text/css" href="/path-to/light-theme.css"/>

התאימו את הנתיב למיקום הקובץ בתיקיית האתר שלכם.

יצירת כפתור המעבר

הוסיפו כפתור לפוטר של האתר שמחליף בין המצבים:

<button id="toggleButton">Change Contrast</button>

הנה CSS למיקום הכפתור כפתור קבוע בפינה הימנית התחתונה:

#toggleButton {
    right: 10px;
    left: auto;
    position: fixed;
    bottom: 14px;
    z-index: 999999;
    display: inline-block;
    text-indent: -999999px;
    width: 40px;
    height: 40px;
    background: linear-gradient(-45deg, #ffd600, #ffd600 49%, #fefefe 49%, #fefefe 51%, #2d2d2d 51%);
    border-radius: 50%;
    border: 0;
    cursor: pointer;
}

JavaScript למעבר עם localStorage

כדי לשמר את העדפת המשתמש בין טעינות עמודים ומפגשי דפדפן, נשתמש ב-localStorage – API של הדפדפן ששומר זוגות key/value באופן מקומי ללא תפוגה.

מידע ב-localStorage שורד רענון דף והפעלה מחדש של הדפדפן. בניגוד לעוגיות, הוא אינו דורש הודעת הסכמה.

ניתן לבדוק ערכי localStorage בכלי המפתחים של Chrome בלשונית Application:

LocalStorage In Chrome Dev Tools

הנה ה-JavaScript שמטפל במעבר:

document.addEventListener('DOMContentLoaded', () => {
    const themeStylesheet = document.getElementById('themeCssLink');
    const themeToggle = document.getElementById('toggleButton');
    const storedTheme = localStorage.getItem('themeColor');

    if (storedTheme) {
        themeStylesheet.href = storedTheme;
    }
    themeToggle.addEventListener('click', () => {
        if (themeStylesheet.href.includes('dark')) {
            themeStylesheet.href = '/path-to/light-theme.css';
        } else {
            themeStylesheet.href = '/path-to/dark-theme.css';
        }
        localStorage.setItem('themeColor', themeStylesheet.href);
    });
});

זכרו לעדכן את הנתיבים בשורות 10 ו-12 כך שיתאימו למיקום בפועל של קבצי ה-CSS שלכם.

הקוד רץ אחרי DOMContentLoaded כדי להבטיח שה-DOM נפרס לחלוטין. הוא בודק את localStorage עבור העדפה שמורה, מחיל אותה אם נמצאה, ומאזין ללחיצות על הכפתור כדי להחליף בין תמות.

גישה 2: משתני CSS עם data-theme (מומלץ)

הגישה המודרנית והמומלצת משתמשת ב-משתני CSS (custom properties) במקום החלפת קבצי CSS שלמים. זה חוסך את בקשת ה-HTTP הנוספת, מבטל את הקובץ הריק, והופך את המעבר למיידי.

הגדירו את הצבעים כמשתני CSS ודרסו אותם עבור התמה הכהה:

:root {
    --bg-color: #ffffff;
    --text-color: #1a1a1a;
    --link-color: #0066cc;
    --surface-color: #f5f5f5;
    --border-color: #e0e0e0;
}

[data-theme="dark"] {
    --bg-color: #121212;
    --text-color: #e0e0e0;
    --link-color: #66b3ff;
    --surface-color: #1e1e1e;
    --border-color: #333333;
}

body {
    background-color: var(--bg-color);
    color: var(--text-color);
}

a {
    color: var(--link-color);
}

ה-JavaScript פשוט יותר כי מחליפים רק תכונת data-theme על אלמנט ה-<html>:

document.addEventListener('DOMContentLoaded', () => {
    const toggle = document.getElementById('toggleButton');
    const savedTheme = localStorage.getItem('theme');

    if (savedTheme) {
        document.documentElement.setAttribute('data-theme', savedTheme);
    }

    toggle.addEventListener('click', () => {
        const current = document.documentElement.getAttribute('data-theme');
        const next = current === 'dark' ? 'light' : 'dark';
        document.documentElement.setAttribute('data-theme', next);
        localStorage.setItem('theme', next);
    });
});

כיבוד העדפות מערכת עם prefers-color-scheme

דפדפנים מודרניים תומכים ב-media query בשם prefers-color-scheme, שמזהה אם מערכת ההפעלה של המשתמש מוגדרת למצב בהיר או כהה. ניתן להשתמש בו כדי להתאים אוטומטית להעדפת המערכת כברירת מחדל, ועדיין לאפשר דריסה ידנית דרך הכפתור:

document.addEventListener('DOMContentLoaded', () => {
    const toggle = document.getElementById('toggleButton');
    const savedTheme = localStorage.getItem('theme');

    if (savedTheme) {
        document.documentElement.setAttribute('data-theme', savedTheme);
    } else if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
        document.documentElement.setAttribute('data-theme', 'dark');
    }

    toggle.addEventListener('click', () => {
        const current = document.documentElement.getAttribute('data-theme');
        const next = current === 'dark' ? 'light' : 'dark';
        document.documentElement.setAttribute('data-theme', next);
        localStorage.setItem('theme', next);
    });
});

הקוד עוקב אחר סדר העדיפויות הנכון: העדפת משתמש שמורה ראשונה, אחריה העדפת מערכת, ואז ברירת מחדל (בהיר).

שאלות נפוצות

שאלות נפוצות על הוספת מצב כהה לאתר:

מהי הדרך הטובה ביותר לממש מצב כהה באתר?
הגישה המומלצת היא שימוש ב-CSS custom properties (משתנים) עם תכונת data-theme על אלמנט ה-<html>. הגדירו את הצבעים כמשתנים ב-:root ודרסו אותם תחת [data-theme="dark"]. החליפו את התכונה עם JavaScript ושמרו את הבחירה ב-localStorage.
מה עושה prefers-color-scheme?
prefers-color-scheme הוא media query ב-CSS שמזהה אם מערכת ההפעלה או הדפדפן של המשתמש מוגדרים למצב בהיר או כהה. הוא נתמך בכל הדפדפנים המרכזיים מאז 2020. השתמשו בו כדי להתאים אוטומטית להעדפת המערכת כתמה ברירת מחדל, תוך מתן אפשרות למשתמשים לדרוס באמצעות כפתור.
איך שומרים את העדפת המצב הכהה של המשתמש?
השתמשו ב-localStorage.setItem('theme', 'dark') כדי לשמור את ההעדפה וב-localStorage.getItem('theme') כדי לשלוף אותה בטעינת העמוד. localStorage שורד רענוני דף והפעלות מחדש של דפדפן, ובניגוד לעוגיות, אינו דורש הודעת הסכמה.
האם לשמור מצב כהה בעוגיות או ב-localStorage?
localStorage הוא הבחירה הטובה יותר להעדפות מצב כהה. הוא שומר נתונים מקומית בדפדפן בלי לשלוח אותם לשרת בכל בקשה (בניגוד לעוגיות), ואינו מפעיל דרישות הסכמת עוגיות. המגבלה היחידה היא ש-localStorage הוא למכשיר בלבד, כך שההעדפה לא תסונכרן בין דפדפנים או מכשירים שונים.
איך מונעים הבהוב של תמה שגויה בטעינת העמוד?
מקמו סקריפט inline קטן ב-<head> של ה-HTML (לפני שכל CSS נטען) שקורא את התמה השמורה מ-localStorage ומגדיר את תכונת data-theme מיידית. זה רץ לפני שהעמוד מרונדר, ומונע את ההבהוב. למשל:
<script>
  const t = localStorage.getItem('theme');
  if (t) document.documentElement.setAttribute('data-theme', t);
</script>

סיכום

הדרך הפשוטה ביותר להוסיף מצב כהה היא החלפת קבצי CSS עם localStorage, אבל הגישה המודרנית עם משתני CSS ותכונת data-theme יעילה יותר – בלי בקשות HTTP נוספות, מעברים מיידיים, ותחזוקה קלה יותר. שלבו אותה עם ה-media query בשם prefers-color-scheme כדי לכבד את העדפת המערכת של המשתמש ועדיין לאפשר דריסה ידנית.

דיון ותגובות
5 תגובות  ]
  • איש נחמד 19 יולי 2021, 17:59

    במקום לקסטם את הטקסט של כפתור ההחלפה עם JS, אפשר גם לעשות את זה עם :before בקבצי ה-CSS של התבנית.
    לא בהכרח שזה יותר עדיף.

  • אפרת 17 אוגוסט 2021, 12:02

    שלום וברכה,
    ראשית אני רוצה להודות על הפוסט בנוגע להוספת מצב כהה.
    הוא נתן לי רעיון נפלא בהקשר להגשת פרויקט בJQUERY שאני במהלכו.
    רציתי רק לשאול לגביו מספר שאלות אשמח לתגובתכם :
    1. האם את העיצוב של הכפתור צריך להוסיף בשני קבצי העיצוב?
    2. משום מה כשהוספתי את האיבנט לTS הוא מסמן לי את המילה HREF

    אז תודה ושוב תודה על הפוסט הנוכחי ועוד הרבה פוסטים שקראתי באתר והחכמתי מהם המון.

    • רועי יוסף 17 אוגוסט 2021, 12:35

      היי אפרת,

      1. במקרה שלך כן.
      2. מה זה TS?

      שמח שאת נהנית מהבלוג…

  • נפתלי שטיין 19 דצמבר 2021, 21:17

    תודה על הבלוג הנפלא, למדתי ממך המון.

    בדיוק יצא לי לממש אתר כזה, היות ואני עובד עם CSS Variables הפתרון היה מאוד נוח. אני משנה את שלושת הצבעים הראשיים של האתר באמצעות js וזה עובד פשוט נפלא. הנה הקוד שמצאתי ב StackOverflow.

    document.documentElement.style.setProperty('--your-variable', '#YOURCOLOR');
    • רועי יוסף 20 דצמבר 2021, 11:12

      היי נפתלי,

      שמח לשמוע שאתה נהנה ולומד 🙂 אכן השימוש ב CSS Variables אידיאלי בסיטואציה הזו.. תודה ששיתפת..

השאירו תגובה

הוסיפו קוד באמצעות הכפתורים מטה. למשל, בכדי להוסיף PHP לחצו על הכפתור PHP והוסיפו את הקוד בתוך השורטקוד. מצאתם שגיאה בפוסט? עדכנו אותנו...

Savvy WordPress Development official logo