فهرست کامل مطالب با HTML + CSS PlatoBlockchain Intelligence Data. جستجوی عمودی Ai.

یک فهرست کامل از مطالب با HTML + CSS

اوایل امسال، کتاب الکترونیکی را خودم منتشر کردم به نام درک وعده های جاوا اسکریپت (رایگان برای دانلود). حتی با وجود اینکه قصد نداشتم آن را به یک کتاب چاپی تبدیل کنم، افراد زیادی برای پرس و جو در مورد یک نسخه چاپی تماس گرفتند که تصمیم گرفتم آن را نیز خودم منتشر کنم. فکر می‌کردم این یک تمرین آسان با استفاده از HTML و CSS است. یک PDF ایجاد کنید و سپس آن را به چاپگر ارسال کنید. چیزی که من متوجه نشدم این بود که برای بخش مهمی از یک کتاب چاپی پاسخی نداشتم: فهرست مطالب.

آرایش فهرست مطالب

در هسته خود، فهرست مطالب نسبتاً ساده است. هر خط نشان دهنده بخشی از یک کتاب یا صفحه وب است و نشان می دهد که کجا می توانید آن محتوا را پیدا کنید. به طور معمول، خطوط شامل سه بخش است:

  1. عنوان فصل یا بخش
  2. لیدرها (یعنی آن نقاط، خط تیره یا خطوط) که به صورت بصری عنوان را به شماره صفحه متصل می کنند
  3. شماره صفحه

ایجاد فهرست مطالب در ابزارهای پردازش کلمه مانند Microsoft Word یا Google Docs آسان است، اما چون محتوای من در Markdown بود و سپس به HTML تبدیل شد، این گزینه برای من مناسب نبود. من چیزی خودکار می‌خواستم که با HTML کار کند تا فهرست مطالب را در قالبی تولید کند که برای چاپ مناسب باشد. من همچنین می‌خواستم هر خط یک پیوند باشد تا بتوان از آن در صفحات وب و PDF برای پیمایش در اطراف سند استفاده کرد. من همچنین می‌خواستم بین عنوان و شماره صفحه، نقطه‌ای وجود داشته باشد.

و بنابراین شروع به تحقیق کردم.

من با دو پست وبلاگ عالی در ایجاد فهرست مطالب با HTML و CSS مواجه شدم. اولی بود “از HTML خود یک فهرست مطالب بسازید” توسط جولی بلان جولی روی آن کار کرد PagedJS، یک پلی پر برای ویژگی های رسانه صفحه شده از دست رفته در مرورگرهای وب که به درستی اسناد را برای چاپ قالب بندی می کند. من با مثال جولی شروع کردم، اما متوجه شدم که برای من کار نمی کند. بعد، کریستف گرابو را پیدا کردم "خطوط رهبر 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 مقدار padding زیرا من هنوز کاملاً مطمئن نبودم که از کدام فونت استفاده کنم. را 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 Embed Fallback

شکل دادن به عنوان و شماره صفحه

با طراحی لیست به دلخواه من، زمان آن فرا رسیده بود که به طراحی یک آیتم فهرست فردی بپردازیم. برای هر مورد در فهرست مطالب، عنوان و شماره صفحه باید در یک خط قرار گیرند و عنوان در سمت چپ و شماره صفحه در سمت راست تراز شود.

ممکن است فکر کنید، "مشکلی نیست، فلکس باکس برای همین است!" شما اشتباه نمی کنید! 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-sized برای پر کردن تمام عرض ظرف، منهای ستون دوم، که به اندازه است 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>

با این پایه و اساس، من به خطاب به رهبران بین عنوان و صفحه پرداختم.

CodePen Embed Fallback

ایجاد رهبران نقطه

رهبران در رسانه های چاپی آنقدر رایج هستند که ممکن است تعجب کنید، چرا 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;
}

La ::after شبه عنصر روی یک موقعیت مطلق تنظیم شده است تا آن را از جریان صفحه خارج کند و از پیچیدن به خطوط دیگر جلوگیری کند. متن در سمت راست تراز شده است زیرا می خواهیم آخرین نقاط هر خط با عدد انتهای خط همسطح باشد. (بیشتر در مورد پیچیدگی های این بعدا.) The .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 Embed Fallback

لمس های نهایی

در این مرحله، جزء فهرست مطالب بسیار خوب به نظر می رسد، اما می تواند از جزئیات جزئی استفاده کند. برای شروع، بیشتر کتاب‌ها عناوین فصل‌ها را از نظر بصری با عنوان‌های فرعی جدا می‌کنند، بنابراین موارد سطح بالا را پررنگ کردم و حاشیه‌ای برای جدا کردن بخش‌های فرعی از فصل‌های بعدی ایجاد کردم:

.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 Embed Fallback

نتیجه

ایجاد فهرست مطالب با هیچ چیز جز HTML و CSS چالشی بیش از آنچه انتظار داشتم بود، اما از نتیجه بسیار راضی هستم. این رویکرد نه تنها به اندازه کافی انعطاف‌پذیر است که فصل‌ها و بخش‌های فرعی را در خود جای دهد، بلکه زیربخش‌ها را به خوبی بدون به‌روزرسانی CSS مدیریت می‌کند. رویکرد کلی در صفحات وب که می‌خواهید به مکان‌های مختلف محتوا پیوند دهید، و همچنین PDFهایی که می‌خواهید فهرست مطالب به صفحات مختلف پیوند داده شود، کار می‌کند. و البته، در صورت چاپ نیز عالی به نظر می رسد اگر تمایل دارید از آن در یک بروشور یا کتاب استفاده کنید.

می‌خواهم از جولی بلان و کریستف گرابو به خاطر پست‌های وبلاگ عالی‌شان در زمینه ایجاد فهرست مطالب تشکر کنم، زیرا هر دوی آن‌ها در شروع کار بسیار ارزشمند بودند. همچنین می‌خواهم از سارا سویدان برای بازخورد دسترسی‌اش در حین کار بر روی این پروژه تشکر کنم.


یک فهرست کامل از مطالب با HTML + CSS در ابتدا منتشر شد ترفندهای CSS. تو باید دریافت خبرنامه.

تمبر زمان:

بیشتر از ترفندهای CSS