使用 CSS 从头开始编写时间线效果
我报名了Goldstone Project Phase 1 Challenge——瓜分100,000奖池,这是我的第7篇文章, 点击查看活动详情
时间线效果介绍
在前端开发中,我们会遇到一些特别适合用时间轴显示的场景。例如,根据日期和时间记录以下事件:
您还可以制作以下更流行的左右对称卡片样式时间线:
如果加一点装饰,还可以有更显高的效果:
时间线效果精华
从上图我们可以看出时间线效果的本质不外乎以下两点:
- 使用从上到下的分隔线将可视区域分为左右两部分
- 分割线中间有一些点代表时间节点,左右显示相关信息
只要掌握如何画分割线,在分割线上画出小圆点,其实可以做出各种时间线效果。今天就带领大家实现下面这个可滚动的时间线,在项目中非常实用。学会了以后,你再也不怕对产品有类似的视觉要求了。
从头开始编写时间线
初始状态
为了教学方便,我们先定义如下空白模板:
HTML结构如下:
<身体>
<div类=“容器”>
< div 类 = "调试区域" >
< button onclick = "add()" >添加活动 </ button >
</ div >
< div class = "时间线区域" >
< div 类 = "时间线包装器" >
< div 类 = “时间线” >
</ div >
</ div >
</ div >
</ div >
</ body >
复制代码
最初的 CSS 样式是:
。容器 {
保证金:汽车;
宽度:350 像素;
高度:350px;
溢出:隐藏;
显示:弯曲;
弹性方向:列;
填充:0;
--左:62px;
--颜色:#0d5dff;
}
.调试区域{
边距:30px 0;
}
.timeline-area {
弹性:1;
位置:相对;
显示:弯曲;
弹性方向:列;
溢出-y:自动;
底部填充:10px;
padding-right: 5px;
边框:1px 实心#ccc;
}
复制代码
布局结构没什么好说的。是一个固定宽高的div,通过flex布局分为上下两部分。上方区域放置了一个按钮用于调试,下方区域是用于显示时间线内容的div,并添加了边框方便大家查看。
您可能注意到上面定义了两个变量 - 剩下
和 - 颜色
,这是干什么用的?接下来你就知道了,请继续阅读。
添加分隔线
分隔线很关键,应该如何实现?先不急着写CSS代码,先看一下HTML结构:
< div 类 = "时间线包装器" >
< div 类 = “时间线” >
</ div >
</ div >
复制代码
timeline-wrapper 是一个包装容器,它的宽度和高度是固定的,时间线就是真正的时间线。当时间轴的内容超过容器的高度时,可以自由上下滚动。所以添加以下 CSS 代码:
.timeline-wrapper {
弹性:1;
溢出-y:自动;
填充:15px 5px 0 0;
}
。时间线 {
位置:相对;
}
复制代码
最关键的地方就是这里,使用伪元素 前
实现分频器:
.timeline ::之前{
内容: ””;
位置:绝对;
左:var(--左);
宽度:1px;
顶部:20px;
底部:0;
背景图像:线性渐变(
到底部,
RGBA(144, 156, 173, 0.6) 60%,
RGBA(255, 255, 255, 0) 0%
);
背景位置:左;
背景尺寸:1px 5px;
背景重复:重复-y;
}
复制代码
设置一个绝对定位,然后从左边开始的宽度就是上面的CSS变量 - 剩下
定义距离,将其宽度设置为 1px,然后我们将样式添加到时间轴:
。时间线 {
高度:500px;
宽度:100%;
}
复制代码
可以看到,中间的分界线已经出来了:
可能很多人不知道怎么脱线?实现虚线的效果有两种。第一个使用边框来设置 dotted 或 dashed 属性:
左边框:1px 虚线 rgba(144、156、173、0.6);
复制代码
另一种是使用 background-image 来模拟:
背景图像:线性渐变(
到底部,
RGBA(144, 156, 173, 0.6) 60%,
RGBA(255, 255, 255, 0) 0%
);
背景位置:左;
背景尺寸:1px 5px;
背景重复:重复-y;
复制代码
后者的确定性更强,控制虚线的间距非常方便。
添加点
线出来后,怎么加一个小点?这时候就需要补充HTML结构了。我们必须在时间线分隔线的两侧布置内容。为了方便用 JS 动态插入内容,我们使用模板来定义时间线中每一项的 HTML 结构:
<模板>
< div class = "时间线项目" >
< div class = "时间线-左" ></ div >
< div 类 = “时间线点” ></ div >
< div class = "时间线-右" ></ div >
</ div >
</ template >
复制代码
然后在head中添加add函数:
<脚本>
常量节点 = [] 函数添加 () { 常量 tpl = 文档。 querySelector ('template') const item = tpl.内容 。儿童 [0] 常量时间线 = 文档。 querySelector ('.timeline') 节点。 forEach (it => it.classList.remove ('current')) const node = item. cloneNode ( true ) 节点。类列表。添加(“当前”)节点。推送(节点)时间线。 appendChild(节点)节点。 scrollIntoView ({ 行为 : 'smooth' , block : 'nearest' , inline : 'center' }) }</ script >
复制代码
这时候,每当我们点击上面的添加活动按钮,就可以动态的复制插入上面的DOM了!
可以看出,时间线-项目内容区域分为时间线-左、时间线-点和时间线-右。顾名思义,它们是时间线内容的左、点和右。我们先写点的样式:
.timeline-dot {
左:var(--左);
宽度:7px;
高度:7px;
位置:绝对;
边界半径:50%;
盒子阴影:0 0 0 1px #d8d8d8;
背景:白色;
文本对齐:居中;
顶部:0;
行高:40px;
左边距:- 3.5px;
}
复制代码
然后为当前活动的点添加高亮样式:
.timeline-item .current .timeline-dot {
宽度:10px;
高度:10px;
背景颜色:var(--color);
盒子阴影:0 0 4px var(--color);
边框:1px 纯白色;
左边距: - 5px;
}
复制代码
此时 - 颜色
变量的作用很明确:用来控制主题颜色。我们反复点击添加活动按钮,可以看到小圆点的效果出来了!
设置左右容器
其实到这里,时间线的原型就已经完成了,剩下的就是根据业务来定义左右两边的内容了。对于left区域,我们需要定义一个宽度小于left的值,否则会超过分割线:
.timeline-left {
显示:块;
宽度:计算(var(--left)- 7px);
位置:绝对;
边距顶部: - 5px;
文本对齐:右;
颜色:#8492a5;
}
复制代码
在右边区域,我们需要定义margin-left的值大于left的值,否则会超过分割线:
.timeline-right {
位置:相对;
边距:- 3px 0 10px calc(var(--left) + 15px);
}
复制代码
为了让大家看到效果,暂时给左右两边设置了背景颜色和高度:
.timeline-left {
背景:黄绿色;
高度:50px;
}
.timeline-right {
背景:黄绿色;
高度:50px;
}
复制代码
可以看到效果出来了:
填写左右内容
为了达到初始动画中的效果,我们来丰富模板中的内容:
<模板>
< div class = "时间线项目" >
< div class = "时间线-左" >
< div class = "开始时间" >14:00</ div >
< div 类 = “持续时间” >1h</ div >
</ div >
< div 类 = “时间线点” ></ div >
< div class = "时间线-右" >
< div class = "title" >和詹姆斯打羽毛球 </ div >
<div类=“内容”>
<div类=“信息”>
< div class = "信息-no" >
< img src = "clock.svg" />
< span class = "info-content" >14:00 ~ 15:00</ span >
</ div >
< div 类 = "信息位置" >
<img src = "location.svg" />
< span class = "info-content" >市中心羽毛球场 </ span >
</ div >
</ div >
<div类=“加入”>
< 按钮 >
报名
</ button >
</ div >
</ div >
</ div >
</ div >
</ template >
复制代码
然后添加一些样式:
.timeline-left {
。开始时间 {
字体大小:16px;
}
。期间 {
字体大小:14px;
显示:弯曲;
对齐项目:居中;
证明内容:弹性结束;
}
}
.timeline-right {
。标题 {
字体大小:15px;
字体粗细:粗体;
@扩展.省略号2;
}
。内容 {
显示:弯曲;
弹性方向:行;
填充:5px 0;
.info {
字体大小:15px;
颜色:rgba($颜色:#1f3858,$alpha:0.6);
弹性:1;
图像{
右边距:5px;
边距顶部: - 2px;
高度:15px;
}
.info-不,
.info-位置{
显示:弯曲;
对齐项目:居中;
边距:5px 0;
.info-icon {
右边距:5px;
}
.info-内容{
弹性:1;
@扩展.省略号2;
}
& .隐藏{
显示:无;
}
}
}
。加入 {
显示:弯曲;
证明内容:弹性结束;
对齐项目:弹性开始;
& .隐藏{
显示:无;
}
}
}
}
复制代码
注意上面的代码是SCSS,这是为了方便使用嵌套语法写,如果想看转换后的CSS源码,可以使用下面的命令全局安装sass预处理器,然后生成上面的SCSS代码到 CSS 中:
$ yarn global 添加 sass
$ sass 时间线.scss > 时间线.css
复制代码
加点修饰,你终于可以达到最初的效果了!
完整代码
HTML 代码:
<!DOCTYPE html >
< html lang = "en" >
<头>
<元字符集=“UTF-8”>
< meta http-equiv = "X-UA-Compatible" 内容 = "IE=edge" >
<元名称=“视口”内容=“宽度=设备宽度,初始比例=1.0”>
<title>时间线</ title >
<链接 rel = "样式表" href = "./timeline.css" >
<脚本>
常量节点 = [] 函数添加 () { 常量 tpl = 文档。 querySelector ('template') const item = tpl.内容 。儿童 [0] 常量时间线 = 文档。 querySelector ('.timeline') 节点。 forEach (it => it.classList.remove ('current')) const node = item. cloneNode ( true ) 节点。类列表。添加(“当前”)节点。推送(节点)控制台。日志(节点,节点。classList)时间线。 appendChild(节点)节点。 scrollIntoView ({ 行为 : 'smooth' , block : 'nearest' , inline : 'center' }) }</ script >
</ head >
<身体>
<div类=“容器”>
< div 类 = "调试区域" >
< button onclick = "add()" >添加活动 </ button >
</ div >
< div class = "时间线区域" >
< div 类 = "时间线包装器" >
< div 类 = “时间线” >
</ div >
</ div >
</ div >
</ div >
</ body >
<模板>
< div class = "时间线项目" >
< div class = "时间线-左" >
< div class = "开始时间" >14:00</ div >
< div 类 = “持续时间” >1h</ div >
</ div >
< div 类 = “时间线点” ></ div >
< div class = "时间线-右" >
< div class = "title" >和詹姆斯打羽毛球 </ div >
<div类=“内容”>
<div类=“信息”>
< div class = "信息-no" >
< img src = "clock.svg" />
< span class = "info-content" >14:00 ~ 15:00</ span >
</ div >
< div 类 = "信息位置" >
<img src = "location.svg" />
< span class = "info-content" >市中心羽毛球场 </ span >
</ div >
</ div >
<div类=“加入”>
< 按钮 >
报名
</ button >
</ div >
</ div >
</ div >
</ div >
</ template >
</ html >
复制代码
SCSS代码:
.省略号 {
溢出:隐藏;
文本溢出:省略号;
空白:nowrap;
}
.省略号2 {
溢出:隐藏;
空白:nowrap;
文本溢出:省略号;
@supports (-webkit-line-clamp: 2) {
空白:初始;
显示:-webkit-box;
-webkit-line-clamp:2;
-webkit-box-orient:垂直;
}
}
按钮 {
显示:弯曲;
证明内容:中心;
对齐项目:居中;
填充:0 12px;
字体大小:14px;
字体粗细:粗体;
高度:30px;
边框样式:实心;
背景:#0d5dff;
边框颜色:透明;
白颜色;
光标:指针;
}
。容器 {
保证金:汽车;
宽度:350 像素;
高度:350px;
溢出:隐藏;
显示:弯曲;
弹性方向:列;
填充:0;
--左:60px;
--颜色:#0d5dff;
}
.调试区域{
边距:30px 0;
}
.timeline-area {
弹性:1;
位置:相对;
显示:弯曲;
弹性方向:列;
溢出-y:自动;
底部填充:10px;
padding-right: 5px;
边框:1px 实心#ccc;
}
.timeline-area ::之前{
内容: ””;
显示:块;
位置:绝对;
z指数:2;
左:0;
右:12px;
顶部:0;
高度:25px;
背景:线性渐变(
到底部,
RGBA(255、255、255、1)、
RGBA(255、255、255、0)
);
}
.timeline-area::after {
内容: ””;
显示:块;
位置:绝对;
z指数:2;
左:0;
右:12px;
底部:10px;
高度:25px;
背景:线性渐变(
到达顶点,
RGBA(255、255、255、1)、
RGBA(255、255、255、0)
);
}
.timeline-wrapper {
弹性:1;
溢出-y:自动;
填充:15px 5px 0 0;
}
.timeline-wrapper::-webkit-scrollbar {
宽度:6px;
背景颜色:透明;
}
.timeline-wrapper::-webkit-scrollbar-track-piece {
边距:20px;
}
.timeline-wrapper::-webkit-scrollbar-thumb {
背景颜色:rgba($color: #000000, $alpha: 0.08);
}
。时间线 {
位置:相对;
}
.timeline ::之前{
内容: ””;
位置:绝对;
左:var(--左);
宽度:1px;
顶部:20px;
底部:0;
背景图像:线性渐变(
到底部,
RGBA(144, 156, 173, 0.6) 60%,
RGBA(255, 255, 255, 0) 0%
);
背景位置:左;
背景尺寸:1px 5px;
背景重复:重复-y;
}
.时间线项目{
位置:相对;
显示:内联块;
宽度:100%;
边距顶部:15px;
}
.timeline-dot {
左:var(--左);
宽度:7px;
高度:7px;
位置:绝对;
边界半径:50%;
盒子阴影:0 0 0 1px #d8d8d8;
背景:白色;
文本对齐:居中;
顶部:0;
行高:40px;
左边距:- 3.5px;
}
.timeline-item .current .timeline-dot {
宽度:10px;
高度:10px;
背景颜色:var(--color);
盒子阴影:0 0 4px var(--color);
边框:1px 纯白色;
左边距: - 5px;
}
.timeline-left {
显示:块;
宽度:计算(var(--left)- 7px);
位置:绝对;
边距顶部: - 5px;
文本对齐:右;
颜色:#8492a5;
}
.timeline-right {
位置:相对;
边距:- 3px 0 10px calc(var(--left) + 15px);
}
.timeline-item .current .title {
颜色: var(--color);
}
.timeline-left {
。开始时间 {
字体大小:16px;
}
。期间 {
字体大小:14px;
显示:弯曲;
对齐项目:居中;
证明内容:弹性结束;
}
}
.timeline-right {
。标题 {
字体大小:15px;
字体粗细:粗体;
@扩展.省略号2;
}
。内容 {
显示:弯曲;
弹性方向:行;
填充:5px 0;
.info {
字体大小:15px;
颜色:rgba($颜色:#1f3858,$alpha:0.6);
弹性:1;
图像{
右边距:5px;
边距顶部: - 2px;
高度:15px;
}
.info-不,
.info-位置{
显示:弯曲;
对齐项目:居中;
边距:5px 0;
.info-icon {
右边距:5px;
}
.info-内容{
弹性:1;
@扩展.省略号2;
}
& .隐藏{
显示:无;
}
}
}
。加入 {
显示:弯曲;
证明内容:弹性结束;
对齐项目:弹性开始;
& .隐藏{
显示:无;
}
}
}
}
复制代码
这里有很多细节与时间线无关,我在文章中没有解释,但其实很实用。例如,ellipsis和ellipsis2用于设置内容超过1或2行时的溢出效果,-webkit-scrollbar,--webkit-scrollbar-track-piece和-webkit-scrollbar-thumb用于自定义滚动条,有兴趣的读者可以参考我以前的 文章 .
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原文出处链接和本声明。
这篇文章的链接: https://homecpp.art/5223/10409/1834
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明