查看原文
其他

【第2711期】利用CSS实现超长内容滚动播放

QCY 前端早读课 2022-09-14

前言

阅读邮件看到一张菜单图,上面有一道” 成都口水鸡 “的菜,由于菜单字数限制就成了” 成都口水 “,所以平时在实现类似这种模块的时候就要考虑具体的交互方式了,那今天的案例分享就来源于此,有兴趣看看。今日前端早读课文章由 @QCY 分享。

正文从这开始~~

如果 UI 稿设计了一个单行定宽的样式,对于超过长度的内容,一般都会选择隐藏并展示省略号

这也是实现起来最简单,最常用的处理方法

但是在实际需求中,很有可能要求在不改变布局的情况下,用单行展示超长的文案且不能省略信息

这时候就可以考虑,用内容来回滚动来实现上述的效果

一、需求分析

先看最终效果

文案来回在指定区域内水平滚动,并且在头尾处停留一段时间

同时我们考虑做成通用的 css,所以尽可能的少使用固定值

二、功能实现

1. 基础布局

先构造一个基本样式

  • box 作为任意需要包含滚动组件 div 的 class,宽度、边框等个性化的 style 都应该在 box 上设置

  • scroll-wrap 作为滚动容器的通用 class

  • scroll-item 作为滚动内容的通用 class

// index.html <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<div class="box">
<div class="scroll-wrap">
<div class="scroll-item">
我是开头,我是中间我是中间我是中间,我是结尾 </div>
</div>
</div>
</body>
</html>
.box {
max-width: 15em;
border: 1px solid;
}

.scroll-wrap {
overflow: hidden;
white-space: nowrap;
}

2. 动效分析

如何实现来回滚动的效果呢?

其实只要实现内容的的两种状态,再加上 animation 让这两种状态来回切换。如果这两种状态的实现都使用的相同的属性,那么切换过程中自然就会加上动画效果

两种状态:

  • 「我是开头」靠左显示

  • 「我是结尾」靠右显示

我们从简单的部分开始实现, 先写一个来回切换状态的 animation 动画

.scroll-item {
animation: scroll linear 4s alternate infinite;
}

@keyframes scroll {
0% {
background: red;
}

100% {
background: yellow;
}
}

简单解释一下当前 animation 的属性

  • animation-name:所使用的 @keyframes 的名称 scroll

  • animation-timing-function:动画的速度曲线,linear 表示匀速

  • animation-duration:规定完成动画所花费的时间为 4s

  • animation-direction:是否应该轮流反向播放动画,alternate 表示在偶数次会反向播放

  • animation-iteration-count:定义动画的播放次数,infinite 表示无限次

animation 定义好了,然后开始实现最关键的部分,头尾靠边显示的两种状态

3. 头尾位置

如果只是单纯的实现其实很简单,直接用 position: absolute,再分别设置 left,right 即可

.scroll-wrap {
overflow: hidden;
white-space: nowrap;
position: relative;
height: 1.4em;

}

.scroll-item {
animation: scroll linear 4s alternate infinite;
position: absolute;
}

@keyframes scroll {
0% {
left: 0;
}

100% {
right:0;
}
}

但是由于 left、right 是不同的属性,所以状态改变过程中并没有动画效果

所以接下来我们的目标就是:如何用 left 实现 right: 0

思考 position: absolute 是如何实现居中的。就会比较容易联想到,可以通过 transform 属性来实现我们想要的效果

@keyframes scroll {
0% {
left: 0;
transform: translateX(0);
}

100% {
left: 100%;
transform: translateX(-100%);
}
}

再给 keyframes 加上两个动画节点,让文案出现头尾的停留

@keyframes scroll {
0% {
left: 0;
transform: translateX(0);
}

10% {
left: 0;
transform: translateX(0);
}

90% {
left: 100%;
transform: translateX(-100%);
}

100% {
left: 100%;
transform: translateX(-100%);
}
}

看起来已经比较完美了?

三、代码优化

回顾我们最开始定下的目标

并且考虑做成通用的 css,所以尽可能的少使用固定值

由于用了 position: absolute,导致需要额外给父元素指定高度。我们理想的状态应该是

  • 内容高度自然撑开

  • box 宽度大于内容时,不会发生滚动

  • box 宽度由内容撑开

使用我们现成的方案,只有不出现上述三种情况时才能正常展示

究其原因,在于宽高都无法自适应,而这主要是由 position: absolute 造成的。所以我们考虑换一个其他方案来实现两种状态。

不过再逐步说明一遍就过于繁琐了,这里直接列出最终代码。同时解释一些关键属性

// 个性化部分 ⬇️
.box
{
width: 15em;
border: 1px solid #ddd;
}

// 通用代码部分 ⬇️
.scroll-wrap
{
max-width: 100%;
display: inline-block;
vertical-align: top;
overflow: hidden;
white-space: nowrap;
}

.scroll-item {
animation: scroll linear 4s alternate infinite;
float: left;
}

@keyframes scroll {
0% {
margin-left: 0;
transform: translateX(0);
}

10% {
margin-left: 0;
transform: translateX(0);
}

90% {
margin-left: 100%;
transform: translateX(-100%);
}

100% {
margin-left: 100%;
transform: translateX(-100%);
}
}
  • max-width: 100%:保证自身宽度不超过 box

  • display: inline-block:目的是让 scroll-wrap 宽度自适应,可以被子元素撑开

  • vertical-align: top:设置完上面的属性之后,inline 会带上 1.x 的行高导致高度过大。设置 top 可以消除

  • float: left:为了让后续的 margin-left,transform 符合预期需要设置 float

  • margin-left:等效于上一个方案中的 left

效果符合预期,想改变布局时。只需要修改 box 即可(例如:「box 不设置宽度」的样式就是定义了 width: auto

至此,我们成功用纯 css 实现了超长内容的滚动播放~

关于本文
作者:@QCY
原文:http://qqqqqcy.top/#/article/821089/nyp16p

关于【CSS】相关推荐。欢迎读者自荐投稿,前端早读课等你来

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存