前端妹子问我positionfixe

北京痤疮医院哪些好 http://baidianfeng.39.net/a_yqhg/210111/8578752.html
背景

这两天公司一位妹子问我,“我这边调试的时候本地显示没问题,到手机端就有问题,该怎么办呢?”测试环境没问题到线上就有问题了?对此我也很纳闷。下图是复现的效果图,这个是一个用户选择组件,当点击按钮的时候,弹窗框可以选择用户,当点击按钮后蒙层并没有覆盖全屏。

选择用户按钮点击按钮后问题分析

组件代码

importReact,{useState}from"react";exportdefaultfunctionApp({children}){const[visivle,setVisivle]=useState(false)return(spanonClick={()=setVisivle(true)}{children}/span{visivle?divclassName="fixed".../div:null}/);}

我们知道,position:fixed在日常的页面布局中非常常用,在许多布局中起到了关键的作用。它的作用是:

position:fixed的元素将相对于屏幕视口(viewport)的位置来指定其位置。并且元素的位置在屏幕滚动时不会改变。

但是在某些特定场景下,指定了position:fixed的元素却无法相对于屏幕视口进行定位。

MDN[1]中有句话对这些特定场景做了解释:

当元素祖先的transform,perspective或filter属性非none时,容器由视口改为该祖先。

其实并不是本地不能复现,只不过这个表单是用户创建的,只有当该选择组件在Tab组件内部的时候%复现。在上面代码中,就是因为在Tab中使用了transform:translate3d(0,0,0)属性,所以会在该场景下失效。

失效的position:fixed

比如下面一个最简单的代码

divid="app"divclass="fixed"/dix/div

#app{width:px;height:px;transform:scale(1);}.fixed{position:fixed;background:blue;top:0;left:0;right:0;bottom:0;}失效的position:fixed

本来应该全屏的div,消失了,上述代码中transform:scale(1);也会导致position:fixed失效,那么,为什么会发生这种情况呢?

这就涉及到了StackingContext,也就是堆叠上下文的概念了。解释上面的问题分为两步:

任何非none的transform值都会导致一个堆叠上下文(StackingContext)和包含块(ContainingBlock)的创建。

由于堆叠上下文的创建,该元素会影响其子元素的固定定位。设置了position:fixed的子元素将不会基于viewport定位,而是基于这个父元素。

解决办法

那么要如何解决呢?我开发的是一个公共组件,总不能要求使用组件的父元素都不使用transform,perspective或filter这些属性吧?

是不是直接将弹窗插入到body下就可以了呢?

在React中提供了createPortal方法,该方法可以将子节点渲染到存在于父组件以外的DOM节点中

所以我们可以改一下组件代码:

importReact,{useState,useRef,useEffect}from"react";import{createPortal}from"react-dom";exportdefaultfunctionApp({children}){const[visivle,setVisivle]=useState(false);constnode=useRef();useEffect(()={node.current=document.createElement("div");document.body.appendChild(node.current);return()={if(node.current){node.current.remove();}};},[]);return(spanonClick={()=setVisivle(true)}{children}/span{visivlenode.current?createPortal(divclassName="fixed".../div):null}/);}

这样就可以解决position:fixed失效的问题,当然,因为在body元素下,可以使用position:absolute代替。

position:fixed的其他问题

position:fixed还有一些其他问题,比如在移动端实现头部、底部模块定位。或者是在position:fixed中使用了input也会存在一些问题,可以看下这篇文章:移动端web页面使用position:fixed问题总结[]

借用了前端胖头鱼的首图。以上就是本文全部内容,希望这篇文章对大家有所帮助,也可以参考我往期的文章或者在评论区交流你的想法和心得,欢迎一起探索前端。

[1]mdnposition:


转载请注明:http://www.aierlanlan.com/grrz/353.html