惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

J
Java Code Geeks
S
SegmentFault 最新的问题
V
Visual Studio Blog
人人都是产品经理
人人都是产品经理
阮一峰的网络日志
阮一峰的网络日志
腾讯CDC
Stack Overflow Blog
Stack Overflow Blog
博客园 - 【当耐特】
Recent Announcements
Recent Announcements
I
InfoQ
U
Unit 42
博客园_首页
GbyAI
GbyAI
Hugging Face - Blog
Hugging Face - Blog
罗磊的独立博客
博客园 - 叶小钗
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
D
DataBreaches.Net
aimingoo的专栏
aimingoo的专栏
月光博客
月光博客
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - 聂微东
T
Tailwind CSS Blog
量子位

一颗小树

周更的第 100 篇 改变阅读方式 宝贵的人生建议 小树的工具库 2023 读《重构》有感 仅需 10 分钟,用 GPTs 实现文章总结助手 高质量的需求交付 产品始于问题,而不是解决方案 如何更好地休息 最优解人生 与体重斗,其乐无穷 结构化 prompt = 数字员工? 持续创作的法门 如何降低知识焦虑 7 月思维碎片 N 倍生产力提升:我的 AI 助理 Indie Hacker,互联网打工人的下一个出路? 如何成就伟大事业 夏日碎片 小报编辑的自我修养 一颗小树 #49 投入真实生活 一颗小树 #48 过年杂记 一颗小树 #47 我的人生信念(2023) 一颗小树 #46 回本就卖 一颗小树 #45 规划和落地 小树的 2022 年终总结 一颗小树 #44 构建高质量信源 一颗小树 #43 我的 2022 书单 一颗小树 #42 阳了怎么办 一颗小树 #41 一人企业
移动端实现内滚动的4种方案
也树 · 2016-12-02 · via 一颗小树

如果在一个区域内只允许部分区域产生滚动的效果,而其余部分不能移动,你会采用什么方法呢?

作者:Icarus 原文链接:移动端实现内滚动的 4 种方案

首先我们可以把这个需求分解为两个小的问题来解决。

  • 部分区域固定
  • 其余区域滚动

部分区域固定

  1. 为页面的 body 部分设置height: 100%以及overflow: hidden,即禁用页面原生的滚动,保证只会显示一屏的内容。
  2. 固定区域采用绝对定位。

其余区域滚动

核心属性overflow-y

mdn 对于 overflow-y 的定义 The overflow-y property specifies whether to clip content, render a scroll bar, or display overflow content of a block-level element, when it overflows at the top and bottom edges. overflow-y 属性指定或是裁剪内容并且渲染一个滚动条,或是当块级元素在其顶部或底部溢出时显示溢出的内容。

简单来说,overflow-y属性在垂直方向上存在溢出的时候,通过设置不同的值会产生不同的表现。为了实现滚动功能我们需要将该属性设置为scroll,之后,无论块级元素的内容是否溢出,浏览器都会生成一个滚动条并且隐藏容器中内容溢出的部分,只有在滚动之后才会显示。

举个例子:

.test{
	width: 200px;
	/* 关键样式 */
	height: 200px;
	overflow-y: scroll;
	/* 以下无关样式 */
	background: #f14c5c;
	color: #fff;
}
<div class="test">
	这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容
	这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容
	这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容
	这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容
</div>

效果如下:

这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容这里面只是一段测试的内容

通过刚才的例子我们可以得出结论,只要限制块级元素的高度,自然就可以实现只有该元素的内容可滚动而不影响其它内容。但是在实现过程中遇到了新的问题,如何实现对设计图的精确还原?设计图如下:

设计图

整个弹出框高度是随页面高度自适应的,标题部分和底部按钮部分位置是固定的,中间列表需要占满剩余高度,并且内容可滚动。整个弹窗被最外层 div 包裹,底部按钮相对于它进行定位。经过思考后,尝试了四种方案,分享给大家。

方案说明

我们需要确定的核心问题就是中间内容的高度,也即是height在不同尺寸屏幕下的精确高度。

vh

相对于视口的高度,视口被均分为 100 单位,即 1vh 等于视口高度的 1%。

vh-caniuse

但是 vh 单位对低版本安卓和 ios 支持不够好,微信浏览器 X5 内核不支持,虽然已经升级到 blink 内核,但是为了确保万无一失,放弃采用这种方案。另外也无法精确控制和底部按钮边距。

height 百分比

和 vh 类似,无法精确控制和底部按钮的边距,自适应效果不好。

calc

对于以上两种方案的存在的问题,calc计算属性可以很好的解决,只需要设置height:calc(100% - 60px),就可以精准的占满中间部分,并且保持和底部按钮的边距。

calc-caniuse

可惜的是对于低版本的安卓浏览器、ios 浏览器包括微信浏览器在内的主流浏览器支持都不好,依然只能弃用。 如果兼容性再好一点的话,calc 方案应该是最好用且最优雅的一种实现方式。

js

单纯的使用 css 无法实现,就只能借助 js 来动态计算内容所需要的高度来进行设置。同时这种方法也几乎不会遇到兼容性的问题,是对优雅降级的一种实践。

题外话

隐藏难看的滚动条。

scrollbar 如果直接设置overflow-y:scroll在 ios 下始终会出现很丑的滚动条,我们可以对该元素设置以下属性:

margin-right: -20px;
padding-right: 20px;

对滚动条进行一个小小的 hack,它就再也不会出现了,用户交互时会有和原生滚动一样的感觉,体验更佳。

@prototype 经大大提醒,设置 webkit 浏览器的私有属性::-webkit-scrollbar能更灵活的控制滚动条,在此感谢。如果只需要隐藏,如下代码即可:

::-webkit-scrollbar{
	display: none
}

虽然移动端的浏览器 webkit 内核居多,不过还是要在真机测试后再得出结论,如果有些浏览器不支持这个属性的话,依然可以使用上面的小 hack。

-webkit-overflow-scrolling: touch

在 ios 设备中,利用overflow来模拟滚动会出现卡顿的情况,可以通过设置-webkit-overflow-scrolling: touch来解决,原因是设置后 ios 会为其创建一个UIScrollView,利用硬件来加速渲染。

这个问题本身并不复杂,甚至需求更改后,实现变的非常简单。但是希望能通过这个小例子能让每一个前端人在思考需求时都能够尽可能的去想更多样的方法来解决问题,即使因为兼容性或其它原因暂时无法实现,在这个过程中获得的成长也是非常有益的。