• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

使用 CSS 和一点 JavaScript 构建垂直时间线

在本教程中,咱们将学习如何从头开始构建响应式垂直时间线

首先,咱们将使用最少的标记和 css 伪元素的强大功能创建基本结构。然后,当咱们向下滚动页面时,咱们将使用一些 javascript 添加一些过渡效果。 

让咱们了解一下咱们将要构建什么(查看CodePen 上的更大版本)。

See the Pen  Building a Vertical Timeline With CSS and a Touch of JavaScript by Envato Tuts+ (@tutsplus)  on CodePen.

1.  html 标记

咱们将使用的标记非常简单;一个普通的无序列表,div在咱们的每个列表项中都有一个元素。当咱们沿着时间线处理事件时,咱们将为每个列表项提供一个time元素来显示年份。

此外,咱们将把整个东西包装在一个section 元素中,其类为timeline:

<section class="timeline">

  <ul>

    <li>

      <div>

        <time>1934</time>

        Some content here

      </div>

    </li> 

    <!-- more list items here -->

  </ul>

</section>

这为咱们提供了以下无样式输出:

See the Pen  Vertical Timeline Step 1 by Envato Tuts+ (@tutsplus)  on CodePen.

2.添加初始 CSS 样式

在一些基本的颜色等之后(查看下面钢笔中 CSS 的上半部分),咱们将为列表项定义一些结构化的 CSS 规则。咱们还将::after  为这些项目的伪元素设置样式:

.timeline ul li {

  list-style-type: none;

  position: relative;

  width: 6px;

  margin: 0 auto;

  padding-top: 50px;

  background: #fff;

}

.timeline ul li::after {

  content: '';

  position: absolute;

  left: 50%;

  bottom: 0;

  transform: translateX(-50%);

  width: 30px;

  height: 30px;

  border-radius: 50%;

  background: inherit;

  z-index: 1;

}

我已删除列表项中的内容以使此步骤更清晰,为咱们提供以下内容:

See the Pen  Vertical Timeline Step 2 by Envato Tuts+ (@tutsplus)  on CodePen.

3. 时间线元素样式

div现在让咱们为列表项中的元素(从现在起咱们将它们称为“时间线元素”)设置样式。::before同样,咱们对这些元素的伪元素进行 样式设置。

此外,正如咱们稍后将看到的,并非所有divs 都具有相同的样式。感谢 :nth-child(odd)和 :nth-child(even) CSS 伪类,咱们能够区分它们的样式。

看看下面对应的 CSS 规则:

.timeline ul li div {

  position: relative;

  bottom: 0;

  width: 400px;

  padding: 15px;

  background: #F45B69;

}

.timeline ul li div::before {

  content: '';

  position: absolute;

  bottom: 7px;

  width: 0;

  height: 0;

  border-style: solid;

}

然后是咱们奇怪元素的一些样式:

.timeline ul li:nth-child(odd) div {

  left: 45px;

}

.timeline ul li:nth-child(odd) div::before {

  left: -15px;

  border-width: 8px 16px 8px 0;

  border-color: transparent #F45B69 transparent transparent;

}

最后是咱们偶数元素的样式:

.timeline ul li:nth-child(even) div {

  left: -439px;

}

 

.timeline ul li:nth-child(even) div::before {

  right: -15px;

  border-width: 8px 0 8px 16px;

  border-color: transparent transparent transparent #F45B69;

}

有了这些规则(并且咱们的 HTML 再次包含内容),咱们的时间线如下所示:

See the Pen  Vertical Timeline Step 3 by Envato Tuts+ (@tutsplus)  on CodePen.

“奇数”和“偶数”之间的主要区别在于div它们的位置。第一个有left: 45px,而第二个left: -439px。为了理解咱们 evendiv的定位,让咱们做一些简单的数学运算:

每个的宽度div+ 所需间距 - 每个列表项的宽度 = 400px + 45px - 6px = 439px

第二个不太重要的区别是它们的伪元素生成的箭头。这意味着,每个“奇数”div的伪元素都有一个左箭头,而每个“偶数”的伪元素div显示为一个右箭头。 

4.增加交互性

现在时间线的基本结构已经准备好了,咱们来弄清楚新的需求: 

  • 默认情况下,时间线元素 ( divs) 应该是隐藏的。

  • 它们应该在其父项(列表项)进入视口时出现。

