
本文详解如何利用 jekyll 的 liquid 模板语法,根据当前页面 url 自动显示对应目录下的子菜单,无需 javascript,纯静态生成,适合初学者快速上手。
本文详解如何利用 jekyll 的 liquid 模板语法,根据当前页面 url 自动显示对应目录下的子菜单,无需 javascript,纯静态生成,适合初学者快速上手。
Jekyll 本身不提供“动态路由”或运行时逻辑,但其强大的 Liquid 模板引擎支持条件判断与字符串操作,足以实现路径感知的自动导航菜单——即访问 /about/ 下任意页面时,自动展开“About”子菜单;访问 /projects/ 时则显示 Projects 相关子项。这种方案完全静态、零依赖、高性能,且易于维护。
核心思路:用 URL 路径判断当前上下文
Jekyll 中每个页面的 page.url 是其生成后的相对路径(如 /about/team/ 或 /projects/apples/)。我们可通过 Liquid 对该路径做字符串匹配,从而决定是否渲染某组子菜单。
最简洁可靠的方式是使用 startswith 过滤器:
{% assign currentUrl = page.url | downcase %}
{% if currentUrl starts_with: "/about/" %}
<nav class="sub-menu">
<a href="/about/">关于我们</a>
<a href="/about/team/">团队介绍</a>
<a href="/about/history/">发展历程</a>
</nav>
{% endif %}
{% if currentUrl starts_with: "/projects/" %}
<nav class="sub-menu">
<a href="/projects/">全部项目</a>
<a href="/projects/web/">Web 应用</a>
<a href="/projects/mobile/">移动应用</a>
</nav>
{% endif %}✅ 优势说明:
- starts_with 比逐级 split + current[1] == 'about' 更健壮,能正确匹配 /about/、/about/team/、/about/team/john/ 等所有子路径;
- downcase 保证大小写不敏感(避免因 URL 大小写差异导致匹配失败);
- 所有逻辑在构建时完成,无客户端 JS,兼容性好、加载快。
实践建议:结构化复用,避免重复代码
若菜单较多,不建议在每个布局中硬编码 if 块。推荐将逻辑封装进 _includes/nav-submenu.html:
<!-- _includes/nav-submenu.html -->
{% assign current = page.url | downcase %}
{% if current starts_with: "/about/" %}
{% include nav-about.html %}
{% elsif current starts_with: "/projects/" %}
{% include nav-projects.html %}
{% elsif current starts_with: "/blog/" %}
{% include nav-blog.html %}
{% endif %}再分别创建 nav-about.html、nav-projects.html 等文件存放对应 HTML,使结构清晰、便于协作维护。
注意事项与常见问题
- ? 路径结尾斜杠很重要:确保使用 "/about/"(含尾部 /),否则会错误匹配 /about-us/;
- ? 首页特殊处理:page.url 在首页为 /,可用 {% if current == '/' %} 单独判断;
- ? 本地开发测试:Jekyll 默认启用 baseurl,若站点部署在子路径(如 https://example.com/docs/),需在 _config.yml 中设置 baseurl: "/docs",并在链接中使用 {{ site.baseurl }}/about/;
- ? 性能无忧:Liquid 模板在构建阶段执行,不影响页面运行时性能。
通过这一模式,你就能像 nchrs.xyz 那样,让导航栏“感知”用户所处位置,并智能呈现上下文相关的子菜单——无需 fork 复杂主题,也不用写一行 JavaScript,仅靠 Jekyll 原生能力即可优雅实现。

















