【转】内滚动布局

许多桌面软件都采用内滚动布局,交互性比较强的的web页面(如:各种后台管理系统)进行桌面软件化可以使得交互操作更加方便快捷。

一、什么是内滚动布局?

内滚动布局的布局效果:顶部和左侧菜单栏固定,不随页面滚动;右侧内容区域相对于页面的其他部分滚动

  • 『内滚动布局』的主滚动条 位于 html 下的某个元素上(即位于某个需要滚动的区域上);

  • 而『传统滚动布局』的主滚动条 则位于 html 上;

内滚动布局
传统滚动布局

二、为什么会有内滚动布局?

随着显示器设备越大越宽越密,以及现代web技术的发展。web站点已经开始有了从传统的瀑布式网页向类桌面软件风格站点转变的趋势

比方说,QQ音乐的首页目前是这样子的:

inner_scroll_3.jpg

以后可能就会变成这样子:

inner_scroll_4.jpg

我们可以局部放大,会发现,是个实打实的内滚动布局。

inner_scroll_5.png

不仅是QQ音乐,其他很多桌面软件都是这种内滚动布局,比方说QQ软件管家等等。

inner_scroll_6.png

由此可见,一旦强交互的传统web页面桌面软件化,内滚动布局是绕不开的一堵墙,了解之还是很有必要的。

三、如何实现内滚动布局?

既然是内滚动,就有必要干掉浏览器原生<html>的滚动条,这个很简单:

html { overflow: hidden; }

“然后呢?”我想了想,好像然后就没有“然后”了,让一个div容器滚动就完事了。

然而,事非经过不知难,原理虽然简单没说头,但是细节操作还是有些上手成本的。

为了更好理解,我们拿实例说话。最近半年一直在参与企业QQ账户中心改版的项目,你可以看成是企业后台管理系统。这里有几个关键字,一是企业,二是管理系统。

1. 企业

这里为什么要强调是“企业”呢?因为企业产品的用户一般都是购买了企业QQ产品的企业的员工,有一定IT技能的人。因此,用户的浏览器的现代感就比Qzone用户强不少。下图为同事在2015-05-20这个爱意满满的日子拉的userAgent数据:

inner_scroll_7.png

如果我们将支持CSS3 animation的浏览器称之为现代浏览器,可以发现,企业产品的用户,70%~80%的用户都是使用的现代浏览器。亲们,近8成的用户都是使用现代浏览器,这就意味着,企业产品其实可以作为现代web技术的试验田,在为用户提供更好体验更高质量产品的同时,为日后其他产品的现代化改造提供了宝贵的借鉴经验。而本文的内滚动布局,就是万千经验中的一小个。

2. 管理系统

“管理系统”意味着站点以强交互为主,会有很多类似办公软件的交互操作在里面。如果是更偏重浏览的站点,例如企业QQ官网,显然,传统的垂直瀑布式的网站是更适合的,滚动浏览,再滚动,再浏览。但是,企业管理系统如此庞大,操作如此频繁,交互如此之多,传统的上下式网站显然很难让用户用得非常得心应手。

下图为以前企业QQ账户中心组织结构页面(测试页面)的真容:

inner_scroll_8.png

看着此页面,立马让我想起了6年前刚毕业那会的青葱岁月,那时候的页面的基本上就是这样的调调,小小的空间里有着小小的世界。时代发展,再辉煌的过去,如果没有改变,终将会被埋汰。

正是由于以上两点,设计师设计的时候,大胆创新,设计成了全屏自适应、半响应、类PC软件风格(内滚动)的管理站点,下图为上面老页面同样数据的新测试页面截图:

inner_scroll_9.png

回到内滚动布局本身。

新版企业账户中心全站,顶部以及左侧固定,不跟随滚动,右侧主体内滚动,如何实现呢?

由于企业产品不用管0.4%的IE6用户,因此,事件就变得简单地多了。我们可以利用绝对定位元素的拉伸特性,使内滚动容器高度自适应匹配

HTML主结构示意如下:

