前端妹子问我 position fixed 失效问题该如何解决?

sxkk20082年前知识分享128

背景

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

点击按钮后

问题分析

组件代码

import React, { useState } from 'react'

export default function App({ children }) {
  const [visible, setVisible] = useState(false)
  return (
    <>
      <span onClick={() => setVisivle(true)}>{children}span>
      {visible ? <div className="fixed">...div> : null}
    >
  )
}

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

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

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

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

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

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

失效的 position:fixed

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

<div id="app">
  <div class="fixed">dix>
div>
#app {
  width: 100px;
  height: 100px;
  transform: scale(1);
}
.fixed {
  position: fixed;
  background: blue;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
}

失效的 position:fixed

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

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

  1. 任何非 nonetransform 值都会导致一个堆叠上下文(Stacking Context)和包含块(Containing Block)的创建。

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

解决办法

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

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

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

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

import React, { useState, useRef, useEffect } from "react";
import { createPortal } from "react-dom";

export default function App({ children }) {
  const [visivle, setVisivle] = useState(false);

  const node = useRef();

  useEffect(() => {
    node.current = document.createElement("div");

    document.body.appendChild(node.current);
    return () => {
      if (node.current) {
        node.current.remove();
      }
    };
  }, []);
  return (
    <>
      <span onClick={() => setVisivle(true)}>{children}span>
      {visivle && node.current
        ? createPortal(<div className="fixed">...div>,node.current)
        : null}
    >
  );
}

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

position:fixed 的其他问题

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

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

相关文章

用AI智能识别技术助力未来发展

用AI智能识别技术助力未来发展

  随着人工智能技术的飞速发展,AI智能识别正成为推动社会进步的重要力量。它通过模拟人类的认知过程,实现机器对图像、语音和文字的理解与处理,为各行各业带来了前所未有的创新。 ...

使用 Next.js 和掘金 API 打造个性博客

文章为稀土掘金技术社区首发签约文章,14 天内禁止转载,14 天后未获授权禁止转载,侵权必究!阅读本文,你将收获:通过 chrome 调试工具获得掘金 api学会使用 Next.js 服务端渲染学会使...

AI人工智能网站的重要性及应用领域:连接世界的知识和信息平台

AI人工智能网站的重要性及应用领域:连接世界的知识和信息平台

  随着科技的不断发展,人工智能(AI)正逐渐渗透到我们生活的方方面面。AI技术的普及使得各类AI人工智能网站成为了人们获取信息、进行交流和实现自我提升的重要平台。在这篇文章...

阿里人脸识别:开创人工智能时代的身份验证进程

阿里人脸识别:开创人工智能时代的身份验证进程

  近年来,随着科技的不断进步和人工智能的快速发展,人脸识别作为一种快速、准确的身份验证技术,正逐渐渗透进我们的日常生活。作为国内的互联网巨头,阿里巴巴也不甘落后,旗下的阿里...

人工智能的新特征:深度学习技术的革命与应用前景

人工智能的新特征:深度学习技术的革命与应用前景

  人工智能技术在这几年里的迅猛发展,深度学习作为其中的重要支柱之一,正引领着人工智能的新特征。深度学习技术以其卓越的性能和广泛的应用领域,成为当前人工智能研究的热点之一。 ...

人工智能为艺术创作注入新生命

人工智能为艺术创作注入新生命

  随着科技的日新月异,人工智能技术越来越普及。在艺术创作领域,AI绘画已成为一个备受瞩目的领域,它不仅降低了艺术门槛,带来了更多的艺术可能性,还推动了艺术形式的不断创新和发...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。