【问题标题】:fixed vertical positioning of css within an iframe修复了 iframe 中 css 的垂直定位
【发布时间】:2022-04-13 00:44:20
【问题描述】:

我试图让我的底部标题贴在我的 iframe 应用程序内的屏幕底部,并且即使页面正在滚动,它也始终显示在用户的视图中。我无法控制外部 iframe,因为它位于不同的域中。标头本身必须在 iframe 内部,因为我在 iframe 之外无法控制。 iframe 总是扩展到其内容的高度,因此它没有滚动条,但滚动条仍然必须始终在视口中可见。

另外需要注意的是:iframe 的高度应该与其内容的高度相同,因此它们不需要滚动条

【问题讨论】:

    标签: css


    【解决方案1】:

    Chrome 存在一个错误,无法修复带有 position:fixed 的元素,如果:

    a) 你在 any 元素中使用 CSS3 转换,和/或

    b) 你有一个子元素位于其父元素的框外

    奇怪的是,这个错误早在 2009 年就被报告了,而且它仍然存在:https://code.google.com/p/chromium/issues/detail?id=20574

    【讨论】:

      【解决方案2】:

      你可能想玩转 position: fixed;

      #element {
          position: fixed;
          z-index: 1000;
          bottom: 0;
      }
      

      编辑:

      对不起,我想我错过了理解你的帖子。如果我没看错,你想创建一个类似于博客的标题栏,但要在用户滚动时始终保持在用户的视野中。

      您可以做的是创建一个容器 div,然后您可以在该容器内嵌套您的标头和 iframe。然后,您可以尝试定位,但我不确定您正在寻找的确切行为是否可能在没有一些 javascript 的情况下实现。

      编辑 2:

      玩了一会儿之后,我得到了一些我认为可能会有所帮助的东西(如果我正确理解您的问题的话)。

      http://digitaldreamer.net/media/examples/iframe-site.html http://digitaldreamer.net/media/examples/iframe.html

      【讨论】:

      • 您好,感谢您的回复。基本上因为我有一个 iframe 应用程序存在于社交网络中,所以我的整个应用程序必须在 iframe 中。我试图让我的页脚和页眉始终在用户的视野中,即使他们向上和向下滚动页面也是如此。有什么想法吗?
      • 标头是否需要包含在 iFrame 中,或者只对用户可见?我正在玩一些选项。
      • 是的,标头需要包含在 iframe 内,并且始终对用户可见,因为我们所有的标记都在 iframe 内,我们在 iframe 之外没有任何控制,因为这是社交网络所在的地方.我非常感谢您对这个具有挑战性的解决方案的帮助,并期待您的潜在解决方案。
      • 有趣的问题。我会尝试一下,看看我是否能想出任何有用的方法。
      • 非常感谢,您有目标网名吗?
      【解决方案3】:

      我不得不寻找一个可能的解决方案很长时间,我想我找到了一个使用Intersection Observer API 来检测父文档中 iframe 的滚动位置而无需访问父文档 DOM .

      我在 iframe 中创建了一堆隐藏的 100 像素高的元素。它们绝对位于彼此下方,以便它们一起填充整个 iframe 文档的高度。交集观察者然后观察(顶级文档)视口和每个隐藏元素之间的交集,并根据它返回的值计算 iframe 的滚动位置。如果主体高度增加,ResizeObserver 会创建额外的隐藏元素。

      此方法假定您的 iframe 始终至少为 100 像素高。如果您期望更小的高度,则需要调整隐藏容器的高度。原因是一旦隐藏的容器 100% 可见,交叉点观察者在父文档滚动时不会发出回调(因为交叉点比率保持在 1)。这也是为什么我需要很多小容器而不是观察与 iframe body 本身的交集的原因。

      const CONTAINER_HEIGHT = 100;
      const threshold = [...Array(CONTAINER_HEIGHT + 1).keys()].map((i) => i / CONTAINER_HEIGHT);
      
      /**
       * Registers an intersection handler that detects the scrolled position of the current
       * iframe within the browser viewport and calls a handler when it is first invoked and
       * whenever the scrolled position changes. This allows to position elements within the
       * iframe in a way that their position stays sticky in relation to the browser window.
       * @param handler Is invoked when the function is first called and whenever the scroll
       * position changes (for example due to the user scrolling the parent document). The
       * "top" parameter is the number of pixels from the top of the browser viewport to the
       * top of the iframe (if the top of the iframe is above the top of the browser viewport)
       * or 0 (if the top of the iframe is below the top of the browser viewport). Positioning
       * an element absolutely at this top position inside the iframe will simulate a sticky
       * positioning at the top edge of the browser viewport.
       * @returns Returns a callback that unregisters the handler.
       */
      function registerScrollPositionHandler(handler: (top: number) => void): () => void {
          const elementContainer = document.createElement('div');
          Object.assign(elementContainer.style, {
              position: 'absolute',
              top: '0',
              bottom: '0',
              width: '1px',
              pointerEvents: 'none',
              overflow: 'hidden'
          });
          document.body.appendChild(elementContainer);
      
          const elements: HTMLDivElement[] = [];
          let intersectionObserver: IntersectionObserver | undefined = undefined;
      
          const resizeObserver = new ResizeObserver(() => {
              intersectionObserver = new IntersectionObserver((entries) => {
                  for (const entry of entries) {
                      if (entry.intersectionRatio > 0 && (entry.intersectionRect.top > entry.boundingClientRect.top || entry.target === elements[0])) {
                          handler(entry.intersectionRect.top);
                      }
                  }
              }, { threshold });
      
              const count = Math.ceil(document.documentElement.offsetHeight / CONTAINER_HEIGHT);
              for (let i = 0; i < count; i++) {
                  if (!elements[i]) {
                      elements[i] = document.createElement('div');
                      Object.assign(elements[i].style, {
                          position: 'absolute',
                          top: `${i * CONTAINER_HEIGHT}px`,
                          height: `${CONTAINER_HEIGHT}px`,
                          width: '100%'
                      });
                      elementContainer.appendChild(elements[i]);
                      intersectionObserver.observe(elements[i]);
                  }
              }
          });
          resizeObserver.observe(document.documentElement);
      
          return () => {
              resizeObserver.disconnect();
              intersectionObserver?.disconnect();
              elementContainer.remove();
          };
      }
      

      此示例代码应在浏览器视口顶部创建一个粘性工具栏:

      <div style="position: absolute; top: 0; left: 0; bottom: 0; right: 0; overflow: hidden; pointer-events: none; z-index: 90">
          <div id="toolbar" style="position: absolute; top: 0; left: 0; right: 0; pointer-events: auto; transition: top 0.3s">
              Line 1<br/>Line 2<br/>Line 3<br/>Line 4<br/>Line 5<br/>Line 6<br/>Line 7<br/>Line 8<br/>Line 9<br/>Line 10
          </div>
      </div>
      <script>
          registerScrollPositionHandler((top) => {
              document.querySelector('#toolbar').style.top = `${top}px`;
          });
      </script>
      
      Note that other than what you asked for, this will position the toolbar at the top of the viewport rather than at the bottom. Positioning at the bottom should also be possible, but is slightly more complex. If anyone requires a solution for this, please let me know in the comments and I will invest the time to adjust my answer.
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-06-26
        • 1970-01-01
        • 2011-07-09
        • 2022-01-16
        • 2022-01-15
        • 2023-04-08
        • 1970-01-01
        相关资源
        最近更新 更多