使用CSS Flexbox创建简洁时间轴

使用CSS Flexbox创建简洁时间轴

在网页设计中,时间轴是一种常见且有效的方式来展示事件的顺序和进程。本文将介绍如何使用CSS Flexbox创建一个简洁优雅的时间轴,无需复杂的JavaScript代码。

基本HTML结构

首先,我们需要创建基本的HTML结构:

复制代码
html复制<div class="timeline">
  <div class="events">
    <div class="event life">
      <svg class="marker" xmlns="http://www.w3.org/200![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d6842b409144c9f99fd8aa5bdc24d89.png#pic_center)
0/svg" width="12" height="12">
        <circle cx="6" cy="6" r="6"></circle>
      </svg>
      <div class="content">
        <time>1989</time>
        <div class="text">
          <p>I was born in the north of Sweden</p>
        </div>
      </div>
    </div>
    <!-- 更多事件... -->
  </div>
</div>

CSS样式

1. 创建时间线

使用::before伪元素创建时间线:

复制代码
css复制.events {
  position: relative;
}

.events::before {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: 1px;
  background: white;
}

2. 事件对齐

使用Flexbox对齐事件:

复制代码
css复制.event {
  display: flex;
  align-items: baseline;
}

.event .marker {
  position: relative;
  left: -6px;
}

3. 垂直间距

使用Flexbox控制事件间的垂直间距:

复制代码
css复制.events {
  display: flex;
  flex-direction: column;
  row-gap: 1em;
}

4. 响应式设计

使用媒体查询实现响应式设计:

复制代码
css复制@media (min-width: 700px) {
  .events::before {
    left: 50%;
  }
  
  .event .marker {
    order: 1;
  }
  
  .event .content {
    width: 50%;
    text-align: right;
    padding-inline: 1em;
  }
  
  .event:nth-child(even) {
    flex-direction: row-reverse;
  }
  
  .event:nth-child(even) .content {
    text-align: left;
  }
  
  .event:nth-child(even) .marker {
    left: 6px;
  }
}

完整CSS代码

以下是完整的CSS代码:

复制代码
css复制.events::before {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: 1px;
  background: var(--color-hr);
}

.events {
  position: relative;
  display: flex;
  margin-block: 0.5em;
  flex-direction: column;
  row-gap: 1em;
}

.event {
  display: flex;
  align-items: baseline;
}

.event .marker {
  position: relative;
  left: -6px;
}

.event.life .marker {
  fill: var(--melange_b_yellow);
}

.event.programming .marker {
  fill: var(--melange_b_magenta);
}

.event.family .marker {
  fill: var(--melange_b_red);
}

.content time {
  font-family: concourse_4, Helvetica, sans-serif;
  font-weight: bold;
}

@media (min-width: 700px) {
  .events::before {
    left: 50%;
  }
  
  .event .marker {
    order: 1;
  }
  
  .event .content {
    width: 50%;
    text-align: right;
    padding-inline: 1em;
  }
  
  .event:is(.programming, .work, .projects) {
    flex-direction: row-reverse;
  }
  
  .event:is(.programming, .work, .projects) .content {
    text-align: left;
  }
  
  .event:is(.programming, .work, .projects) .marker {
    left: 6px;
  }
}

通过这些CSS样式,我们创建了一个简洁、响应式的时间轴。在小屏幕上,事件垂直排列;在大屏幕上,事件分布在时间线的两侧。这种设计既美观又实用,能够有效地展示事件的顺序和重要性。

使用Flexbox使得创建这样的时间轴变得相对简单,它简化了许多曾经复杂的布局任务。通过调整颜色、字体和间距,你可以进一步自定义时间轴以适应你的网站设计。

demos实现

HTML实现

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>交互式时间轴演示</title>
  <style>
    /* CSS 样式将在这里 */
  </style>
