当前位置: 首页 > Web前端 > HTML5

纯CSS解决H5布局中的天花板和底部

时间:2023-04-05 12:50:58 HTML5

Demo地址(手机打开):https://closertb.site/Klotski...Demo源码:https://github.com/closertb/k...原文:https://github.com/closertb/c...想提自己要什么的产品最近提出了一个需求,准确的说是迭代需求:加个headeroverview(类似下图),让用户更好的观察营销变化,故事的开头悄悄埋下了伏笔。以前这个页面只是一个评论列表(可以通过上拉加载)。为了使数据更具可读性,列表的表头采用了固定的布局。但是,我添加这个概览的时候,并没有提到产品,所以我干脆把listheader改成了相对布局,ok,测试一下。但是第二天,发现上拉加载了很多数据。列表头部被推上去之后,如果想再过滤,就得再次向上滑动列表才能看到。这次体验非常差。于是同事说是问问产品,还是把overview加overview搞定。我的第一反应是,我怕提了之后,产品只会让我固定过滤列表的表头,只关注那个。然后就是下面的对话:果然,你怕什么,你来干什么。但正如同事所说,我不得不接受我提出的需求,眼中含着泪水。经过后面提到的评论,加上了stickysolution,确实是最优解。下面部分吊顶的代码是页面的dom结构Thisisanoverviewheader

这是列表的头部

可过滤

下面是一个滚动列表

{arr.map(({key,label})=>{label})}
JS实现因为页面本身有滚动事件监听,所以第一个想到的是用JS来完成,但是已经下班了,又是周五。我觉得5分钟内做不完,就跑了上去。现在让我们尝试用JS来实现它。我们先想一想:监听页面的滚动。当ul元素的top距离页面顶部大于title的高度时,添加cssclass,使滤头吸顶;当ul元素顶部距离小于等于title高度时,删除添加的类,取消过滤头天花板JS代码useEffect(()=>{constdemo=document.querySelector('#demo');constcontent=document.querySelector('#content');consttitleHeight=document.querySelector('#title').clientHeight;letfixed=false;demo.addEventListener('scroll',(e)=>{//添加上限if(!fixed&&e.target.scrollTop>=titleHeight){fixed=true;content.classList.add('with-fixed');}//取消上限if(fixed&&e.target.scrollTop100vh){title.hide();那么如何隐藏概览表头,过滤出视口之外的表头和列表呢?filterBarHeight+listHeight=100vh当用户向上滑动时只需要内容(filterheader和list)刚好是一个视口高度(100vh),overviewheader只是隐藏,filterheader只是吸顶,这样实现withCSSSomethinglikethis://不是完整的代码,详情请看demo:.demo{:global{.title{height:15vh;行高:15vh;文本对齐:居中;border-bottom:1PXsolid#eee;背景颜色:#fff;}.filter-bar{高度:15vw;背景色:#888;显示:弹性;对齐项目:居中;}.list{最大高度:计算(100vh-15vw);;//这里的设置很重要overflow:scroll;背景色:rgba(127,255,212,.8);}CSSSticky的优化实现css中有一个不常用的position属性值:sticky;摘自MDN官方文档:一个元素按照正常的文档流定位,然后相对于它最近的滚动和最近的块级祖先,包括表格相关的元素,根据top、right、底部和左侧。粘性定位可以被认为是相对定位和固定定位的混合体。元素相对定位,直到它们超过某个阈值,然后固定。这里我们对JS解决方案进行更改。我们只需要将filter-bar的定位属性改为sticky定位即可,去掉对JS的依赖;.demo{最大高度:100%;溢出:滚动;.filter-bar{position:sticky;顶部:0;}}demo类作用于最外层的dom(),表观高度为100vh,当内容超出高度时,为滚动;filter-条形元素采用粘性定位。当与demo元素的高度距离大于0时,采用相对定位,即以普通文档流的形式定位;当高度小于等于0时,采用固定定位,实现吸顶效果。对比一下,是不是觉得css很简单,稍微设置一下就搞定了,但是需要一点经验(yun)测试(qi)才觉得内容高度刚好是100vh。经常写H5,粘性解决方案相信对新手来说是粘性的。其实不仅简单,而且和JS相比至少有两点优势:如果JS只是如上,直接把滤头的定位改成固定定位,眼力好的人其实能感觉到列表跳转,即列表会突然上移filterBar的高度,填满filterhead,离开正常的文档流;(解决方法是在filterhead外面多放一层dom,并给定一个固定的高度,这样filterhead就脱离了正常的文档流,但是高度还在);在使用JS操作Dom元素的重排时,面试官年年说的重绘重拍就不多说了,比CSS实现更耗性能;当然viewport解决方案也有ios手机由于safari的兼容性问题,滑动时头部和底部的可见度会发生变化,所以当Bar可见时,实际100vh高于可见高度屏幕,这将导致天花板的头部被挡住。至此,虽然网上有很多关于高度的说法:-webkit-fill-available;,但是对于这个场景是无效的;但是只要依赖100vh,就会面临这样的困境。Safari太奇葩了,下一个IE就是了。经过上面的分析,100vh在IOSsafari上的致命问题会让100vh这个纯CSS方案淡出。但是对于PC页面,或者你和我一样,你要写的页面是跑在APP里的(就是没有栏),那么这个方案是可行的。所有的计划都需要具体的场景和具体的分析。没有人天生完美。这只是为了改进一种思维方式和获得见识。粘性解不依赖100vh,可以100%写入,所以没有这个顾虑,所以相比较而言,最??优解是粘性的;但是height:100%是个无底洞,需要从html标签开始,一直写Writes到一个有滚动的容器元素。如果你对重绘和重排感兴趣,建议看Chrome官方博文:浏览器四部分弹性底部是吸底的。当页面内容大于100vh时,Footer处于正常文档流中,使内容可见区域变大,不会因为内容太少而影响外观。看图:没有像第一张图那样的定位还有很多人,因为他们坚信自己的网站内容不会不足,但过去比较普遍的做法是固定定位在底部。弹性吸底采用min-height加绝对定位,实现非常简单。核心代码不超过5行css:body{position:relative;最小高度:100vh;}页脚{宽度:100%;位置:绝对;bottom:0;}原理是内容区域的最小高度是一屏,然后bottom是相对屏幕绝对定位的;当内容增加时,高度大于100vh,因为依赖bottom:0;,所以会一直吸底,这就是trick。对于这种场景,height:-webkit-fill-available是有效的。有关-webkit-fill-available的更多信息,请参阅[https://allthingssmitty.com/2...];综上所述,vh确实是个好东西,可以解决移动端的适配问题;sticky(通常写PC的人)的非流行属性值得花时间学习。我个人认为,作为一个合格的前端,CSS还是必不可少的技能。偶尔看看张旭新还是很有必要的;不要太依赖JS,这不是不可以,但是好钢要用在刀刃上。