使用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实现
<!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实现
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实现
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
<!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>