具有绝对内容的可滚动 div

Ale*_*gão 7 html css reactjs

我有一个Carddiv,如果内容超过其高度,它应该显示滚动。我曾经overflow-y: auto这样做过。我正在尝试使用Select其中的 a ,并且选择菜单应该显示在卡的前面。菜单位置是absolute

问题是,即使使用position: absolute,菜单也会占用卡内的空间。使其可滚动。

图像

如果我从卡中删除溢出部分,它工作正常,但内容超出了它。我为它创建了一个沙箱:

https://codesandbox.io/s/position-absolute-inside-overflow-y-9kppcy?file=/src/App.js

我尝试过的其他事情

  • 显示SelectMenu门户内部。

    • 到目前为止,我得到了更好的结果,但是当窗口滚动时,菜单固定在屏幕上。
  • 从卡片中删除溢出,将其添加到CardBody元素中,并将选择保留在其外部。

    • 确实很神奇,但是对于深层嵌套的 div,很难将其保留在每个溢出元素之外。
    • 如果选择位于模态内部,则不起作用(因为模态应该有滚动)。

更多细节

  • 我正在使用react-select来创建我的选择,但问题严格来说是css和html。

这可能是一个常见问题,但我找不到解决方案。

Ter*_*rry 1

我认为您使用 React Portal 的解决方案实际上很有意义,但您只需要更多一点技巧来定位元素。

{showMenu &&
  createPortal(
    <div className="SelectMenu" style={menuStyle}>
      I'm the menu.
    </div>,
    PORTAL_HOST_NODE
  )}
Run Code Online (Sandbox Code Playgroud)

menuStyle只是一个由 返回的计算值useMemo,它只是我们需要应用来定位菜单的 CSS 样式。您想要的是要使用的菜单position: fixed,然后只需使用触发元素(在本例中为“打开选择”按钮)的、 和top属性left来定位该元素。widthheight

为了确保在视口滚动时更新位置,您还需要跟踪该window.scrollY值:

const [scrollY, setScrollY] = useState(window.scrollY);

useEffect(() => {
  const onScroll = () => setScrollY(window.scrollY);
  window.addEventListener("scroll", onScroll);

  return () => {
    window.removeEventListener("scroll", onScroll);
  };
}, []);
Run Code Online (Sandbox Code Playgroud)

我发现您有一个手动0.5rem偏移量,您希望选择菜单远离其触发元素。我们可以将其存储为 CSS 变量:

{showMenu &&
  createPortal(
    <div className="SelectMenu" style={menuStyle}>
      I'm the menu.
    </div>,
    PORTAL_HOST_NODE
  )}
Run Code Online (Sandbox Code Playgroud)

然后,就像前面提到的那样设置其他代码。一些注意事项:

  • 使用 CSS 变换,以便我们可以处理子像素放置(而不是顶部/左侧)
  • 设置宽度,以便您的选择菜单遵循其触发元素的宽度
  • 使用上面设置的CSS自定义属性来计算CSS变换的y轴值
const [menuTriggerElementRect, setMenuTriggerElementRect] = useState(null);

const toggleMenu = useCallback((e) => {
  setShowMenu((old) => !old);
  setMenuTriggerElementRect(e.currentTarget.getBoundingClientRect());
}, []);

const menuStyle = useMemo(() => {
  if (menuTriggerElementRect === null) return {};

  const { top, left, width, height } = menuTriggerElementRect;
  return {
    transform: `translate(${left}px, calc(${
      top + height - scrollY
    }px + var(--top-offset)))`,
    width: `${width}px`
  };
}, [menuTriggerElementRect, scrollY]);
Run Code Online (Sandbox Code Playgroud)

请在此处查看更新的 CodeSandbox 示例:

编辑位置绝对位于溢出 Y 内(分叉)