body
 -- page
    -- header
    -- side
    -- content

其中++page扮演传统页面<body>的角色。这是一个预留设计,用于应对:为了满足某些功能或交互体验需要,一个页面同时出现多个类似结构页面的情况++。或者这么说吧,把所有页面内容放在一个page中,此时page就好比一个可以移动的房子,回头你跳槽来腾讯了,房子可以一起带过来,原来的位置可以被其他房子代替。但是,你如果直接放在<body>中,由于<body>只能是一个,不动产,此时想要做整体迁移,难度就较大,同时项目几乎成型,全局修改成本高高风险大。不过凡事都有两面性,这样的折腾可以减少你白头发的数目,因为你会因操劳过度头发直接脱掉的。

page相关CSS如下:

.page { position: absolute; top: 0; right: 0; bottom: 0; left: 0; }

应该很好理解,绝对定位,++满屏拉伸++,等同于:

.page { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }

由于省了好几个字节,所以我舍弃了IE6使用了上面写法。

对于固定的头部 header 或者固定的侧边 side, 你可以使用语义明确的position:fixed定位,或者直接使用position:absolute,因为滚动容器跟他们平级,所以,absolute其实就是fixed效果。

讲到这里就不得不说点题外话,很多人会遇到移动端position:fixed的底部输入框定位的头疼问题,如何解决?就是使用本文介绍的内滚动布局,然后底部使用position:absolute模拟fixed效果。代码方面,同样就是拉伸拉伸:

```
.header { height: 62px; position: absolute; top: 0; right: 0; left: 0; }
.side { width: 200px; position: absolute; top: 62px; bottom: 0; left: 0; }
```

最后就是高能的content, 还是一样的套路:

.content { position: absolute; top: 62px; right: 0; bottom: 0; left: 200px; overflow: auto; }

主体内容全部都在content里面玩耍。于是,一个高宽均自适应浏览器窗体的内滚动布局就成型了。

四、内滚动布局的赏与罚

我们站在上帝视角审视一下内滚动布局,本质上就是滚动容器的迁移,职能下发。所以绝大部分情况下,跟我们平常玩转页面的路数没什么区别。

但是,毕竟江山易主,差异还是存在的。

最简单的例子就是对滚动事件的影响。很多滚动插件,包括以前的脚本,我们可能都是这么写的:

$(window).scroll(function() {
    // 跟我一起翻滚吧,骚年……
});

但是,在内滚动布局下,由于滚动的容器不是 window 窗体,不是<html>元素,因此,上面滚动事件八辈子都不会执行。我们需要调整,由于现在,页面的主滚动条是 .content, 因此,我们可以:

$(".content").scroll(function() {
    // 跟我一起翻滚吧,骚年 again……
});

你以为事情就这么完了吗?太天真了!以前我们的滚动条是跟浏览器上边缘是靠在一起的,但是,自从变成了内滚动,滚动条是跟网站公用头部下边缘排排站,这会造成什么问题呢?就是一些offset的计算要发生一些变化。举个例子,我们希望表格头部操作区域有类似position:sticky效果,也就是视区内一起翻滚,要被滚出去的时候,fixed固定,不跟随。

inner_scroll_10.png

此时,我们的最大滚动高度值,就需要把网站头部的高度考虑进去(传统窗体滚动不需要,因为值是0):

var maxScrollTop = $("#tableHeader").offset().top - $(".header").height();

以上这个,我们可以称之为“变化”,与原本的实现相比无功无过,一种变化一种转移。实际上,内滚动布局还会带来带有质变性质的一些特性。

无法滚动的弹出层

基本上,是个像样的 web2.0 网站都会有弹框 web 组件,一个黑色半透明的 overlay 层,上面摇曳着弹框面板,例如这样的:

inner_scroll_11.png

++对于黑色半透明覆盖层++,

传统实现是这样的:如果要兼容IE6浏览器,一般是absolute绝对定位,高度由JS计算赋予;如果不需要管IE6, 则可以使用fixed固定定位。