</head>
<body>
  <h1>交互式时间轴演示</h1>
  
  <div class="controls">
    <label>
      时间轴颜色:
      <input type="color" id="lineColor" value="#ffffff">
    </label>
    <label>
      事件间距:
      <input type="range" id="eventSpacing" min="0.5" max="3" step="0.1" value="1">
    </label>
    <label>
      响应式布局宽度:
      <input type="number" id="responsiveWidth" min="300" max="1200" step="50" value="700">px
    </label>
  </div>

  <div class="timeline">
    <div class="events">
      <div class="event life">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>1989</time>
          <div class="text">
            <p>我出生在瑞典北部</p>
          </div>
        </div>
      </div>
      <div class="event programming">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2005</time>
          <div class="text">
            <p>开始学习编程</p>
          </div>
        </div>
      </div>
      <div class="event life">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2010</time>
          <div class="text">
            <p>搬到瑞典南部</p>
          </div>
        </div>
      </div>
      <div class="event programming">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2015</time>
          <div class="text">
            <p>开始职业编程生涯</p>
          </div>
        </div>
      </div>
      <div class="event family">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2020</time>
          <div class="text">
            <p>组建家庭</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script>
    // JavaScript 代码将在这里
  </script>
</body>
</html>

CSS实现

css 复制代码
body {
  font-family: Arial, sans-serif;
  max-width: 800px;
  margin: 0 auto;
  padding: 20px;
  background-color: #f0f0f0;
  color: #333;
}

h1 {
  text-align: center;
}

.controls {
  background-color: #e0e0e0;
  padding: 10px;
  margin-bottom: 20px;
  border-radius: 5px;
}

.controls label {
  display: block;
  margin-bottom: 10px;
}

.timeline {
  background-color: #fff;
  padding: 20px;
  border-radius: 5px;
  box-shadow: 0 2px 5px rgba(0,0,0,0.1);
}

