جدول محتويات مثالي مع ذكاء بيانات HTML + CSS PlatoBlockchain. البحث العمودي. منظمة العفو الدولية.

جدول محتويات مثالي مع HTML + CSS

في وقت سابق من هذا العام ، نشرت بنفسي كتابًا إلكترونيًا بعنوان فهم وعود JavaScript (مجاني للتحميل). على الرغم من أنه لم يكن لدي أي نية لتحويله إلى كتاب مطبوع ، فقد تواصل عدد كافٍ من الأشخاص للاستفسار عن نسخة مطبوعة قررت نشرها بنفسي أيضًا. اعتقدت أنه سيكون تمرينًا سهلاً باستخدام HTML و CSS قم بإنشاء ملف PDF ثم أرسله إلى الطابعة. ما لم أدركه هو أنه لم يكن لدي إجابة لجزء مهم من الكتاب المطبوع: جدول المحتويات.

تكوين جدول المحتويات

في جوهره ، جدول المحتويات بسيط إلى حد ما. يمثل كل سطر جزءًا من كتاب أو صفحة ويب ويشير إلى المكان الذي يمكنك العثور فيه على هذا المحتوى. عادةً ما تحتوي الخطوط على ثلاثة أجزاء:

  1. عنوان الفصل أو القسم
  2. القادة (أي تلك النقاط أو الشرطات أو الخطوط) التي تربط العنوان مرئيًا برقم الصفحة
  3. رقم الصفحة

من السهل إنشاء جدول محتويات داخل أدوات معالجة الكلمات مثل Microsoft Word أو محرّر مستندات Google ، ولكن نظرًا لأن المحتوى الخاص بي كان في Markdown ثم تحول إلى HTML ، لم يكن هذا خيارًا جيدًا بالنسبة لي. أردت شيئًا آليًا يعمل مع HTML لإنشاء جدول المحتويات بتنسيق مناسب للطباعة. أردت أيضًا أن يكون كل سطر رابطًا حتى يمكن استخدامه في صفحات الويب وملفات PDF للتنقل حول المستند. أردت أيضًا وجود رموز نقطية بين العنوان ورقم الصفحة.

وهكذا بدأت في البحث.

صادفت منشورتين ممتازتين في المدونة حول إنشاء جدول محتويات باستخدام HTML و CSS. الأول كان "أنشئ جدول محتويات من HTML الخاص بك" بواسطة جولي بلانك. عملت جولي عليها بيجد، وهو polyfill لميزات الوسائط المقسمة المفقودة في متصفحات الويب التي تعمل على تنسيق المستندات بشكل صحيح للطباعة. لقد بدأت بمثال جولي ، لكنني اكتشفت أنه لم ينجح معي تمامًا. بعد ذلك ، وجدت كريستوف جرابو "خطوط قائد TOC سريعة الاستجابة مع CSS" post ، الذي قدم مفهوم استخدام CSS Grid (على عكس نهج Julie القائم على التعويم) لتسهيل المحاذاة. مرة أخرى ، على الرغم من ذلك ، لم يكن أسلوبه مناسبًا تمامًا لأغراضي.

بعد قراءة هذين المنشورين ، شعرت أن لدي فهمًا جيدًا بما يكفي لقضايا التخطيط للشروع في العمل بمفردي. لقد استخدمت أجزاء من منشورات المدونة بالإضافة إلى إضافة بعض مفاهيم 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>

تطبيق الأنماط على جدول المحتويات

بمجرد إنشاء العلامات التي خططت لاستخدامها ، كانت الخطوة التالية هي تطبيق بعض الأنماط.

أولاً ، قمت بإزالة الأرقام التي تم إنشاؤها تلقائيًا. يمكنك اختيار الاحتفاظ بالأرقام المُنشأة تلقائيًا في مشروعك إذا كنت ترغب في ذلك ، ولكن من الشائع أن تحتوي الكتب على كلمات تمهيدية وكلمات لاحقة غير مرقمة مدرجة في قائمة الفصول ، مما يجعل الأرقام المُنشأة تلقائيًا غير صحيحة.

من أجل هدفي ، أود ملء أرقام الفصول يدويًا ثم ضبط التخطيط بحيث لا تحتوي قائمة المستوى الأعلى على أي حشوة (وبالتالي مواءمتها مع الفقرات) ويتم وضع مسافة بادئة لكل قائمة مضمنة بمسافتين. اخترت استخدام ملف 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>
تضمين CodePen الاحتياطية

تصميم العنوان ورقم الصفحة

مع تصميم القائمة حسب رغبتي ، فقد حان الوقت للانتقال إلى تصميم عنصر قائمة فردي. لكل عنصر في جدول المحتويات ، يجب أن يكون العنوان ورقم الصفحة على نفس السطر ، مع محاذاة العنوان إلى اليسار ورقم الصفحة إلى اليمين.

قد تفكر ، "لا مشكلة ، هذا هو الغرض من 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. يتم محاذاة رقم الصفحة إلى اليمين ، كما هو معتاد في جدول المحتويات.