第一项任务相对简单。但是,第二个要复杂一些。咱们需要检测目标元素(列表项)是否在当前视口中完全可见,如果发生这种情况,咱们会显示它们的子元素。为了实现这个功能,咱们不会使用任何外部 JavaScript 库(例如 WOW.js 或ScrollReveal.js)或编写咱们自己的复杂代码。令人高兴的是,Stack Overflow 上有一个关于这个问题的热门话题。因此,首先让咱们利用建议的答案来测试元素在当前视口中是否可见。 

这是咱们将使用的简化函数:

function isElementInViewport(el) {

  var rect = el.getBoundingClientRect();

  return (

    rect.top >= 0 &&

    rect.left >= 0 &&

    rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&

    rect.right <= (window.innerWidth || document.documentElement.clientWidth)

  );

}

在视图中添加类

接下来,咱们将in-view类添加到当前视口中可见的列表项中。 

注意:咱们必须测试它们在以下情况下是否可见:

  • 页面加载时

  • 当咱们向下滚动

如果需要,咱们可以做一些额外的测试(比如当浏览器窗口的大小改变时)。

在咱们的示例中,这是咱们使用的代码:

var items = document.queryselectorAll(".timeline li");

// code for the isElementInViewport function

function callbackFunc() {

  for (var i = 0; i < items.length; i++) {

    if (isElementInViewport(items[i])) {

      items[i].classList.add("in-view");

    }

  }

}

window.addeventListener("load", callbackFunc);

window.addEventListener("scroll", callbackFunc);

现在咱们已经添加了 javaScript,如果咱们重新加载页面,咱们应该会看到类似这样的结果: 

使用 CSS 和一点 JavaScript 构建垂直时间线  第1张


隐藏和揭示

现在让咱们重新审视咱们最初的需求。请记住,默认情况下,所有divs 都应该被隐藏。为此,咱们使用visibility和opacityCSS 属性。此外,咱们使用该translate3d()函数将它们从原始位置移动 200 像素。只要它们的父级在视图中,咱们就会显示它们并删除预定义的偏移量。通过这种方式,咱们创建了漂亮的滑入效果。  

最后,当 a 在视口中时,咱们要做的另一件小事li是更改其::after伪元素的背景颜色。

以下样式可以解决所有这些问题:

.timeline ul li::after {

  background: #fff;

  transition: background .5s ease-in-out;

}

 

.timeline ul li.in-view::after {

  background: #F45B69;

}

 

.timeline ul li div {

  visibility: hidden;

  opacity: 0;

  transition: all .5s ease-in-out;

}

 

.timeline ul li:nth-child(odd) div {

  transform: translate3d(200px,0,0);

}

 

.timeline ul li:nth-child(even) div {

  transform: translate3d(-200px,0,0);

}

 

.timeline ul li.in-view div {

  transform: none;

  visibility: visible;

  opacity: 1;

}

以下可视化显示了咱们时间线的初始状态。在这里您可以看到时间线元素,因为我给它们添加了一点不透明性,只是为了说明它们最初的位置:

使用 CSS 和一点 JavaScript 构建垂直时间线  第2张

这是时间线的最终状态:

使用 CSS 和一点 JavaScript 构建垂直时间线  第3张

5.自定义圈子

默认情况下,::after每个时间线元素的伪元素看起来像一个圆圈。但是,让咱们为自定义其初始外观提供一些选择。

最重要的是,咱们将使用该clip-path属性来创建一些复杂的形状。但令人高兴的是,咱们不需要从头开始创建它们。咱们将利用Clippy,一个剪辑路径生成器。

  • 如果您想要星形而不是圆形,请将timeline-clippy和timeline-star类添加到时间轴,如下所示:


<section class="timeline timeline-clippy timeline-star">

使用 CSS 和一点 JavaScript 构建垂直时间线  第4张

  • 如果您想要菱形而不是圆形,请将timeline-clippy 和 timeline-rhombus 类添加到时间轴,如下所示:


<section class="timeline timeline-clippy timeline-rhombus">
使用 CSS 和一点 JavaScript 构建垂直时间线  第5张
  • 如果您想要一个 七边形 而不是圆形,请将 timeline-clippy 和 timeline-heptagon类添加到时间轴,如下所示:


<section class="timeline timeline-clippy timeline-heptagon">
使用 CSS 和一点 JavaScript 构建垂直时间线  第6张

Clippy 可让您创建更多形状,因此如果您想要不同的东西,请务必查看其网站。

如果你仍然想保留圆圈,也可以通过使用这样的timeline-infinite类给它们一些无限比例的动画


<section class="timeline timeline-infinite">
使用 CSS 和一点 JavaScript 构建垂直时间线  第7张

