用electron框架写项目的时候由于需要用到element-ui这个组件库,于是顺手打开element-ui的官网界面,本想淘淘可用的组件,没想到先被element-ui手册首页新的屏幕滑动效果吸引。图片随页面滚动由蓝变红的效果让我觉得很有意思,于是奔着分析背后原理加自己手动实现的想法就写了这篇博客~
关键词:滚动触发、元素高度动态控制、CSS定位机制整理
官网效果预览
开始分析
🤔当我们开始滚动屏幕时,发现图片也随着滚动由蓝色渐变成了红色:
1.红色图片的高度与页面顶部距离窗口顶部的距离肉眼可见成正比
2.同时图片的变色完美衔接,那么两张图位置上应该是完全重合的,只是随着滚动隐藏的红色图片覆盖了蓝色图片
结合上述分析,我们可以总结出完成这样一个让人眼前一亮的动效背后对应的需求与需求对应的知识技能点:
1.html层面
:我们可以用一个大盒子套蓝色图片+红色图片盒子(红色盒子内部套红色图片的结构)便于控制两张图片的重合
2.css层面
:为了实现重合我们给大盒子的position属性相对定位relative,红色图片盒子的position属性给绝对定位。因为absolute元素将会脱离正常的文档流,所以其周围的元素将会忽略它的存在,实现红色图片盒子与同一级的蓝色图片重叠;同时top和left属性都赋值0,实现两张图片的完美重合。
3.js层面
:利用HTML DOM事件里的onscroll事件,在窗口元素(也就是window)滚动时触发赋值函数,让红色盒子的高度等于文档根节点距窗口顶部的高度,实现渐变效果
点亮小南瓜效果展示
这里我采用了小南瓜灰图和小南瓜彩图替代上述的蓝色图片和红色图片实现效果复刻。彩图盒对应上述红色图片盒子。
我的代码实现
html部分
<div class="container">
<h3 class="title">实现效果</h3>
<div id="jumbotron">
<img src="./grey.png" alt="灰色" id="grey-img">
<div id="jumbotron-colorful" style="height:0px">
<img src="./colorful.png" alt="彩色" id="colorful-img">
</div>
</div>
</div>
css部分
body {
height: 1500px;
background: #000;
}
.container {
margin: 100px auto;
display: flex;
flex-direction: column;
align-items: center;
}
.title {
color: #fff;
}
/* 大盒子position属性为相对定位relative */
#jumbotron {
width: 300px;
position: relative;
}
/* 让两张图片都占满各自的父容器 */
#jumbotron img,
#jumbotron-colorful img {
width: 100%;
}
/* 彩图盒position属性为绝对定位absolute, left和top属性均为0实现彩图盒铺满大盒子(也就是宽高都和大盒子相等),overflow:属性值为hidden实现溢出隐藏 */
#jumbotron-colorful {
transition: height 0.1s;
background: #000;
position: absolute;
left: 0;
top: 0;
overflow: hidden;
}
js部分
// 通过id拿到彩图盒封装成变量便于后续操作
const colorfulBox = document.getElementById("jumbotron-colorful");
let imgHeight = 0;
// 这里需要利用HTML DOM事件里的onscroll事件,在window元素滚动时执行后续js
window.onscroll = function () {
let scrolltop = null;
// 这里需要利用HTML DOM documentElement 属性(此属性为document文档根节点),并拿到其scrollTop属性(也就是根节点距窗口顶部的距离)
scrolltop = document.documentElement.scrollTop;
// 让彩图盒的高度等于scrollTop,就实现我们想要的效果啦
colorfulBox.style.height = scrolltop + 'px';
}
css定位机制整理(敲敲自己的黑板)
css定位机制
在整理定位属性之前,我们先来了解一下什么是css定位机制。根据w3c规定:
CSS 有三种基本的定位机制:普通流
、浮动(float)
和绝对定位(position:absolute/fixed)
。
除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 (X)HTML 中的位置决定。
这里提到的普通流根据我的理解和查询的资料就是正常的文档流,文档流指的是HTML中元素在计算布局排版的过程中,所有处于文档流中的元素会自动的从左到右(非块级元素),从上到下(块级元素)的排列规则。
【注:div、h1 或 p 元素常常被称为块级元素。这意味着这些元素显示为一块内容,即“块框”(即从上到下一块块排列)。与之相反,span 和 strong 等元素称为“行内元素”,这是因为它们的内容显示在行中,即“行内框”(即从左到右一个个排列)。
块级框从上到下一个接一个地排列,框之间的垂直距离是由框的垂直外边距计算出来。
行内框在一行中水平布置。可以使用水平内边距、边框和外边距调整它们的间距。但是,垂直内边距、边框和外边距不影响行内框的高度。由一行形成的水平框称为行框(Line Box) ,行框的高度总是足以容纳它包含的所有行内框。不过,设置行高可以增加这个框的高度。】
相对定位
设置为相对定位的元素框会偏移某个距离。元素仍然保持其未定位前的形状,它原本所占的空间仍保留。如果对一个元素进行相对定位,它将出现在它所在的位置上。然后,可以通过设置垂直或水平位置,让这个元素“相对于”它的起点进行移动。
如果将 top 设置为 20px,那么框将在原位置顶部下面 20 像素的地方。如果 left 设置为 30 像素,那么会在元素左边创建 30 像素的空间,也就是将元素向右移动。
浮动
由于浮动用的比较少,故不再二次整理,有需要可参考下列文章
绝对定位
绝对定位使元素的位置与文档流无关,因此不占据空间。这一点与相对定位不同,相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。普通流中其它元素的布局就像绝对定位的元素不存在一样:
所有 CSS 定位属性
!注意:Internet Explorer、Edge 15 以及更早的版本不支持粘性定位。 Safari 需要 -webkit- 前缀(请参见下面的实例)。还必须至少指定 top、right、bottom 或 left 之一,以便粘性定位(position:sticky;)起作用。
属性 | 使用举例 | 效果描述 |
---|---|---|
top | top:5px; | 把元素的上边缘设置在其包含元素上边缘之下 5 像素的位置 |
right | right:5px; | 把元素的右边缘设置在其包含元素右边缘向左 5 像素的位置 |
bottom | bottom:5px; | 把元素的底边缘设置在其包含元素底边缘之上 5 像素的位置 |
position | 规定元素的定位类型 | |
position:static; | 默认值。没有定位,元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 | |
position:relative; | 生成相对定位的元素,相对于其正常位置进行定位。因此,"left:20" 会向元素的 LEFT 位置添加 20 像素。 | |
position:absolute; | 生成绝对定位的元素,相对于 static 定位以外的第一个父元素进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。absolute 元素将会脱离正常的文档流,所以其周围的元素将会忽略它的存在。 | |
position:fixed; | 生成绝对定位的元素,相对于浏览器窗口进行定位。元素的位置通过 "left", "top", "right" 以及 "bottom" 属性进行规定。 | |
position:sticky; | position: sticky; 的元素根据用户的滚动位置进行定位。粘性元素根据滚动位置在相对(relative)和固定(fixed)之间切换。起先它会被相对定位,直到在视口中遇到给定的偏移位置为止 - 然后将其“粘贴”在适当的位置(比如 position:fixed)。 | |
position:inherit; | 规定应该从父元素继承 position 属性的值。 | |
clip | clip 属性剪裁绝对定位元素。 | |
clip:auto | 默认值。不应用任何剪裁。 | |
clip:inherit; | 规定应该从父元素继承 clip 属性的值。 | |
clip:rect(0px,60px,200px,0px); | 设置元素的形状。唯一合法的形状值是:rect (top, right, bottom, left) | |
z-index | z-index 属性设置元素的堆叠顺序。 | |
z-index:auto | 默认。堆叠顺序与父元素相等。 | |
z-index:inherit; | 规定应该从父元素继承 z-index 属性的值。 | |
z-index:1; | 拥有更高堆叠顺序的元素总是会处于堆叠顺序较低的元素的前面。并且仅能在定位元素上奏效。 |
我觉得不错的其他博主的相关分析
这一篇内容和评论区都可以一看,更推荐自己亲自试试:有详细列举不同情况下(如父元素不同box-sizing或position属性时的情况)举例
博主xiaobing_hope:position:absolute详解
下一次点亮技能树预告
٩(๑>◡<๑)۶终于!点亮了这一次的技能树:css定位整理,同时分析了个人觉得眼前一亮的效果。下次一起实现flex布局+css动画的登录动效~!下次见,希望离下次见面不会太远👋🏻 放一个下期预告: