看到渣浪的查看文章或者查看大图有个效果:弹窗查看内容时,如果内容过长有滚动条,则滚动条会被放到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; } }
最后,记得在弹窗关闭的时候,还原相关的更改即可