كان التغيير الآخر الوحيد الذي أجريته في هذه المرحلة هو إخفاء نص "الصفحة". هذا مفيد لقارئات الشاشة ولكنه غير ضروري بصريًا ، لذلك استخدمت ملف تقليدي 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>

مع وجود هذا الأساس ، انتقلت إلى مخاطبة القادة بين العنوان والصفحة.

تضمين CodePen الاحتياطية

تكوين قادة النقطة

القادة شائعون جدًا في وسائل الإعلام المطبوعة لدرجة أنك قد تتساءل ، لماذا لا تدعم CSS ذلك بالفعل؟ الجواب هو: نعم هو كذلك. كذلك نوع من.

في الواقع هناك leader() وظيفة محددة في محتوى CSS الذي تم إنشاؤه لمواصفات الوسائط المقسمة إلى صفحات. ومع ذلك ، كما هو الحال مع الكثير من مواصفات الوسائط المقسمة إلى صفحات ، لا يتم تنفيذ هذه الوظيفة في أي متصفحات ، وبالتالي يتم استبعادها كخيار (على الأقل في الوقت الذي أكتب فيه هذا). إنه غير مدرج حتى في caniuse.comربما لأنه لم ينفذها أحد ولا توجد خطط أو إشارات تدل على أنها ستنفذها.

لحسن الحظ ، عالج كل من جولي وكريستوف هذه المشكلة بالفعل في منشورات كل منهما. لإدراج قادة النقاط ، استخدم كلاهما ملف ::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 يتم تعيين العنصر الزائف على الموضع المطلق لإزالته من تدفق الصفحة وتجنب الالتفاف على سطور أخرى. تتم محاذاة النص إلى اليمين لأننا نريد أن تتدفق النقاط الأخيرة من كل سطر مع الرقم الموجود في نهاية السطر. (المزيد عن تعقيدات هذا لاحقًا) .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;
}

الآن ستتجاهل برامج قراءة الشاشة النقاط وتجنيب المستخدمين الإحباط من الاستماع إلى النقاط المتعددة التي يتم الإعلان عنها.

تضمين CodePen الاحتياطية

اللمسات الأخيرة

في هذه المرحلة ، يبدو عنصر جدول المحتويات جيدًا ، ولكن قد يستخدم بعض الأعمال التفصيلية البسيطة. للبدء ، تقوم معظم الكتب بإزاحة عناوين الفصول بصريًا من عناوين الأقسام الفرعية ، لذلك جعلت عناصر المستوى الأعلى بالخط العريض وقدمت هامشًا لفصل الأقسام الفرعية عن الفصول التالية:

.toc-list > li > a { font-weight: bold; margin-block-start: 1em;
}

بعد ذلك ، أردت تنظيف محاذاة أرقام الصفحات. بدا كل شيء على ما يرام عندما كنت أستخدم خطًا بعرض ثابت ، ولكن بالنسبة للخطوط ذات العرض المتغير ، يمكن أن ينتهي الأمر بالنقاط الرئيسية بتشكيل نمط متعرج أثناء ضبطها على عرض رقم الصفحة. على سبيل المثال ، أي رقم صفحة يحتوي على 1 سيكون أضيق من غيره ، مما يؤدي إلى عدم محاذاة النقاط البادئة مع النقاط الموجودة في الأسطر السابقة أو التالية.

أرقام ونقاط غير محاذية في جدول المحتويات.
جدول محتويات مثالي مع HTML + CSS

لإصلاح هذه المشكلة ، قمت بتعيين 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

وبذلك يكون جدول المحتويات كاملاً!

تضمين CodePen الاحتياطية

وفي الختام

كان إنشاء جدول محتويات لا يحتوي على أي شيء سوى HTML و CSS بمثابة تحدٍ أكبر مما توقعت ، لكنني سعيد جدًا بالنتيجة. هذا النهج ليس فقط مرنًا بما يكفي لاستيعاب الفصول والأقسام الفرعية ، ولكنه يعالج الأقسام الفرعية بشكل جيد دون تحديث CSS. يعمل النهج العام على صفحات الويب حيث تريد الارتباط بمواقع المحتوى المختلفة ، بالإضافة إلى ملفات PDF حيث تريد ربط جدول المحتويات بصفحات مختلفة. وبالطبع ، تبدو رائعة أيضًا في الطباعة إذا كنت تميل إلى استخدامها في كتيب أو كتاب.

أود أن أشكر جولي بلان وكريستوف جرابو على منشوراتهما الممتازة في المدونة حول إنشاء جدول محتويات ، حيث كان كلاهما لا يقدر بثمن عندما كنت أبدأ. أود أيضًا أن أشكر سارة سويدان على تعليقاتها المتعلقة بإمكانية الوصول أثناء عملي في هذا المشروع.


جدول محتويات مثالي مع HTML + CSS نشرت أصلا في حيل CSS. يجب احصل على النشرة الإخبارية.

الطابع الزمني:

اكثر من الخدع المغلق