.events::before {
  content: "";
  position: absolute;
  top: 0;
  height: 100%;
  width: 2px;
  background: var(--line-color, #fff);
}

.events {
  position: relative;
  display: flex;
  margin-block: 0.5em;
  flex-direction: column;
  row-gap: var(--event-spacing, 1em);
}

.event {
  display: flex;
  align-items: baseline;
}

.event .marker {
  position: relative;
  left: -6px;
}

.event.life .marker { fill: #ffd700; }
.event.programming .marker { fill: #ff00ff; }
.event.family .marker { fill: #ff0000; }

.content time {
  font-weight: bold;
}

@media (min-width: 700px) {
  .events::before {
    left: 50%;
  }

  .event .marker {
    order: 1;
  }

  .event .content {
    width: 50%;
    text-align: right;
    padding-inline: 1em;
  }

  .event:nth-child(even) {
    flex-direction: row-reverse;
  }

  .event:nth-child(even) .content {
    text-align: left;
  }

  .event:nth-child(even) .marker {
    left: 6px;
  }
}

js实现

js 复制代码
document.addEventListener('DOMContentLoaded', function() {
  const lineColor = document.getElementById('lineColor');
  const eventSpacing = document.getElementById('eventSpacing');
  const responsiveWidth = document.getElementById('responsiveWidth');
  const timeline = document.querySelector('.timeline');
  const events = document.querySelector('.events');

  function updateTimeline() {
    timeline.style.setProperty('--line-color', lineColor.value);
    events.style.setProperty('--event-spacing', `${eventSpacing.value}em`);
    document.body.style.setProperty('--responsive-width', `${responsiveWidth.value}px`);
  }

  lineColor.addEventListener('input', updateTimeline);
  eventSpacing.addEventListener('input', updateTimeline);
  responsiveWidth.addEventListener('input', updateTimeline);

  updateTimeline();
});

完整demo

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>交互式时间轴演示</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      max-width: 800px;
      margin: 0 auto;
      padding: 20px;
      background-color: #f0f0f0;
      color: #333;
    }

    h1 {
      text-align: center;
    }

    .controls {
      background-color: #e0e0e0;
      padding: 10px;
      margin-bottom: 20px;
      border-radius: 5px;
    }

    .controls label {
      display: block;
      margin-bottom: 10px;
    }

    .timeline {
      background-color: #fff;
      padding: 20px;
      border-radius: 5px;
      box-shadow: 0 2px 5px rgba(0,0,0,0.1);
    }

    .events::before {
      content: "";
      position: absolute;
      top: 0;
      height: 100%;
      width: 2px;
      background: var(--line-color, #fff);
    }

    .events {
      position: relative;
      display: flex;
      margin-block: 0.5em;
      flex-direction: column;
      row-gap: var(--event-spacing, 1em);
    }

    .event {
      display: flex;
      align-items: baseline;
    }

    .event .marker {
      position: relative;
      left: -6px;
    }

    .event.life .marker { fill: #ffd700; }
    .event.programming .marker { fill: #ff00ff; }
    .event.family .marker { fill: #ff0000; }

    .content time {
      font-weight: bold;
    }

    @media (min-width: var(--responsive-width, 700px)) {
      .events::before {
        left: 50%;
      }

      .event .marker {
        order: 1;
      }

      .event .content {
        width: 50%;
        text-align: right;
        padding-inline: 1em;
      }

      .event:nth-child(even) {
        flex-direction: row-reverse;
      }

      .event:nth-child(even) .content {
        text-align: left;
      }

      .event:nth-child(even) .marker {
        left: 6px;
      }
    }
  </style>
</head>
<body>
  <h1>交互式时间轴演示</h1>
  
  <div class="controls">
    <label>
      时间轴颜色:
      <input type="color" id="lineColor" value="#ffffff">
    </label>
    <label>
      事件间距:
      <input type="range" id="eventSpacing" min="0.5" max="3" step="0.1" value="1">
    </label>
    <label>
      响应式布局宽度:
      <input type="number" id="responsiveWidth" min="300" max="1200" step="50" value="700">px
    </label>
  </div>

  <div class="timeline">
    <div class="events">
      <div class="event life">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>1989</time>
          <div class="text">
            <p>我出生在瑞典北部</p>
          </div>
        </div>
      </div>
      <div class="event programming">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2005</time>
          <div class="text">
            <p>开始学习编程</p>
          </div>
        </div>
      </div>
      <div class="event life">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2010</time>
          <div class="text">
            <p>搬到瑞典南部</p>
          </div>
        </div>
      </div>
      <div class="event programming">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2015</time>
          <div class="text">
            <p>开始职业编程生涯</p>
          </div>
        </div>
      </div>
      <div class="event family">
        <svg class="marker" xmlns="http://www.w3.org/2000/svg" width="12" height="12">
          <circle cx="6" cy="6" r="6"></circle>
        </svg>
        <div class="content">
          <time>2020</time>
          <div class="text">
            <p>组建家庭</p>
          </div>
        </div>
      </div>
    </div>
  </div>

  <script>
    document.addEventListener('DOMContentLoaded', function() {
      const lineColor = document.getElementById('lineColor');
      const eventSpacing = document.getElementById('eventSpacing');
      const responsiveWidth = document.getElementById('responsiveWidth');
      const timeline = document.querySelector('.timeline');
      const events = document.querySelector('.events');

      function updateTimeline() {
        timeline.style.setProperty('--line-color', lineColor.value);
        events.style.setProperty('--event-spacing', `${eventSpacing.value}em`);
        document.body.style.setProperty('--responsive-width', `${responsiveWidth.value}px`);
      }

      lineColor.addEventListener('input', updateTimeline);
      eventSpacing.addEventListener('input', updateTimeline);
      responsiveWidth.addEventListener('input', updateTimeline);

      updateTimeline();
    });
  </script>
</body>
</html>

参考文章: Jonas Hietala: A simple timeline using CSS flexbox

相关推荐
SunTecTec26 分钟前
Flink Docker Application Mode 命令解析 - 修改命令以启用 Web UI
大数据·前端·docker·flink
软件技术NINI27 分钟前
html css js网页制作成品——HTML+CSS甜品店网页设计(4页)附源码
javascript·css·html
拉不动的猪1 小时前
前端常见数组分析
前端·javascript·面试
小吕学编程2 小时前
ES练习册
java·前端·elasticsearch
Asthenia04122 小时前
Netty编解码器详解与实战
前端
袁煦丞2 小时前
每天省2小时!这个网盘神器让我告别云存储混乱(附内网穿透神操作)
前端·程序员·远程工作
一个专注写代码的程序媛3 小时前
vue组件间通信
前端·javascript·vue.js
一笑code3 小时前
美团社招一面
前端·javascript·vue.js
懒懒是个程序员4 小时前
layui时间范围
前端·javascript·layui
NoneCoder4 小时前
HTML响应式网页设计与跨平台适配
前端·html