在iOS中实现sticky header
经常在网页中看到这样一种效果,当页面滚动一段距离后,页面中的某个部分固定在一个区域(通常是头部导航),这种效果一般称为Sticky Header,如下图所示:
上述操作在Android系统中非常好实现,只需要监听onscroll事件并将实现逻辑写在里面即可,但iOS则不一样,它在页面scroll的时候,是不会执行代码的,直到页面停下来为止。
如此一来上面的效果就比较难实现了,因为不能实时更新导航条的位置,所以用户体验会与Android系统不一致。经过查阅资料,大概找了几种解决方案:
- 在iOS中同时监听onscroll与ontouchmove(然而尝试过后效果不好,特别是在屏幕上飞快地划一下然后把手指松开的时候);
- 自己模拟实现页面滚动,或者使用iScroll.js(感觉比较复杂没有试过);
- 使用postion:sticky属性(最终采用了这个,因为简单而且性能也好);
position:sticky是CSS3中新增的样式,它的表现相当于position:relative
和position:fixed
的集合,当目标区域在屏幕中可见时,它的行为就像position:relative;
而当页面滚动超出目标区域时,它的表现就像position:fixed
,它会固定在目标位置。比如:
.header{ position:-webkit-sticky; position:sticky; top:0 }
当header滚动出可视窗口外时,它就会执行position:fixed操作,并定位在top:0的位置。当header重新出现在视口内时,它执行position:relative操作,看起来就像元素仍然在原来的位置。
以上经过3GS真机测试并且测试通过。测试代码:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Sticky Header for iOS</title> <style> body{ margin: 0; color: #ffffff; } .banner{ height: 100px; background-color: #3b9a90; } .header{ height: 30px; line-height: 30px; background-color: #daac76; position: -webkit-sticky; position: sticky; top:0; } .content{ background-color: #557b4d; height: 900px; padding: 10px; line-height: 24px; text-indent:2em; } </style> </head> <body> <div class="banner">banner</div> <div class="header">navigation</div> <div class="content">A young man was getting ready to graduate from college. For many months he had admired a beautiful sports car in a dealer's showroom, and knowing his father could well afford it, he told him that was all he wanted. As Graduation Day approached, the young man awaited signs that his father had purchased the car. Finally, on the morning of his graduation, his father called him into his private study. His father told him how proud he was to have such a fine son, and told him how much he loved him. He handed his son a beautiful wrapped gift box. Curious, but somewhat disappointed, the young man opened the box and found a lovely, leather-bound Bible, with the young man's name embossed in gold. Angrily, he raised his voice to his father and said, "With all your money you give me a Bible?" He then stormed out of the house, leaving the Bible. Many years passed and the young man was very successful in business. He had a beautiful home and a wonderful family, but realizing his father was very old, he thought perhaps he should go to see him. He had not seen him since that graduation day. Before he could make the arrangements, he received a telegram telling him his father had passed away, and willed all of his possessions to his son. He needed to come home immediately and take care of things. When he arrived at his father's house, sudden sadness and regret filled his heart. He began to search through his father's important papers and saw the still new Bible, just as he had left it years ago. With tears, he opened the Bible and began to turn the pages. As he was reading, a car key dropped from the back of the Bible. It had a tag with the dealer's name, the same dealer who had the sports car he had desired. On the tag was the date of his graduation, and the words... "PAID IN FULL". How many times do we miss blessings because they are not packaged as we expected? Do not spoil what you have by desiring what you have not; but remember that what you now have was once among the things you only hoped for. Sometimes we don't realize the good fortune we have or we could have because we expect "the packaging" to be different. What may appear as bad fortune may in fact be the door that is just waiting to be opened.</div> </body> </html>
如果要在onscroll里实时执行逻辑操作,以上代码就力不从心了,只能找别的解决方案。