תוכן עניינים
אמ;לק
Shadow DOM הוא נדבך בHTML שחשוב מאוד להכיר. מעבר לעובדה שהוא מאפשר פתרונות לבעיות מסויימות בעבודה עם HTML וCSS (מתי לאחרונה רציתם להוסיף class או ID חדש לפרוייקט ישן וגדול, ולא חששתם עד עצמותיכם מקונפליקט עם שם שכבר קיים בעמוד?), זהו הבסיס לשימוש ברכיבי ווב, או בשמם הבאזזי והלועזי – Web Components.
זה מתאפשר מכיוון ש- Shadow DOM מכיל בתוכו את היכולת ליצור ולבודד DOM ועיצוב של אותו DOM מבודד.
חשוב לציין: הפוסט הבא מתייחס לShadow DOM v0
, לו ישנה תמיכה רחבה יותר כרגע. עם זאת, Shadow DOM v1
מכיל בתוכו פונקציונליות גדולה יותר.
ביום ברוס ויין, בלילה Shadow DOM
אתם צודקים, האנלוגיה בין באטמן לShadow DOM היא צפוייה ולו רק בגלל השם, "DOM הצללים". ועדיין, אין מה לעשות..אני פשוט אוהב את באטמן. אגב, ידעתם ששותפי היקר נקסי הוא-הוא בעצם באטמן? אבל אל תספרו על זה לאף אחד. זה סוד!
אז מה זה בכלל Shadow DOM, הבאטמן הזה?
דמיינו שמעבר לDOM הרגיל והאהוב, קיים עוד לו DOM נוסף, DOM צללים. האלמנטים בDOM הצללים הזה עוברים את הרנדור ומופיעים לנו במסמך – עם זאת, אנחנו לא יכולים לגשת אליהם.
לא ברור? אני מסכים. בואו ננסה להדגים.
1 2 3 4 5 |
<video id="myVideo" width="200" height="100" controls> <source src="shadowDOM.mp4" type="video/mp4" /> </video> |
הקוד הבא יתן לנו נגן וידאו. משהו כזה בעצם:
נגן וידאו יפה ונחמד, עם כפתורי עצירה והפעלה, שליטה בעוצמת השמע והכל מעוצב מאוד נחמד וקומפקטי.
רגע, מה?! את האלמנט של הוידאו אכן אנחנו כתבנו, אבל מי כתב את יתר הדברים? מאיפה הגיעו האלמנטים האלה לכל הרוחות?
ואם יש אלמנטים בתוך אלמנט הוידאו, אני בטוח אוכל לגשת אליהם עם קצת ג'אווהסקריפט, לא?
1 2 3 4 5 |
var video = document.getElementsById("myVideo"); console.log(video.firstChild); // אנחנו מקבלים NULL |
האם בעצם מתרחש פה קסם?
התשובה היא לא ולא. זה פשוט הבאטמן שלנו, Shadow DOM.
הגיע הזמן לשלוף את סימן העטלף
כן, לא מספיק שזה רפרנס קלוש, הוא גם מתורגם לעברית ובכלל מאבד את משמעותו. ועם זאת, אין מה לעשות..אין על באטמן. וגם את אבא-באטמן אתם תאהבו!
בכל אופן, הגיע הזמן להיכנס לצללים ולחשוף את הShadow DOM המתחבא באמצעות הפנס שלנו (עיין ערך סימן העטלף!) – כלי המפתחים של Chrome.
נכנס לSettings מתוך חלון הDeveloper Tools, שמוכר יותר בתור Inspect Element. שם, תחת הכותרת Elements, נסמן וי על ההגדרה הבאה:
Show user agent shadow DOM
עכשיו, כשנעשה Inspect Element על אלמנט הוידאו שלנו, נוכל ממש לראות את האלמנטים המרכיבים אותו:
ברוכים הבאים לאזור האפל של HTML 🙂
ולמה בדיוק אני צריך את כל הכישופים האלו?
Shadow DOM מתייחס ליכולת של הדפדפן לכלול DOM נוסף ונסתר, מעין "תת-DOM", לתוך הרינדור של מסמך. עם זאת, הרינדור לא מתבצע לתוך הDOM הרגיל והראשי של המסמך, כמו שראינו למעלה.
הרינדור הוא בעצם נסתר מן העין, ואין לנו יכולת לגשת אליו או להשפיע עליו, גם לא דרך הג'אווה סקריפט.
חלק מהסיבות שבגינן הבאטמן שלנו קיים הן ההבנה של מפתחי הדפדפנים שלקודד את המראה וההתנהגות של אלמנטים מסויימים בHTML ידנית היא קשה ולא יעילה. הShadow DOM הוא סוג-של הרמאות הקטנה שלהם.
יחד עם זאת, Shadow DOM הוא סטנדרט מתגבש בעולם הווב (עם כי, יש עוד קצת דרך לעבור) אשר נותן למפתחים את היכולת ליצור ולבודד DOM ועיצוב של אותו DOM מבודד.
איך אנחנו יכולים לנצל את זה לטובתנו – בשביל זה תאלצו להמשיך לקרוא 🙂
רמאות על רמאות
טוב, אז הנה טריק קטן שחלקכם בטח מכירים (או מכירים מבלי באמת להכיר). למרות כל ההצהרות הבומבסטיות, יש חלקים מסויימים בShadow DOM הדיפולטיבי של הדפדפן עליהם ניתן להחיל חוקי CSS.
נניח למשל, שאנחנו רוצים לשחק עם הצבע של תצוגת הזמן בנגן הוידאו שלנו..מה, לא ידעתם שאפשר? קבלו!
1 2 3 4 5 |
video::-webkit-media-controls-current-time-display { color: red; } |
וכמובן שיש עוד המון אלמנטים דיפולטיביים שניתן לעצב – מאופי לחיצה בפלאפונים (לרוב לחיצה בפלאפונים משאירה ריבוע כחול כזה מסביב לאלמנט, מעין פוקוס), ועד לנראות של שדות מתקדמים בטפסים.
כל אחד רוצה Shadow DOM משלו!
לפני שאלפרד העוזר החביב ומנהל האחוזה של מר ברוס ויין, מעניק לכם את הכוח ליצור DOM צללים משלכם, חשוב שנעבור בזריזות על המבנה של Shadow DOM שאנחנו יוצרים.
את הצל אנחנו מדביקים ל"אלמנט מארח". הוא יכיל בתוכו את הShadow Root, ובתוך הShadow Root ימצא התוכן שבחרנו לשים בShadow DOM שלנו.
אנצל את ההזדמנות להזכיר שכל המארק-אפ והCSS של הShadow DOM מבודדים, משמע חוקים והגדרות של המסמך לא ישפיעו על הShadow DOM, ולהפך.
וזה, הרי, כל מה שאי פעם רצינו, לא?
ליצור את הShadow DOM
מבחינת HTML, אנחנו צריכים את האלמנט המארח:
1 2 3 |
<div id="host"></div> |
כדי ליצור את הShadowRoot, נשתמש בפונקצייה createShadowRoot()
:
1 2 3 4 |
var host = document.getElementById('host'); var shadow = host.createShadowRoot(); |
אוקיי, באטמנים שכמותנו, אז יש לנו את הShadow Root שלנו, אבל זה לא מספיק! צריך שיהיו בו אלמנטים בשביל שהוא יהיה Shadow DOM אמיתי, לא?
1 2 3 4 5 |
var image = document.createElement('img'); image.src = "https://c2.staticflickr.com/8/7375/14177453364_a3442dfa70.jpg"; shadow.appendChild(image); |
נסו לעשות Inspect על דוגה החמוד שלנו ^
אבל אל תשכחו, גם כשאנחנו יוצרים את הShadow DOM בעצמנו, הוא עדיין מתחבא לו בצללים(באטמן או לא באטמן?).
לא מאמינים לי? נסו לראות מה תקבלו בפקודה הבאה:
1 2 3 |
console.log(document.querySelector('#host img')); |
רמז: זה מתחרז עם המילה קל..
ומה לגבי דברים גדולים יותר?
אוקיי, אז שתלנו תמונה בDOM הצללים שיצרנו בעצמנו. Yippee ki yay.
הגיע הזמן לצאת לעולם האמיתי, או במילים אחרות: בואו ננסה לעשות דברים מורכבים יותר.
בואו ניתן לדוגה החמוד שם, כי הרי מה זה שיבה-אינו בלי שם בעולם הזה?
1 2 3 4 5 |
<div class="cute-doge"> <span class="cute-doge-name">DOGE</span> </div> |
וגם קצת סטייל:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<style> .cute-doge { background-image: url('https://c2.staticflickr.com/8/7375/14177453364_a3442dfa70.jpg'); width: 300px; height: 300px; } .cute-doge-name { font-size: 50px; font-weight: bold; font-family: sans-serif; color: #00ada7; text-shadow: 1px 1px 1px #005250; } </style> |
טוב, אז הגענו לשפת הבריכה של הגדולים. מה עכשיו? איך דוחפים את כל הבלגן הזה לShadow DOM?
התשובה טמונה בתגית <template>
, ולמי שלא מכיר זה בדיוק הזמן המושלם.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
<template id="doge"> <style> .cute-doge { background-image: url('https://c2.staticflickr.com/8/7375/14177453364_a3442dfa70.jpg'); width: 300px; height: 300px; } .cute-doge-name { font-size: 50px; font-weight: bold; font-family: sans-serif; color: #00ada7; text-shadow: 1px 1px 1px #005250; } </style> <div class="cute-doge"> <span class="cute-doge-name">DOGE</span> </div> </template> |
ועכשיו, באטמן!
1 2 3 4 5 6 |
var batman = document.getElementById('host').createShadowRoot(); var doge = document.querySelector('#doge'); var clone = document.importNode(doge.content, true); batman.appendChild(clone); |
שימו לב: אנחנו משתמשים בquerySelector()
ו-ב importNode()
מפאת האופי של <template>
, שהרי גם הוא לא בדיוק אלמנט שמתרנדר למסמך.
Shadow DOM ו-SEO
מפתחים רבים צריכים להתעסק, ברמה כזו או אחרת, גם בצד הקידומי של האתר, לפחות מבחינה טכנית.
לכן נשאלת השאלה, איך הדברים בShadow DOM מתאנדקסים, ביחס לאינדוקס הרגיל של הDOM.
מכיוון שShadow DOM עדיין מוגדר כדראפט, קשה לקבוע נחרצות דברים כאלה. מה שכן אפשר להגיד זה שקודם כל, מנועי החיפוש מתמודדים מול דברים דומים בהצלחה – אתרים מבוססי AJAX כבד, למשל.
בנוסף, ישנם אתרים שכבר בנויים באמצעות Web Components, משמע מסתמכים על Shadow DOM – ומתאנדקסים טוב מאוד. bitHound הוא אחד מהם.
Shadow DOM ונגישות
עוד שקרוב ללב המפתחים הישראלים, הוא נושא הנגישות.
בפוסט שכתב סטיב פולקנר, הוא מציין שאין בעיית נגישות עם ה-Shadow DOM. קוראי המסך מתמודדים עם מסמכים מרונדרים כבר, ובגלל שה-Shadow DOM מתרנדר למסמך, אין איתו שום בעיה.
יחד עם זאת, סטיב מסביר שאסור לנו לשכוח את השימוש בARIA באלמנטים בתוך DOM הצללים.
סיכום – מShadow DOM לWeb Components
קודם כל, אתחיל בהבהרה חשובה:
הרבה מדריכים שמסתובבים באינטרנט לגבי Shadow DOM ו- Web Components הם אינם מעודכנים.
חלק מהמדריכים האלו מכלילים בדרך לWeb Components, שמתחילה בShadow DOM ובטמפלייטים, את התגיות <content
>
או <shadow>
, על מנת להוציא את התוכן מתוך ה<template>
, ולשלוט ביכולת לשנות אותו.
<content>
ו- <shadow>
הן תגיות שהופסקה התמיכה בהן, וההמלצה הנוכחית היא לא להשתמש בהן יותר. הן יוחלפו בעתיד על ידי התגית <slot>
, תגית שמטרתה ליצוק תוכן לתוך Shadow DOM.
אז Shadow DOM זה באמת נחמד, ותמיד כיף לגעת בצדדים "אפלים" בHTML. עם זאת, חשוב לזכור שהשימוש העיקרי בShadow DOM הוא בשביל ליצור Web Components – העתיד של פיתוח הWEB.
הShadow DOM הוא הבסיס לWeb Components, אבל לא לדאוג – אני מבטיח שתקבלו גם מדריך מלא ומקיף לWeb Components! 😉
מקורות
- דימיטרי גלזקוב – מסביר מה זה לעזאזל Shadow DOM
- W3C – הדראפט הרשמי על Shadow DOM
- MDN – הסבר שימוש בShadow DOM
אם אתם רוצים להיות הראשונים לדעת כשהמדריך לWeb Components מתפרסם, הירשמו פה למטה לניוזלטר, אנחנו מעריכים את זה!


5 תגובות
תיקון קל
8 בינואר 2017 - 5:27לא אלברט, אלפרד
שלומי זק
8 בינואר 2017 - 10:59לגמרי! איזו פדיחה.
תוקן 🙂
רם
15 בינואר 2017 - 21:01שלום, ותודה על המדריך!
לא כל כך הבנתי את הסעיף ״רמאות על רמאות״. מה בעצם מאפשר קיום של חלקים מסויימים בShadow DOM הדיפולטיבי של הדפדפן שעליהם ניתן להחיל חוקי CSS?
שלומי זק
24 בינואר 2017 - 17:45הי רם, שמח שנהנת מהמדריך 😉
על חלקים מסויימים בShadow DOM הדיפולטיבי של הדפדפן אכן ניתן להכיל חוקי CSS, מכיוון שכך יצרו אותם.
לא מעט מהShadow DOM הדיפולטיבי של הדפדפן לא נוצר בשביל "להחביא" אלמנטים מסויימים ממפתחי הWEB, אלא דווקא בשביל להקל עליהם את העבודה, ולעיתים גם בשביל להקל על מפתחי הדפדפנים את העבודה.
מקווה שהצלחתי להבין את השאלה כמו שצריך, אם לא אתה יותר ממוזמן לחדד את השאלה!