如何给 Hugo 博客添加优雅的垂直时间线组件

Web
373 字 · 2 分钟
... 次阅读

最近有朋友问我栏目的时间线功能是怎么实现的。为了能够在文章中优雅地展示经历或版本更新记录,我使用 Hugo 的 Shortcode 功能配合 CSS 实现了一个垂直时间线组件。本文将简要介绍其实现原理,并分享完整代码。

实现思路

实现这个功能的核心思想是利用 Hugo 的 Shortcode 来生成 HTML 结构,并通过 CSS 处理布局和连线。

为了保持代码的语义化(Semantic HTML),我们将时间线视为一个无序列表(<ul>),每一个时间节点则是列表项(<li>)。这比单纯使用 <div> 堆砌更符合 Web 标准,对 SEO 和辅助阅读设备也更友好。

代码实现

我们需要创建两个 Shortcode 文件:容器和列表项。

容器组件 (timeline)

创建文件 layouts/shortcodes/timeline.html:

<ul class="timeline-container">
  {{ .Inner }}
</ul>

子项组件 (timeline-item)

创建文件 layouts/shortcodes/timeline-item.html:

<li class="timeline-item">
  <div class="timeline-marker"></div>
  <div class="timeline-content">
    <p class="timeline-date">{{ .Get "date" }}</p>
    <div class="timeline-text">{{ .Inner }}</div>
  </div>
</li>

样式定义 (CSS)

以下是完整的 CSS 样式代码(支持响应式和深色模式)。你可以将其添加到你的 SCSS 或 CSS 文件中(例如 assets/scss/custom.scss):

/* 时间线样式 */
.timeline-container {
  max-width: 600px;
  margin: 40px auto;
  padding: 0 20px;
  position: relative;
  background: transparent;
  list-style: none;
}

.timeline-container::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  background: var(--timeline-line, #e6e6e6);
  transform: translateX(-50%);
  transition: background 0.3s;
}

.timeline-item {
  display: flex;
  margin-bottom: 40px;
  position: relative;
}

.timeline-marker {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: linear-gradient(
    135deg,
    var(--primary-color, #4285f4),
    var(--primary-color-dark, #1a237e)
  );
  border: 3px solid var(--timeline-bg, #fff);
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
  box-shadow: 0 0 0 4px var(--timeline-shadow, #e3f2fd);
  transition:
    background 0.3s,
    box-shadow 0.3s;
}

.timeline-content {
  width: calc(50% - 40px);
  padding: 0px 10px 12px 15px;
  border-radius: 10px;
  background: var(--timeline-bg, #fff);
  box-shadow: 0 3px 16px rgba(0, 0, 0, 0.1);
  color: var(--timeline-text, #263238);
  transition:
    background 0.3s,
    color 0.3s,
    box-shadow 0.3s;
  margin-top: 0;
}

.timeline-item:nth-child(odd) .timeline-content {
  margin-left: auto;
}

.timeline-item:nth-child(even) .timeline-content {
  margin-right: auto;
}

.timeline-date {
  color: var(--primary-color, #4285f4);
  margin-bottom: 10px;
  font-weight: bold;
}

.timeline-text {
  line-height: 1.6;
}

/* 响应式设计 - 时间线在小屏幕上改为单列布局 */
@media (max-width: 768px) {
  .timeline-container {
    max-width: 100%;
  }

  .timeline-container::before {
    left: 20px;
  }

  .timeline-item {
    flex-direction: column;
  }

  .timeline-marker {
    left: 20px;
  }

  .timeline-content {
    width: calc(100% - 45px);
    margin-left: 45px !important;
  }
}

/* 时间线深色模式 */
[data-scheme='dark'] {
  --timeline-bg: #23272e;
  --timeline-line: #31343a;
  --timeline-text: #e6e6e6;
  --timeline-shadow: #181a20;
  --primary-color: #64b5f6;
  --primary-color-dark: #1976d2;
}

[data-scheme='dark'] .timeline-content {
  background: linear-gradient(135deg, #23272e 80%, #262a32 100%);
  color: var(--timeline-text, #e6e6e6);
  box-shadow: 0 3px 16px rgba(0, 0, 0, 0.4);
  border: 1px solid #31343a;
}

[data-scheme='dark'] .timeline-marker {
  background: linear-gradient(135deg, #64b5f6, #1976d2);
  border: 3px solid #23272e;
  box-shadow: 0 0 0 4px #181a20;
}

[data-scheme='dark'] .timeline-date {
  color: #90caf9;
}

使用方法

定义好组件后,在 Markdown 文件中就能非常方便地调用了。

{{</* timeline */>}}
{{</* timeline-item date="2025-12" */>}}
发布了这篇关于时间线实现的教程。
{{</* /timeline-item */>}}

    {{</* timeline-item date="2024-01" */>}}
    博客正在进行代码重构优化。
    {{</* /timeline-item */>}}

{{</* /timeline */>}}

以下是上述代码渲染后的实际效果:

发布了这篇关于时间线实现的教程。

博客正在进行代码重构优化。

这样,一个清晰明了且代码优雅的时间线就完成啦。

感谢阅读与支持

如果本文对您有所启发或帮助,欢迎点赞鼓励或请博主喝杯咖啡!

☕支持