Sea 目录样式修改

Hexo Theme Sea 主题目录(TOC)位置修改文档

本文档旨在详细记录将 Hexo Sea 主题的文章目录从内容区域移动到页面左侧固定侧边栏的所有代码修改步骤。

修改目标

  • 功能:在文章页面,将目录(TOC)显示在左侧边栏,并使其在页面滚动时保持固定(sticky)。
  • 体验:便于用户在阅读长篇文章时,随时通过点击目录进行快速跳转。
  • 兼容性:在没有目录的文章页面,主内容区域应保持居中,不发生布局偏移。在屏幕宽度不足时,侧边栏自动隐藏,以保证移动端阅读体验。

修改文件概览

总共需要修改 4 个文件:

  1. layout/layout.njk:修改主布局文件,以支持新的网格布局结构。
  2. layout/post.njk:移除文章内容区域内旧的目录显示代码。
  3. source/css/_partial/layout.css:为新的页面结构添加核心的 CSS Grid 布局样式。
  4. source/css/_partial/post.css:为新的左侧目录侧边栏添加美化样式。

详细修改步骤

1. 修改主布局文件:layout/layout.njk

目的:创建支持三栏布局(左侧栏、内容区、右侧栏)的 HTML 结构,为新的目录侧边栏提供容器。

具体操作:将原有的 <main> 标签用一个新的 <div class="sea-content-wrapper"> 包裹起来,并在这个新容器中添加用于显示目录的 <aside> 标签。

原始代码

stateDiagram-v2
    [*] --> CLOSED : 系统启动

    CLOSED --> OPEN   : 失败率/连续失败数\n≥阈值
    OPEN   --> HALF_OPEN : 休眠时间到
    HALF_OPEN --> CLOSED : 探测请求全部成功
    HALF_OPEN --> OPEN   : 存在失败
<main id="sea-main-wrapper" data-pagefind-body>
  {{ body }}
</main>

修改后代码

<div class="sea-content-wrapper">
  
  <main id="sea-main-wrapper" data-pagefind-body>
    {{ body }}
  </main>

  {% if is_post() and page.tableOfContents %}
    {% set tocContent = toc(page.content) %}
    {% if tocContent %}
    <aside class="sea-toc-aside">
      <div class="sea-article-catalog">
        <h2 class="sea-article-catalog-title">
          {{ __('page.contents') }}
        </h2>
        
        <div class="sea-toc-scrollable">
          {{ tocContent }}
        </div>

      </div>
    </aside>
    {% endif %}
  {% endif %}
  
</div>

2. 移除旧目录代码:layout/post.njk

目的:避免目录重复显示,并移除不再需要的旧版目录折叠功能的脚本。

具体操作:删除 post.njk 文件中用于生成可折叠目录的 {% if page.tableOfContents %} 代码块以及文件底部的相关 <script> 标签。

**需删除的代码块 1 (目录结构)**:

{% if page.tableOfContents %}
  {% set tocContent = toc(page.content) %}
  {% if tocContent %}
    <div class="sea-article-catalog">
      <h2 class="sea-article-catalog-title">
        {{ partial('svg/arrow_right_fill') }}
        {{ __('page.contents') }}
      </h2>
      {{ tocContent }}
    </div>
  {% endif %}
{% endif %}

**需删除的代码块 2 (JavaScript 脚本)**:

<script defer>
  document.addEventListener('DOMContentLoaded', function () {
    const toggleIcon = document.querySelector('.sea-article-catalog-title .sea-svg-icon');
    const tocContent = document.querySelector('.sea-article-catalog > .toc');
    if (toggleIcon && tocContent) {
      toggleIcon.addEventListener('click', function () {
        tocContent.classList.toggle('sea-article-catalog-show');
        toggleIcon.classList.toggle('sea-svg-icon-rotate');
      });
    }
  });
</script>

3. 添加核心布局样式:source/css/_partial/layout.css

目的:使用 CSS Grid 技术定义新的页面布局,确保主内容区无论在何种情况下都保持居中。