当然,您也可以将此动画与上述自定义形状结合起来,如下所示:


<section class="timeline timeline-clippy timeline-star timeline-infinite">
使用 CSS 和一点 JavaScript 构建垂直时间线  第8张

以下是所有相关样式:

.timeline-clippy ul li::after {

  width: 40px;

  height: 40px;

  border-radius: 0;

}

.timeline-rhombus ul li::after {

  clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);

}

.timeline-rhombus ul li div::before {

  bottom: 12px;

}

.timeline-star ul li::after {

  clip-path: polygon(

    50% 0%,

    61% 35%,

    98% 35%,

    68% 57%,

    79% 91%,

    50% 70%,

    21% 91%,

    32% 57%,

    2% 35%,

    39% 35%

  );

}

.timeline-heptagon ul li::after {

  clip-path: polygon(

    50% 0%,

    90% 20%,

    100% 60%,

    75% 100%,

    25% 100%,

    0% 60%,

    10% 20%

  );

}

.timeline-infinite ul li::after {

  animation: scaleAnimation 2s infinite;

}

@keyframes scaleAnimation {

  0% {

    transform: translateX(-50%) scale(1)

  }

  50% {

    transform: translateX(-50%) scale(1.25);

  }

  100% {

    transform: translateX(-50%) scale(1);

  }

}

6.响应迅速

咱们几乎准备好了!咱们要做的最后一件事是让咱们的时间线响应。 

首先,在咱们所说的“中等屏幕”(>600px 和 ≤900px)上,咱们只做了一个小的修改。具体来说,咱们减小了divs 的宽度。 

以下是咱们必须更改的规则:

@media screen and (max-width: 900px) {

  .timeline ul li div {

    width: 250px;

  }

  .timeline ul li:nth-child(even) div {

    left: -289px; /*250+45-6*/

  }

}

在这种情况下,时间线如下所示:

使用 CSS 和一点 JavaScript 构建垂直时间线  第9张

然而,在小屏幕上(≤600px),所有时间线元素看起来都一样;“奇数”和“偶数”之间没有区别div。同样,咱们必须覆盖一些 CSS 规则:

@media screen and (max-width: 600px) {

  .timeline ul li {

    margin-left: 20px;

  }

   

  .timeline ul li div {

    width: calc(100vw - 91px);

  }

   

  .timeline ul li:nth-child(even) div {

    left: 45px;

  }

   

  .timeline ul li:nth-child(even) div::before {

    left: -15px;

    border-width: 8px 16px 8px 0;

    border-color: transparent #F45B69 transparent transparent;

  }

}

在较小的屏幕上,时间线如下所示:

使用 CSS 和一点 JavaScript 构建垂直时间线  第10张

注意:在小屏幕上,咱们使用vw单位来指定时间线元素的宽度。这种方法背后没有任何特殊原因。咱们同样可以使用百分比或像素。

浏览器支持

该演示在最新的浏览器和设备中运行良好。然而,在 ios 设备上,时间线元素始终可见,而不是在其父元素进入视口时出现。 

从我的测试中,我发现在这些设备上window.innerHeight 和document.documentElement.clientHeight 属性不会返回实际的视口高度。具体来说,它们返回的数字要大得多。由于这种不一致,所有列表项都会在页面加载时收到in-view该类。 

虽然这不是什么大问题(您可能只希望在大屏幕上播放动画),但如果您对此问题了解更多或以前见过,请不要忘记通过社交媒体留下详细信息。

结论

在本教程中,咱们创建了一个响应式垂直时间线。咱们已经介绍了很多东西,所以让咱们回顾一下:

  • 通过使用简单的无序列表和 CSS 伪元素,咱们设法构建了时间线的主要结构。不过,这种方法的一个缺点是,正如我在另一篇文章中已经提到的,CSS 伪元素不是 100% 可访问的,因此请记住这一点。

  • 咱们利用从 Stack Overflow 上一个流行线程中提取的代码片段来测试列表项是否在视图中。然后,咱们编写了自己的 CSS 来为它们的子元素设置动画。或者,咱们可以使用 JavaScript 库或编写自己的代码。

我希望您喜欢本教程,并且您将使用此时间线作为构建有趣内容的基础。


文章目录
  • 1. html 标记
  • 2.添加初始 CSS 样式
  • 3. 时间线元素样式
  • 4.增加交互性
    • 在视图中添加类
    • 隐藏和揭示
  • 5.自定义圈子
  • 6.响应迅速
  • 浏览器支持
  • 结论