נפתרה עם :has(): מרווח אנכי בטקסט ארוך

נפתרה עם :has(): מרווח אנכי בטקסט ארוך

אם אי פעם עבדת על אתרים עם הרבה טקסט ארוך - במיוחד אתרי CMS שבהם אנשים יכולים להזין קטעי טקסט בעורך WYSIWYG - סביר להניח שהיית צריך לכתוב CSS כדי לנהל את המרווח האנכי בין אלמנטים טיפוגרפיים שונים, כמו כותרות, פסקאות, רשימות וכן הלאה.

זה מסובך באופן מפתיע לעשות את זה נכון. וזו אחת הסיבות לכך שדברים כמו התוסף Tailwind Typography ו-Stack Overflow's Prose קיימים - אם כי אלה מטפלים בהרבה יותר מסתם מרווח אנכי.

פיירפוקס תומך :has() מאחורי ה layout.css.has-selector.enabled דגל in about:config בזמן הכתיבה.

מה הופך את המרווח האנכי הטיפוגרפי למסובך?

אין ספק שזה צריך להיות פשוט כמו לומר שכל אלמנט - p, h2, ul, וכו' - יש כמות מסוימת של שוליים עליונים ו/או תחתונים... נכון? למרבה הצער, זה לא המקרה. שקול את ההתנהגות הרצויה הזו:

  • הרכיבים הראשונים והאחרונים בבלוק של טקסט ארוך לא צריכים לכלול רווח נוסף מעל או מתחת (בהתאמה). זאת כדי שאלמנטים אחרים שאינם טיפוגרפיים עדיין ממוקמים באופן צפוי סביב התוכן הארוך.
  • לקטעים בתוך התוכן הארוך צריך להיות מרווח גדול ויפה ביניהם. "קטע" הוא כותרת וכל התכנים הבאים השייכים לאותה כותרת. בפועל, זה אומר שיש מקום גדול ויפה לפני כותרת... אבל לֹא אם קודמת לכותרת זו מיד כותרת אחרת!
דוגמה לכותרת 3 בעקבות פסקה ועוד אחת בעקבות כותרת 2.
אנו רוצים להרחיב מקום מעל לכותרת 3 כאשר הוא עוקב אחר אלמנט טיפוגרפי, כמו פסקה, אך פחות רווח כאשר הוא עוקב מיד אחרי כותרת אחרת.

אתה לא צריך לחפש יותר מאשר כאן ב-CSS-Tricks כדי לראות איפה זה יכול להועיל. הנה כמה צילומי מסך של מרווחים שהוצאתי ממאמר אחר.

רכיב כותרת 2 ישירות מעל כותרת 3.
המרווח האנכי בין כותרת 2 לכותרת 3
רכיב Heading 3 ישירות אחרי רכיב פסקה.
הרווח האנכי בין כותרת 3 לפיסקה

הפתרון המסורתי

הפתרון הטיפוסי שראיתי כרוך בהכנסת כל תוכן בעל צורה ארוכת עטיפה div (או תג סמנטי, אם מתאים). השם שלי ללכת לכיתה היה .rich-text, שלדעתי אני משתמש בו כהנגאובר מגרסאות ישנות יותר של Wagtail CMS, שיוסיף את המחלקה הזו באופן אוטומטי בעת רינדור תוכן WYSIWYG. טיפוגרפיה של רוח גב משתמש .prose בכיתה (בתוספת כמה מחלקות משנה).

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

הפתרון המסורתי נשמע הגיוני... מה הבעיה? אני חושב שיש כמה…

מבנה קשיח

צריך להוסיף שיעור עטיפה כמו .rich-text בכל המקומות הנכונים פירושו אפייה במבנה ספציפי לקוד ה-HTML שלך. זה הכרחי לפעמים, אבל זה מרגיש כאילו זה לא צריך להיות במקרה הספציפי הזה. זה גם יכול להיות קל לשכוח לעשות זאת בכל מקום שאתה צריך, במיוחד אם אתה צריך להשתמש בו עבור שילוב של CMS ותוכן מקודד קשה.

מבנה ה-HTML נעשה קשיח עוד יותר כאשר אתה רוצה להיות מסוגל לקצץ את השוליים העליונים והתחתונים מהרכיב הראשון והאחרון, בהתאמה, מכיוון שהם צריכים להיות ילדים מיידיים של רכיב העטיפה, למשל, .rich-text > *:first-child. זה > חשוב - אחרי הכל, אנחנו לא רוצים לבחור בטעות את פריט הרשימה הראשון בכל אחד מהם ul or ol עם הבורר הזה.

ערבוב מאפייני שוליים

בטרום:has() בעולם, לא הייתה לנו דרך לבחור אלמנט על סמך מה שאחריו. לכן, הגישה המסורתית למרווח בין אלמנטים טיפוגרפיים כרוכה בשימוש בשילוב של שניהם margin-top ו margin-bottom:

  1. אנו מתחילים בהגדרת מרווח ברירת המחדל שלנו לאלמנטים עם margin-bottom.
  2. לאחר מכן, אנו מרווחים את "הקטעים" שלנו באמצעות margin-top - כלומר שטח גדול מאוד מעל כל כותרת
  3. ואז אנחנו עוקפים את הגדולים האלה margin-tops כאשר אחרי כותרת מיד אחריה כותרת נוספת באמצעות בורר האחים הסמוך (למשל h2 + h3).