具体操作:修改 #sea-main-wrapper 的样式,并在文件末尾添加用于 .sea-content-wrapper.sea-toc-aside 的新样式。

修改 #sea-main-wrapper 样式

/* 原始样式 */
#sea-main-wrapper {
  width: var(--sea-main-width);
  padding: 1rem 1.2rem 0;
  max-width: var(--sea-main-max-width);
  margin: 0 auto;
}

/* 修改后的样式 */
#sea-main-wrapper {
  grid-column: 2; /* 强制主内容区始终位于中间的第二列 */
  width: 100%;
  padding: 1rem 0 0;
  margin: 0;
}

在文件末尾添加新样式

/* -- 新的页面内容网格布局 -- */
.sea-content-wrapper {
  display: grid;
  grid-template-columns: 1fr minmax(auto, var(--sea-main-max-width)) 1fr;
  column-gap: 2rem;
  width: 100%;
  margin: 0 auto;
  padding: 0 1.2rem;
}

#sea-main-wrapper {
  grid-column: 2; /* 强制主内容区始终位于中间的第二列 */
  width: 100%;
  padding: 1rem 0 0;
  margin: 0;
}

.sea-toc-aside {
  position: fixed;
  top: 50px; /* 侧边栏距离顶部的距离 */
  left: calc((100% - var(--sea-main-max-width)) / 2 - 320px - 2rem);
  width: 250px;
  display: none; /* 默认隐藏,在宽屏时由下面的媒体查询显示 */
  bottom: 20px; /* 侧边栏距离底部的距离 */
}
/* 在宽屏上显示目录 */
@media screen and (min-width: 1350px) {
  .sea-toc-aside {
    display: block;
  }
}

4. 添加目录美化样式:source/css/_partial/post.css

目的:美化新的左侧目录侧边栏,使其具有更好的视觉效果。

具体操作:在文件末尾添加以下样式代码。

在文件末尾添加新样式

/* 目录美化样式 */
/* 1. 使 .sea-article-catalog 成为一个 flex 容器,并撑满整个侧边栏 */
.sea-toc-aside .sea-article-catalog {
  display: flex;
  flex-direction: column;
  height: 80%; /* 关键:让它占满父容器 .sea-toc-aside 的全部高度 */
}

/* 2. 目录标题样式 (作为固定部分) */
.sea-toc-aside .sea-article-catalog-title {
  font-size: 1.2rem;
  font-weight: 600;
  margin-bottom: 1rem;
  padding-top: 1rem;
  flex-shrink: 0; /* 防止标题在空间不足时被压缩 */
  margin-top: 10vh;
}

/* 3. 可滚动容器的样式 */
.sea-toc-aside .sea-toc-scrollable {
  overflow-y: auto; /* 核心:启用垂直滚动 */
  
  /* --- 隐藏滚动条 --- */
  scrollbar-width: none; /* Firefox */
  -ms-overflow-style: none; /* IE and Edge */
}
.sea-toc-aside .sea-toc-scrollable::-webkit-scrollbar {
  display: none; /* Chrome, Safari, Opera */
}


/* 4. 目录列表(.toc)本身的美化样式 */
.sea-toc-aside .toc {
  display: block !important;
  list-style: none;
  padding-left: 1rem;
  border-left: 2px solid var(--sea-color-divider);
  padding-bottom: 1rem; /* 为滚动到底部时增加一些空间 */
}

.sea-toc-aside .toc .toc-item {
  margin-top: 0.5rem;
}

.sea-toc-aside .toc .toc-link {
  font-size: 0.875rem;
  color: var(--sea-color-text-2);
  transition: color 0.2s ease;
}

.sea-toc-aside .toc .toc-link:hover {
  color: var(--sea-color-primary);
}

.sea-toc-aside .toc .toc-child {
  padding-left: 1rem;
}

/* 5. 覆盖旧样式,确保我们的代码生效 */
.sea-article-catalog-title .sea-svg-icon {
  display: none;
}