מוקדם יותר השנה, הוצאתי בעצמי ספר אלקטרוני בשם הבנת הבטחות JavaScript (חינם להורדה). למרות שלא הייתה לי כל כוונה להפוך אותו לספר מודפס, מספיק אנשים הגיעו לשאלות לגבי גרסה מודפסת שהחלטתי לפרסם אותה גם בעצמי. חשבתי שזה יהיה תרגיל קל באמצעות HTML ו-CSS כדי ליצור PDF ולאחר מכן לשלוח אותו למדפסת. מה שלא הבנתי זה שאין לי תשובה לחלק חשוב בספר מודפס: תוכן העניינים.
ההרכבה של תוכן עניינים
בבסיסו, תוכן העניינים הוא פשוט למדי. כל שורה מייצגת חלק של ספר או דף אינטרנט ומציינת היכן אתה יכול למצוא את התוכן הזה. בדרך כלל, השורות מכילות שלושה חלקים:
- כותרת הפרק או הקטע
- מובילים (כלומר אותם נקודות, מקפים או קווים) המחברים חזותית את הכותרת למספר העמוד
- מספר העמוד
קל ליצור תוכן עניינים בתוך כלי עיבוד תמלילים כמו Microsoft Word או Google Docs, אבל מכיוון שהתוכן שלי היה ב-Markdown ולאחר מכן הומר ל-HTML, זו לא הייתה אפשרות טובה עבורי. רציתי משהו אוטומטי שיעבוד עם HTML כדי ליצור את תוכן העניינים בפורמט שמתאים להדפסה. רציתי גם שכל שורה תהיה קישור כך שניתן יהיה להשתמש בה בדפי אינטרנט ובקובצי PDF כדי לנווט ברחבי המסמך. רציתי גם מובילי נקודות בין הכותרת למספר העמוד.
וכך התחלתי לחקור.
נתקלתי בשני פוסטים מצוינים בבלוג על יצירת תוכן עניינים עם HTML ו-CSS. הראשון היה "בנה תוכן עניינים מה-HTML שלך" מאת ג'ולי בלאן. ג'ולי עבדה על PagedJS, polyfill עבור תכונות מדיה חסרות בדפדפני אינטרנט המעצב כראוי מסמכים להדפסה. התחלתי עם הדוגמה של ג'ולי, אבל גיליתי שזה לא ממש עבד בשבילי. לאחר מכן, מצאתי את Christoph Grabo's "קווים מנהיגים רספונסיביים של TOC עם CSS" פוסט, שהציג את הרעיון של שימוש ב-CSS Grid (בניגוד לגישה המבוססת על ציפה של ג'ולי) כדי להקל על היישור. שוב, עם זאת, הגישה שלו לא הייתה מתאימה בדיוק למטרות שלי.
עם זאת, לאחר שקראתי את שני הפוסטים הללו, הרגשתי שיש לי מספיק הבנה של בעיות הפריסה כדי להתחיל בעצמי. השתמשתי בקטעים משני הפוסטים בבלוג וכן הוספתי כמה מושגי HTML ו-CSS חדשים לגישה כדי להגיע לתוצאה שאני מרוצה ממנה.
בחירת הסימון הנכון
כשהחלטתי על הסימון הנכון עבור תוכן עניינים, חשבתי בעיקר על הסמנטיקה הנכונה. ביסודו, תוכן עניינים מתייחס לכותרת (פרק או תת-סעיף) הקשורה למספר עמוד, כמעט כמו צמד מפתח-ערך. זה הוביל אותי לשתי אפשרויות:
- אפשרות אחת היא להשתמש בטבלה (
<table>
) עם עמודה אחת לכותרת ועמודה אחת לדף. - ואז יש את רשימת ההגדרות לעתים קרובות שאינה בשימוש ונשכחת (
<dl>
) אלמנט. היא פועלת גם כמפת מפתח-ערך. אז, שוב, הקשר בין הכותרת למספר העמוד יהיה ברור.
כל אחת מהן נראתה כמו אפשרויות טובות עד שהבנתי שהן באמת עובדות רק עבור תוכן עניינים ברמה אחת, כלומר רק אם אני רוצה שיהיה לי תוכן עניינים עם שמות פרקים בלבד. אם רציתי להציג תת-סעיפים בתוכן העניינים, לא היו לי אפשרויות טובות. רכיבי טבלה אינם מצוינים עבור נתונים היררכיים, ולמרות שניתן לקנן טכנית רשימות הגדרות, הסמנטיקה נראתה לא נכונה. אז, חזרתי ללוח השרטוטים.
החלטתי להתבסס על הגישה של ג'ולי ולהשתמש ברשימה; עם זאת, בחרתי ברשימה מסודרת (<ol>
) במקום רשימה לא מסודרת (<ul>
). אני חושב שרשימה מסודרת מתאימה יותר במקרה הזה. תוכן עניינים מייצג רשימה של פרקים וכותרות משנה לפי סדר הופעתם בתוכן. הסדר חשוב ואסור ללכת לאיבוד בסימון.
לרוע המזל, שימוש ברשימה מסודרת פירושו איבוד הקשר הסמנטי בין הכותרת למספר העמוד, אז הצעד הבא שלי היה ליצור מחדש את הקשר הזה בתוך כל פריט ברשימה. הדרך הקלה ביותר לפתור זאת היא פשוט להכניס את המילה "עמוד" לפני מספר העמוד. כך, הקשר של המספר ביחס לטקסט ברור, גם ללא כל הבחנה ויזואלית אחרת.
להלן שלד HTML פשוט שיצר את הבסיס לסימון שלי:
<ol class="toc-list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title</span> <span class="page">Page 1</span> </a> <ol> <!-- subsection items --> </ol> </li>
</ol>
החלת סגנונות על תוכן העניינים
לאחר שקבעתי את הסימון שבו תכננתי להשתמש, השלב הבא היה ליישם כמה סגנונות.
ראשית, הסרתי את המספרים שנוצרו אוטומטית. אתה יכול לבחור להשאיר את המספרים שנוצרו אוטומטית בפרויקט שלך אם תרצה, אבל זה נפוץ שלספרים יש הקדמה והאחריות לא ממוספרות ברשימת הפרקים, מה שהופך את המספרים שנוצרו אוטומטית לא נכונים.
למטרה שלי, הייתי ממלא את מספרי הפרקים באופן ידני ואז משנה את הפריסה כך שלרשימה ברמה העליונה לא תהיה ריפוד (ובכך מיישר אותה עם פסקאות) וכל רשימה מוטבעת מוזזת בשני רווחים. בחרתי להשתמש ב- a 2ch
ערך ריפוד כי עדיין לא הייתי בטוח באיזה גופן אשתמש. ה ch
יחידת אורך מאפשרת לריפוד להיות יחסית לרוחב של תו - לא משנה באיזה גופן משתמשים - במקום לגודל פיקסל מוחלט שעלול להיראות לא עקבי.
הנה ה-CSS שהגעתי אליו:
.toc-list, .toc-list ol { list-style-type: none;
} .toc-list { padding: 0;
} .toc-list ol { padding-inline-start: 2ch;
}
שרה סויידאן ציין בפניי שדפדפני WebKit מסירים סמנטיקה של רשימה כאשר list-style-type
is none
אז הייתי צריך להוסיף role="list"
לתוך ה-HTML כדי לשמר אותו:
<ol class="toc-list" role="list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title</span> <span class="page">Page 1</span> </a> <ol role="list"> <!-- subsection items --> </ol> </li>
</ol>
עיצוב הכותרת ומספר העמוד
כשהרשימה מעוצבת לטעמי, הגיע הזמן לעבור לעיצוב פריט רשימה בודד. עבור כל פריט בתוכן העניינים, הכותרת ומספר העמוד חייבים להיות באותה שורה, כאשר הכותרת משמאל ומספר העמוד מיושרת לימין.
אולי אתה חושב, "אין בעיה, בשביל זה יש flexbox!" אתה לא טועה! Flexbox אכן יכול להשיג את היישור הנכון של עמוד השער. אבל יש כמה בעיות יישור מסובכות כאשר המנהיגים מתווספים, אז בחרתי במקום זאת ללכת עם הגישה של כריסטוף באמצעות רשת, שכבונוס היא גם עוזרת עם כותרות מרובות שורות. הנה ה-CSS עבור פריט בודד:
.toc-list li > a { text-decoration: none; display: grid; grid-template-columns: auto max-content; align-items: end;
} .toc-list li > a > .page { text-align: right;
}
לרשת יש שתי עמודות, הראשונה שבהן היא auto
-בגודל כדי למלא את כל רוחב המיכל, מינוס העמודה השנייה, שגודלה הוא max-content
. מספר העמוד מיושר לימין, כפי שמקובל בתוכן העניינים.
השינוי הנוסף היחיד שעשיתי בשלב זה היה הסתרת הטקסט "דף". זה מועיל לקוראי מסך אבל מיותר מבחינה ויזואלית, אז השתמשתי ב-a מסורתי visually-hidden
בכיתה כדי להסתיר את זה מהעין:
.visually-hidden { clip: rect(0 0 0 0); clip-path: inset(100%); height: 1px; overflow: hidden; position: absolute; width: 1px; white-space: nowrap;
}
וכמובן, יש לעדכן את ה-HTML כדי להשתמש במחלקה הזו:
<ol class="toc-list" role="list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title</span> <span class="page"><span class="visually-hidden">Page</span> 1</span> </a> <ol role="list"> <!-- subsection items --> </ol> </li>
</ol>
כשהבסיס הזה קיים, עברתי להתייחס למובילים בין הכותרת לדף.
יצירת מובילי נקודות
מנהיגים כל כך נפוצים במדיה המודפסת שאולי אתה תוהה, למה CSS כבר לא תומך בזה? התשובה היא: זה עושה. ובכן, סוג של.
יש למעשה א leader()
פונקציה המוגדרת ב תוכן שנוצר ב-CSS עבור מפרט מדיה דפדפת. עם זאת, כמו בחלק גדול ממפרטי המדיה המדפים, פונקציה זו אינה מיושמת באף דפדפן, ולכן אינה כוללת אותה כאופציה (לפחות בזמן שאני כותב זאת). זה אפילו לא רשום ב caniuse.com, ככל הנראה כי אף אחד לא יישם את זה ואין תוכניות או איתותים שיעשו זאת.
למרבה המזל, גם ג'ולי וגם כריסטוף כבר התייחסו לבעיה הזו בפוסטים שלהם. כדי להכניס את מובילי הנקודות, שניהם השתמשו ב-a ::after
פסאודו-אלמנט עם שלו content
מאפיין מוגדר למחרוזת ארוכה מאוד של נקודות, כך:
.toc-list li > a > .title { position: relative; overflow: hidden;
} .toc-list li > a .title::after { position: absolute; padding-left: .25ch; content: " . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . "; text-align: right;
}
השמיים ::after
pseudo-element מוגדר למיקום מוחלט כדי להוציא אותו מזרימת העמוד ולהימנע מגליפה לשורות אחרות. הטקסט מיושר לימין מכיוון שאנו רוצים שהנקודות האחרונות של כל שורה יהיו צמודות למספר שבסוף השורה. (עוד על המורכבות של זה מאוחר יותר.) .title
אלמנט מוגדר למיקום יחסי כך שה ::after
פסאודו-אלמנט אינו פורץ מהקופסה שלו. בינתיים, ה overflow
מוסתר כך שכל הנקודות הנוספות האלה בלתי נראות. התוצאה היא תוכן עניינים יפה עם מובילי נקודות.
עם זאת, יש עוד משהו שצריך לקחת בחשבון.
שרה גם ציינה בפניי שכל הנקודות הללו נחשבות כטקסט לקוראי מסך. אז מה אתה שומע? "הקדמה נקודה נקודה נקודה נקודה..." עד שכל הנקודות יוכרזו. זו חוויה איומה עבור משתמשי קוראי מסך.
הפתרון הוא להכניס אלמנט נוסף עם aria-hidden
מכוון ל true
ולאחר מכן השתמש ברכיב זה כדי להכניס את הנקודות. אז ה-HTML הופך:
<ol class="toc-list" role="list"> <li> <a href="#link_to_heading"> <span class="title">Chapter or subsection title<span class="leaders" aria-hidden="true"></span></span> <span class="page"><span class="visually-hidden">Page</span> 1</span> </a> <ol role="list"> <!-- subsection items --> </ol> </li>
</ol>
וה-CSS הופך:
.toc-list li > a > .title { position: relative; overflow: hidden;
} .toc-list li > a .leaders::after { position: absolute; padding-left: .25ch; content: " . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . " ". . . . . . . . . . . . . . . . . . . . . . . "; text-align: right;
}
כעת קוראי מסך יתעלמו מהנקודות ויחסכו מהמשתמשים את התסכול של האזנה למספר נקודות המוכרזות.
נגיעות גימור
בשלב זה, רכיב תוכן העניינים נראה די טוב, אבל הוא יכול לצרוך קצת עבודת פרטים קטנים. בתור התחלה, רוב הספרים קיזזו חזותית את כותרות הפרקים מכותרות הסעיפים, אז הפכתי את הפריטים ברמה העליונה למודגשים והכנסתי שוליים להפרדה בין קטעי משנה מהפרקים שאחריו:
.toc-list > li > a { font-weight: bold; margin-block-start: 1em;
}
לאחר מכן, רציתי לנקות את היישור של מספרי העמודים. הכל נראה בסדר כאשר השתמשתי בגופן ברוחב קבוע, אבל עבור גופנים ברוחב משתנה, נקודות המובילות עלולות בסופו של דבר ליצור תבנית זיגזג כשהן מתכווננות לרוחב של מספר עמוד. לדוגמה, כל מספר עמוד עם 1 יהיה צר יותר מאחרים, וכתוצאה מכך נקודות מובילות שאינן מיושרות עם הנקודות בשורות הקודמות או הבאות.
כדי לתקן את הבעיה הזו, הגדרתי font-variant-numeric
ל tabular-nums
כך שכל המספרים מטופלים באותו רוחב. על ידי הגדרת הרוחב המינימלי ל 2ch
, וידאתי שכל המספרים בעלי ספרה אחת או שתיים מיושרים בצורה מושלמת. (ייתכן שתרצה להגדיר זאת ל 3ch
אם לפרויקט שלך יש יותר מ-100 עמודים.) הנה ה-CSS הסופי עבור מספר העמוד:
.toc-list li > a > .page { min-width: 2ch; font-variant-numeric: tabular-nums; text-align: right;
}
ובכך, תוכן העניינים הושלם!
סיכום
יצירת תוכן עניינים עם HTML ו-CSS היה יותר אתגר ממה שציפיתי, אבל אני מאוד מרוצה מהתוצאה. לא רק שגישה זו גמישה מספיק כדי להכיל פרקים ותתי-סעיפים, אלא שהיא מטפלת יפה בתתי-סעיפים מבלי לעדכן את ה-CSS. הגישה הכוללת פועלת על דפי אינטרנט שבהם אתה רוצה לקשר למיקומי התוכן השונים, כמו גם קובצי PDF שבהם אתה רוצה שתוכן העניינים יקשר לדפים שונים. וכמובן, זה גם נראה נהדר בהדפסה אם אי פעם נוטה להשתמש בו בחוברת או בספר.
אני רוצה להודות לג'ולי בלאן וכריסטוף גרבו על הפוסטים המצוינים שלהם בבלוג על יצירת תוכן עניינים, מכיוון ששניהם היו חשובים לאין ערוך כשהתחלתי. אני גם רוצה להודות לשרה סויידן על משוב הנגישות שלה בזמן שעבדתי על הפרויקט הזה.
תוכן עניינים מושלם עם HTML + CSS פורסם במקור ב CSS-טריקים. אתה צריך לקבל את הניוזלטר.
- "
- 100
- a
- אודות
- מוּחלָט
- נגישות
- להתאים
- להשיג
- לרוחב
- הוסיף
- נוסף
- כתובת
- תעשיות
- מאפשר
- כְּבָר
- הודיע
- לענות
- החל
- גישה
- מתאים
- סביב
- המכונית
- אוטומטי
- בסיס
- כי
- לפני
- החל
- להיות
- בֵּין
- בלוג
- בלוג הודעות
- לוּחַ
- סיכה
- מַעֲנָק
- ספרים
- אריזה מקורית
- לִבנוֹת
- מקרה
- לאתגר
- שינוי
- הפרק
- בחרו
- בכיתה
- טור
- איך
- Common
- מורכבות
- רְכִיב
- מושג
- לְחַבֵּר
- התחשבות
- מכולה
- תוכן
- תוכן
- ליבה
- יכול
- יוצרים
- החליט
- פרט
- אחר
- ספרות
- לְהַצִיג
- מסמכים
- ציור
- כל אחד
- אלמנטים
- לצאת לדרך
- מוטבע
- נוסד
- הכל
- דוגמה
- מצוין
- לְמַעֵט
- תרגיל
- צפוי
- ניסיון
- תכונות
- מָשׁוֹב
- ראשון
- לסדר
- גמיש
- תזרים
- הבא
- פוּרמָט
- מצא
- קרן
- החל מ-
- פונקציה
- ביסודו
- ליצור
- מקבל
- טוב
- גדול
- רֶשֶׁת
- שמח
- גובה
- מועיל
- עוזר
- כאן
- הסתר
- אולם
- HTTPS
- יושם
- חשוב
- כלול
- בנפרד
- למשל
- מטרה
- בעיות
- IT
- JavaScript
- שמור
- מנהיג
- מנהיגים
- הוביל
- קו
- קווים
- קשר
- רשימה
- ברשימה
- האזנה
- רשימות
- מקומות
- ארוך
- נראה
- הסתכלות
- עשוי
- לעשות
- עושה
- איפור
- באופן ידני
- מַפָּה
- דבר
- עניינים
- אומר
- מדיה
- מיקרוסופט
- יכול
- מינימום
- יותר
- רוב
- המהלך
- מספר
- כלומר
- שמות
- נווט
- צרכי
- מספר
- מספרים
- ברור
- לקזז
- בסדר
- אפשרות
- אפשרויות
- להזמין
- אחר
- מקיף
- שֶׁלוֹ
- חלק
- תבנית
- אֲנָשִׁים
- חתיכות
- מתוכנן
- תוכניות
- נקודה
- עמדה
- הודעות
- יפה
- קודם
- בעיה
- תהליך
- פּרוֹיֶקט
- רכוש
- מטרה
- למטרות
- RE
- קורא
- הקוראים
- קריאה
- להבין
- הבין
- קשר
- מייצג
- וכתוצאה מכך
- אותו
- מסך
- עצמית לפרסם
- סמנטיקה
- סט
- הצבה
- פָּשׁוּט
- מידה
- So
- פִּתָרוֹן
- לפתור
- כמה
- משהו
- רווחים
- מפרטים
- התחלה
- החל
- עוד
- תמיכה
- השמיים
- לכן
- חושב
- שְׁלוֹשָׁה
- קָשׁוּר
- זמן
- כותרת
- כלים
- הרמה העליונה
- מסורתי
- טרנספורמציה
- בדרך כלל
- הבנה
- עדכון
- להשתמש
- משתמשים
- ערך
- שונים
- גרסה
- לצפיה
- W3
- רציתי
- אינטרנט
- דפדפני אינטרנט
- מה
- בזמן
- רוח
- בתוך
- לְלֹא
- תיק עבודות
- עבד
- עובד
- היה
- כתיבה
- שנה