然而,在内滚动布局下,“赏”就出来了,就算需要兼容IE6浏览器,黑色半透明高宽100%自适应覆盖也不需要任何JS计算的帮助,也不需要监听window的resize事件,直接CSS就可以搞定。很简单:

.overlay { position: absolute; left: 0; top: 0; width: 100%; height: 100%; }

为啥一行CSS就能搞定所有场景?因为使用的是内滚动布局,如下图示意,屏幕就这么高,滚动在里面,自然自适应:

inner_scroll_12.png

看上去是内滚动布局带来的一个小小的“赏”,但是,实际上,埋下了一个不小的“罚”。

随意改变滚动容器最大的问题在于,当存在覆盖层的时候,会影响背后页面内容的滚动。

100%尺寸的position:absolute/fixed的覆盖层,会覆盖任何非<html>元素(包括<body>)(包括这些元素的滚动条),因此,只要覆盖+滚动容器改变,页面就无法滚动。

内滚动布局是典型的改变浏览器默认滚动容器的布局,自然覆盖层一出现,就没法滚动。不过这也没什么,对吧,弹框出现时候,页面背景没法滚也挺好的。

但是,麻烦的事情是,如果弹框自身高度很高,却又没法滚动呢(浏览器可用高度700像素,弹框有900像素高)?

传统布局下的弹框,如果高度很高,直接设置弹框容器position:absolute就可以愉快地上下翻滚了。但是,在内滚动布局下,弹框根本就不在滚动容器里面,翻滚一说从何谈起?

大危机!怎么办!?

我们新版企业账户中心就遇到这个问题,我是这么解决的——overlay和dialog合体。

合体与滚动

合体是什么意思呢?基本上,90%+的弹框组件,半透明覆盖层overlay和弹框dialog是两个并列的兄弟关系的独立的元素,这种设计的好处在于overlay组件可以复用。实际上,我们要实现一个弹框效果,只要一层div标签就可以了,核心就是使用兼容的RGBA背景色技巧,然后弹框HTML放在里面:

.container {
    position: absolute; top: 0; left: 0; bottom: 0; width: 100%;
    background-color: rgba(0,0,0,.5);
    filter: progid:DXImageTransform.Microsoft.gradient(startcolorstr=#7F000000,endcolorstr=#7F000000);
    overflow: auto;
}
:root .container {
    /* IE9 无 filter */
    filter: none;
}

HTML结构示意如下:

<div>
    <dialog></dialog>
</div>

此时,弹框在一个可滚动的容器之中,妈妈再也不用担心我不能愉快地翻滚了!

inner_scroll_13.gif

五、结束语

由于传统窗体滚动已经深入人心,所以我们可能会觉得内滚动布局似乎有些坑;但是,如果当年是内滚动布局天下,我们又该如何看待新兴的窗体滚动布局呢?然后,从产品的角度讲,内滚动布局在操作如此频繁的重交互项目中所带来的交互体验上的改进,要远比经验不足带来的额外开发成本要大很多很多

我相信,这种交互形式以及web布局上的创新一定会带来很多正面的反馈和积极的影响,产品即将上线,我们可以拭目以待。

内滚动布局,更现代,更移动,如果您的项目合适,不妨也试试这种看似新颖的布局方式。

转自:优设
原文:腾讯ISUX
作者:zhang xinxu

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,389评论 25 707
  • 内容抽屉菜单ListViewWebViewSwitchButton按钮点赞按钮进度条TabLayout图标下拉刷新...
    皇小弟阅读 46,700评论 22 664
  • 三年前,他在街角遇到了无家可归的她。 他问 『我带你回去好不好?』 她用清澈的眸看他『好』 她开始在他的戏班里每天...
    车贤凯阅读 176评论 0 1
  • 我喜欢在黑暗里待着 我不会爱也不会表达 我没有安全感 一丁点关注我就会心跳加速 伤害带给我的看起来更刻骨铭心 或许...
    七萧萧阅读 199评论 0 1