看到渣浪的查看文章或者查看大图有个效果:弹窗查看内容时,如果内容过长有滚动条,则滚动条会被放到body区滚动
什么意思呢?
看个图片,一般正常弹窗是有宽高限制的,如果内容过长则直接在弹窗中进行滚动
将滚动位置放到整个body中,让弹窗中内容自适应高度
这么做的好处自然很明显,body区域有更大的可视区域,来看看最后的效果
那具体是怎么实现呢
其实不算很难,各位看官可以先想一想能怎么搞
首先,得先弄一个基本的弹窗逻辑,为了简单,就直接操作了。可以自行封装
写个HTML结构
<button class="show-big-img" data-h="300">查看大图 h300</button>
<button class="show-big-img" data-h="3000">查看大图 h3000</button>
<div class="layer-shade"></div>
<div class="layer-wrap">
<a href="javascript:;" class="layer-close">×</a>
<div class="layer-content">
<p class="show-origin-img">
<a href="javascript:;">查看原图</a>
</p>
<div class="big-img">
<div class="big-img__item">我是图片</div>
</div>
</div>
</div>
将 layer-shade 看作遮罩,将 layer-wrap看作弹窗,将 layer-content 看作弹窗内容区,将 big-img__item 看作这里的长图片(长内容)
把样式写好
1 body {
2 &.layer-scroll-in-body {
3 overflow: hidden;
4 }
5 }
6
7 .layer-shade {
8 display: none;
9 position: fixed;
10 width: 100%;
11 height: 100%;
12 top: 0;
13 left: 0;
14 background-color: #000;
15 opacity: .15;
16
17 &.visible {
18 display: block;
19 }
20 }
21
22 @keyframes bounceIn {
23 to {
24 opacity: 1;
25 transform: scale(1);
26 }
27 }
28
29 .layer-wrap {
30 display: none;
31 z-index: 1;
32 position: fixed;
33 width: 70%;
34 height: 50%;
35 top: 100px;
36 left: 100px;
37 background-color: #000;
38 border-radius: 3px;
39
40 opacity: 0;
41 transform: scale(.3);
42
43 &.visible {
44 display: block;
45 animation: bounceIn .5s;
46 animation-fill-mode: both;
47 }
48
49 &.layer-scroll-in-body {
50 position: absolute;
51 height: auto;
52 }
53
54 &__wrapper {
55 overflow: auto;
56 position: fixed;
57 top: 0;
58 right: 0;
59 width: 100%;
60 height: 100%;
61 }
62 }
63
64 .layer-close {
65 position: absolute;
66 top: -16px;
67 right: -12px;
68 width: 24px;
69 height: 24px;
70 text-decoration: none;
71 color: #fff;
72 background: #999;
73 border-radius: 50%;
74 border: 3px solid #fff;
75 text-align: center;
76 line-height: 22px;
77 font-size: 22px;
78
79 &:hover {
80 background-color: #358eea;
81 }
82 }
83
84 .layer-content {
85 height: 100%;
86 overflow: auto;
87 }
88
89 .show-origin-img {
90 position: absolute;
91 top: 5px;
92 right: 20px;
93 font-size: 12px;
94
95 a {
96 color: #fff;
97 text-decoration: none;
98
99 &:hover {
100 text-decoration: underline;
101 }
102 }
103
104 }
105
106 .big-img {
107 display: flex;
108 justify-content: center;
109 box-sizing: border-box;
110 padding: 20px;
111
112 &__item {
113 display: flex;
114 justify-content: center;
115 align-items: center;
116 max-width: 100%;
117 width: 300px;
118 height: 3000px;
119 background-color: #c7bdb3;
120 }
121 }
最后加上JS操作逻辑
// 显示弹窗
function showLayer(onShow, onClose) {
var $body = $('body'),
$layerShade = $('.layer-shade'),
$layerWrap = $('.layer-wrap');
// 查看大图
$('.show-big-img').click(function() {
$layerWrap.find('.big-img__item').css('height', $(this).attr('data-h'));
// 显示前处理
if (onShow && typeof onShow === 'function') {
onShow($body, $layerWrap);
}
$layerShade.addClass('visible');
$layerWrap.addClass('visible');
});
$('.layer-close').click(function() {
// 关闭前处理
if (onClose && typeof onClose === 'function') {
onClose($body, $layerWrap);
}
$layerShade.removeClass('visible');
$layerWrap.removeClass('visible');
});
}
// 显示弹窗,并设置弹窗内容滚动区为body区
function showLayerScrollInBody(setPageScroll) {
// 模拟:确保显示弹窗前页面由垂直方向滚动条
setPageScroll && $('.show-big-img').css('margin-bottom', 2000);
showLayer(function($body, $layer) {
// body设置 overflow: hidden
$body.addClass('layer-scroll-in-body');
$layer
.addClass('layer-scroll-in-body')
// 弹出层增加一层父级
.wrap('<div class="layer-wrap__wrapper">');
}, function($body, $layer) {
// 关闭弹窗,则恢复
$body.removeClass('layer-scroll-in-body');
$layer
.removeClass('layer-scroll-in-body')
.unwrap();
});
}
showLayer();
/* showLayerScrollInBody(); */
/* showLayerScrollInBody(true); */
代码不算太复杂,如果到这里为止已经看懂的话,应该不需要再往下看了
一般的弹窗实现,需要设置遮罩层和弹窗的position为fixed,才能更好地保证页面有滚动条的时候位置不会出错。
fixed之后,弹窗的最大高度为视窗高度,若要使得弹窗的内容区直接显示出来,就必须设置为非fixed值,而弹窗不能少了定位,那就只能使用 absolute值了
但设置了absolute就无法计算页面有滚动条的时候的位置,所以需要给弹窗包裹一层父级,设置为fixed,则弹窗基于此父级来定位,相应的 top 和 left 值无需改变
$layer.wrap('<div class="layer-wrap__wrapper">');
&__wrapper {
overflow: auto;
position: fixed;
top: 0;
right: 0;
width: 100%;
height: 100%;
}
原先弹窗是设置了高度的,所以需要进行重置。推荐使用css类名来切换,方便维护
$layer.addClass('layer-scroll-in-body')
&.layer-scroll-in-body {
position: absolute;
height: auto;
}
在页面有滚动条的时候,还要注意页面的滚动条会不会和弹窗中的滚动条产生冲突,如
所以需要给body设置
$body.addClass('layer-scroll-in-body');
body {
&.layer-scroll-in-body {
overflow: hidden;
}
}
最后,记得在弹窗关闭的时候,还原相关的更改即可