עכשיו, אני לא יודע מה איתכם, אבל תמיד הרגשתי שעדיף להשתמש בכיוון שוליים בודדים כשמפרידים בין דברים, בדרך כלל בעד margin-bottom (זה בהנחה ש CSS gap רכוש אינו בר ביצוע, מה שלא במקרה זה). אם זה עניין גדול, או אפילו נכון, אני אתן לך להחליט. אבל באופן אישי, אני מעדיף להגדיר margin-bottom למרווח תוכן ארוך.

שוליים מתכווצים

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

שוליים מתמוטטים הם עוד דבר שצריך להיות מודע אליו. זה עשוי להיות מבלבל עבור מפתחים זוטרים שאינם מעודכנים במוזרות ה-CSS הזו. המרווח ישתנה לחלוטין (כלומר יפסיק להתמוטט) אם היית משנה את העטיפה ל-a flex פריסה עם flex-direction: column למשל, וזה משהו שלא יקרה אם תגדיר את השוליים האנכיים שלך בכיוון אחד.

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

השמיים :has() פִּתָרוֹן

והנה הניסיון שלי לפתור את הבעיות האלה עם :has().

כדי לסכם את השיפורים זה נועד לעשות:

  • אין צורך בשיעור עטיפה.
  • אנחנו עובדים עם א כיוון שוליים עקבי.
  • נמנעים מקריסת שוליים (מה שעשוי להיות שיפור או לא, תלוי בעמדתך).
  • אין להגדיר סגנונות ואז לעקוף אותם מיד.

הערות ואזהרות על :has() פִּתָרוֹן

  • בדוק תמיד את תמיכת הדפדפן. בזמן הכתיבה, פיירפוקס תומך רק :has() מאחורי דגל ניסיוני.
  • הפתרון שלי לא כולל את כל האלמנטים הטיפוגרפיים האפשריים. למשל, אין <blockquote> בהדגמה שלי. עם זאת, קל מספיק להרחיב את רשימת הבוררים.
  • הפתרון שלי גם לא מטפל באלמנטים לא טיפוגרפיים שעשויים להופיע בבלוק הטקסט הארוך המסוים שלך, למשל <img>. הסיבה לכך היא שעבור האתרים שאני עובד עליהם, אנו נוטים לנעול את ה-WYSIWYG ככל האפשר לצמתי טקסט הליבה, כמו כותרות, פסקאות ורשימות. כל דבר אחר - למשל מרכאות, תמונות, טבלאות וכו' - הוא בלוק רכיבי CMS נפרד, והבלוקים עצמם מרוחקים זה מזה כאשר הם מוצגים בדף. אבל שוב, ניתן להרחיב את רשימת הבוררים.
  • כללתי רק h1 למען השלמות. בדרך כלל לא הייתי מאפשר למשתמש CMS להוסיף h1 באמצעות WYSIWYG, מכיוון שכותרת העמוד תאפוף בתבנית העמוד במקום כלשהו במקום מוזנת בעורך עמודי ה-CMS.
  • אני לא מתייחס לכותרת שמיד אחריה אותה כותרת ברמה (h2 + h2). זה אומר שהכותרת הראשונה לא תהיה "בעלת" שום תוכן, מה שנראה כמו שימוש לרעה בכותרות (ותקנו אותי אם אני טועה, אבל זה יכול להפר WCAG 1.3.1 מידע ומערכות יחסים). אני גם לא מתייחס לרמות שדילגו על הכותרות, שאינן חוקיות.
  • אני לא דופק בשום אופן את הגישות הקיימות שהזכרתי. אם וכאשר אבנה עוד אתר Tailwind אשתמש בתוסף המצוין Typography, אין שאלה!
  • אני לא מעצב. המצאתי את ערכי המרווחים האלה על ידי גלגל עיניים. אתה כנראה יכול (וצריך) להשתמש בערכים טובים יותר.

ספציפיות ומבנה הפרויקט

התכוונתי לכתוב כאן דבר גדול על איך השיטה המסורתית והחדשה :has() דרך לעשות את זה עשויה להשתלב ב ITCSS מתודולוגיה... אבל עכשיו כשיש לנו :where() (בורר האפס-ספציפיות) אתה יכול כמעט לבחור את רמת הספציפיות המועדפת עליך עבור כל בורר כעת.

עם זאת, העובדה שכבר אין לנו עסק עם עטיפה - .prose, .rich-text, וכו' - לי זה מרגיש כאילו זה צריך לחיות בשכבת ה"אלמנטים", כלומר לפני שמתחילים להתמודד עם ספציפיות ברמת הכיתה. השתמשתי :where() בדוגמאות שלי כדי לשמור על עקביות ספציפיות. לכל הבוררים בשתי הדוגמאות שלי יש א ציון ספציפיות of 0,0,1 (פרט לאיפוס העצמות החשופות).

גלישה את

אז הנה, פתרון מדמם לבעיה משעממת מאוד! הגישה החדשה יותר הזו היא עדיין לא מה שהייתי מכנה CSS "פשוט" - כפי שאמרתי בהתחלה, זה נושא מורכב יותר ממה שזה נראה בהתחלה. אבל חוץ מכמה בוררים מעט מורכבים, אני חושב שהגישה החדשה הגיונית יותר בסך הכל, ומבנה ה-HTML הפחות נוקשה נראה מאוד מושך.

אם בסופו של דבר אתה משתמש בזה, או משהו דומה לזה, אשמח לדעת איך זה מסתדר לך. ואם אתם יכולים לחשוב על דרכים לשפר אותו, אשמח לשמוע גם על אלו!

בול זמן:

עוד מ טריקים של CSS