Jekyll单篇文章与列表页共用默认布局的问题解决问询
解决Jekyll单篇文章与列表页共用默认布局的问题
首先得理清你的核心问题:你想让单篇文章使用默认布局(包含站点通用的头部、尾部等结构),但直接把默认布局应用到文章模板后,列表页循环渲染文章时会重复加载整个默认布局,导致页面结构嵌套混乱。
解决思路是拆分布局职责,用布局继承+内容片段复用的方式,让默认布局只负责站点全局结构,单篇文章和列表页分别填充各自的内容,避免重复渲染。
步骤1:定义基础默认布局
先把站点通用的结构放在 _layouts/default.html 里,这是所有页面的基础框架,只渲染一次:
<!DOCTYPE html> <html lang="{{ site.lang }}"> <head> <meta charset="UTF-8"> <title>{{ page.title }} | {{ site.title }}</title> <!-- 站点通用CSS、JS等 --> <link rel="stylesheet" href="/css/main.css"> </head> <body> <header class="site-header"> <!-- 导航栏、站点标题等全局头部 --> <h1><a href="/">{{ site.title }}</a></h1> <nav> <a href="/blog/">博客</a> <a href="/about/">关于</a> </nav> </header> <!-- 页面专属内容会插入到这里 --> <main class="content"> {{ content }} </main> <footer class="site-footer"> <!-- 全局尾部内容 --> <p>© {{ site.time | date: "%Y" }} {{ site.title }}</p> </footer> </body> </html>
步骤2:创建单篇文章的专用布局
新建 _layouts/post.html,让它继承默认布局,只负责单篇文章的内容结构:
--- layout: default --- <article class="single-post"> <h1 class="post-title">{{ page.title }}</h1> <div class="post-meta"> <span class="post-date">{{ page.date | date_to_string }}</span> {% if page.tags %} <span class="post-tags">标签:{{ page.tags | join: ", " }}</span> {% endif %} </div> <div class="post-content"> {{ content }} </div> </article>
然后在每篇文章的 front matter 里指定使用这个布局:
--- layout: post title: "我的第一篇文章" date: 2024-05-20 tags: [教程, Jekyll] --- <!-- 文章内容 -->
步骤3:构建列表页(复用默认布局)
列表页(比如 blog/index.html)直接使用默认布局,然后在内容区域循环渲染文章的预览片段,而不是整个文章布局:
--- layout: default title: 我的博客 --- <h1 class="page-title">最新文章</h1> <div class="post-list"> {% for post in site.posts %} <div class="post-preview"> <h2><a href="{{ post.url }}">{{ post.title }}</a></h2> <div class="preview-meta">{{ post.date | date_to_string }}</div> <p class="preview-excerpt">{{ post.excerpt | strip_html | truncatewords: 30 }}</p> <a href="{{ post.url }}" class="read-more">阅读全文 →</a> </div> {% endfor %} </div>
进阶:复用文章预览片段
如果多个页面需要展示文章预览(比如首页、分类页),可以把预览代码抽成独立的 include 文件 _includes/post-preview.html:
<div class="post-preview"> <h2><a href="{{ include.post.url }}">{{ include.post.title }}</a></h2> <div class="preview-meta">{{ include.post.date | date_to_string }}</div> <p class="preview-excerpt">{{ include.post.excerpt | strip_html | truncatewords: 30 }}</p> <a href="{{ include.post.url }}" class="read-more">阅读全文 →</a> </div>
然后在列表页里这样调用:
{% for post in site.posts %} {% include post-preview.html post=post %} {% endfor %}
关键注意点
- 绝对不要在列表页的循环里直接引用
_layouts/post.html,这会导致默认布局被嵌套渲染多次,破坏页面结构。 - 用
post.excerpt而不是post.content来展示预览,避免加载整篇文章的内容,提升列表页加载速度。
这样一来,单篇文章会通过 post 布局继承默认的站点结构,列表页也会使用默认布局,但只渲染一次全局框架,循环展示的是轻量化的文章预览,完美解决你的问题。
内容的提问来源于stack exchange,提问作者gpb14
相关产品推荐
相关产品推荐

