Google 如何在 iframe 中创建适合移动设备的固定背景和视差内容?

Dim*_*ser 4 javascript css iframe ads

我当前的测试涉及一个intersectionobserver,它使用带有当前滚动位置的iframe postMessage 来转换iframe 中的3d 背景图像。但这会产生很多抖动,在生产中可能会延迟,我可以看到这种方法存在更多问题。根据我在 Google 的网络开发人员工具中玩弄的理解,广告使用视差来使内容响应滚动位置,但是 Google 是否依赖 postMessage 来实现这一点,或者他们如何做才能使内容流畅固定背景和内容响应父窗口滚动事件的体验?

Some code example
Run Code Online (Sandbox Code Playgroud)

演示|| 代码

抖动

据我了解,使用的组件称为视差,可在Google Web Designer 中使用

当你滚动时,她的脸在转动(一系列图像根据 yPosition 变化) 根据滚动位置更改表盘和背景图像 固定位置背景

关于固定背景,我知道iOS不支持背景附件:固定,为什么它必须是一些基于JS的功能。然后由我相信的父窗口中的intersectionobserver触发。如果 Google 广告完全依赖父窗口来提供任何信息,或者一切都从 iframe 内部进行管理 - 我不知道。但我想听听是否有人知道这些技术及其背后的工作,因为这看起来非常简单,但对于像我这样的凡人来说却是非常难以实现的。

Aar*_*219 6

多么有趣的问题!我想从你的最后一张 gif 开始。

GIF #3

关于固定背景,我知道 iOS 不支持background-attachment: fixed,为什么它必须是一些基于 JS 的功能。

即使 IOS 支持background-attachment: fixed这也行不通,因为此属性仅适用于背景图像。它也不是 JS(至少不一定),因为你可以用 CSS 来做到这一点:

* {
  margin: 0;
  padding: 0;
}

.section {
  width: 100%;
  height: 1000px;
  background: red;
}

.spacer {
  width: 100%;
  height: 200px;
  background: transparent;
}

.background-scroller {
  background: lightgrey;
  width: 100%;
  height: 100%;
  position: fixed;
  top: 0;
  z-index: -1;
  display: flex;
  align-items: center;
  justify-content: center;
}
Run Code Online (Sandbox Code Playgroud)
<div class="section"></div>
<div class="spacer"></div>
<div class="section"></div>
<div class="background-scroller">
  This could be anything
</div>
Run Code Online (Sandbox Code Playgroud)

我知道在某些网站上,每个“间隔”的广告都会发生变化,但这也可以通过 CSS 仅通过使用position: sticky.

* {
  margin: 0;
  padding: 0;
}

.section {
  width: 100%;
  height: 1000px;
  background: red;
}

.spacer {
  width: 100%;
  height: 200px;
  background: transparent;
}

.background-scroller {
  background: lightgrey;
  width: 100%;
  height: 100vH;
  position: sticky;
  top: 0;
  z-index: -1;
  display: flex;
  align-items: center;
  justify-content: center;
  float: left;
}

.section-wrapper {
  position: relative;
}
Run Code Online (Sandbox Code Playgroud)
<div class="section-wrapper">
  <div class="background-scroller">
    This is one thing
  </div>
  <div class="section"></div>
  <div class="spacer"></div>

  <div class="background-scroller">
    And this is something completely else
  </div>

  <div class="section"></div>
  <div class="spacer"></div>

  <div class="section"></div>
</div>
Run Code Online (Sandbox Code Playgroud)

每个站点的做法都不一样,而且很多站点都使用相交观察器 API,但我的观点是,有时一些简单的 CSS 就可以完成这项工作。所以不一定是JS!这些是一些合法的方法来做到这一点。


Gif #2, Gif #1

这些效果有点复杂。

跨域限制是一个很大(但必要)的问题。您的父框架对 iframe 的访问非常受限,反之亦然。这让我们只剩下几个可以使用的属性

如果您检查 iframe 元素,您可能已经注意到,它们使用了一个data-is-safeframe属性。我复制了这样一个元素并删除了所有不重要的属性。

<iframe src="" data-is-safeframe="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts allow-top-navigation-by-user-activation"></iframe>
Run Code Online (Sandbox Code Playgroud)

什么是安全框架?那么,SafeFrame API是由 IAB(Interactive Advertising Bureau)开发的,基本上允许广告商和广告提供商之间的通信。如果您不是 Google 开发人员,则可能无法确切知道他们使用此 API 的目的。

只有一种现代方式可以与跨域通信iframespostMessage(). 是的,他们也使用 SafeFrame,但我认为这不适合这样的事情。没有办法(对于谷歌也是)打破这个规则。可以肯定的是,我做了一些测试(如果我考虑一下,这真的没有必要)并且我所有的测试都失败了。


但这会产生很多抖动

这让我感到惊讶,因为postMessage不应该那么慢。我用 JSFiddle 做了一个小例子,因为 SO 用我的iframe.

  • 这是将显示在以下页面中的页面iframe单击代码
  • 这是将显示iframe和发送postMessage()的页面(向下滚动页面(不是iframe)):单击代码

如果您查看控制台,您会注意到它postMessage的速度绝对足以处理快速触发事件,例如scroll. 您也可以因为“迪斯科iframe”而注意到它。

老实说,我认为问题出在您的网站上。


结论

我不知道谷歌是如何做到这一点的。但是,我只能想到一种可能的方法:postMessage- 您已经选择的方法。这意味着,如果没有其他方式,这一定是谷歌使用的方式。

你的性能问题一定是你的错。


所以这只是我的意见。可能有我没有想到的技术和方法。我觉得这个问题很有趣,如果我的解决方案不对,我想知道正确的答案!所以请随时纠正我。


编辑 #1

经过大量耗时的调查,我终于从可靠来源找到了解决方案:在某种程度上,来自谷歌本身。但也来自我发现的各种网站,它们利用了这种效果。

简答

它基本上就像我在Gif #3 中解释的那样。

长答案

这样的广告有不同的名称:InterscrollerFlying地毯粘性广告,可能还有更多,但这些是我遇到的。

我发现广告通常是使用谷歌发布的AMP加速移动页面)编写和实施的。

终于找到了一个使用飞毯广告的网站后,我可以检查它并发现以下内容:

这证实了我的发现。他们使用AMP!但不仅是他们,我还遇到过使用相同技术的不同网站。

让我们分析一下 HTML 结构。我们关注的部分是<amp-fx-flying-carpet>和它的第一个父级,<div class="amp-article-ad>直到<iframe>.

删除了所有不必要的东西的基本结构如下所示:

<div class="amp-article-ad">
  ::before
  <amp-fx-flying-carpet>
    <div class="i-amphtml-fx-flying-carpet-clip">
      <div class="i-amphtml-fx-flying-carpet-container">
        <amp-ad class="amp-article-ad-element i-amphtml-layout-fixed i-amphtml-layout-size-defined i-amphtml-element i-amphtml-layout">
          <div fallback></div>
          <amp-analytics></amp-analytics>
          <iframe></iframe>
        </amp-ad>
      </div>
    </div>
  </amp-fx-flying-carpet>
</div>
Run Code Online (Sandbox Code Playgroud)

如果我们通过删除所有不必要的包装器来进一步减少这种情况,则结构如下所示:

<div class="amp-article-ad">
  <amp-fx-flying-carpet>
    <div class="i-amphtml-fx-flying-carpet-container">
      <amp-ad>
        <iframe></iframe>
      </amp-ad>
    </div>
  </amp-fx-flying-carpet>
</div>
Run Code Online (Sandbox Code Playgroud)

让我们从头开始。<div class="amp-article-ad">只是广告的包装器,包含<amp-fx-flying-carpet>. 的大小<div class="amp-article-ad"><amp-fx-flying-carpet>是相同的,并且我们可以通过看广告的窗口:

现在是重要的部分!<div class="i-amphtml-fx-flying-carpet-container">是 的包装器,<amp-ad>它的尺寸大于它的包装器<amp-fx-flying-carpet>的尺寸(要预先调整的广告尺寸),这已经表明某些 CSS 属性将其从流程中移除。一些属性的例子是:

  • float: left
  • float: right
  • position: fixed
  • position: absolute
  • ...

你可能知道我要去哪里。的 CSS 属性<div class="i-amphtml-fx-flying-carpet-container">是:

我们有它:position: fixed

的大小<amp-ad>是广告的大小,这是有道理的,因为它包含包含广告的 iframe。

<iframe>明明只包含广告。


所以我们有外部包装器,作为我们可以看到的窗口。此窗口内是容器,通过添加position: fixed. 这些固定容器包含<iframe>,其中包含广告。


说服自己!这是带有示例的官方 AMP 文档:https : //amp.dev/documentation/examples/components/amp-fx-flying-carpet/#flying-carpet-for-ads

结构几乎相同。当然,我做了一个小例子,使用相同的技术:

* {
  margin: 0;
  padding: 0;
}

body {
  text-align: center;
}

p {
  width: 100%;
  background: white;
  position: relative;
  z-index: 1;
}

.flying-carpet-wrapper {
  height: 200px;
  width: 100%;
}

.amp-ad-wrapper {
  position: fixed;
  height: 100%;
  top: 0;
  left: 0;
  width: 100%;
  display: flex;
  justify-content: center;
  align-items: center;
}

iframe {
  border: 0;
  height: 500px;
  width: 500px;
}
Run Code Online (Sandbox Code Playgroud)
<p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p>

<div class="flying-carpet-wrapper"> <!--<amp-fx-flying-carpet>-->
 <div class="amp-ad-wrapper"> <!--<div class="i-amphtml-fx-flying-carpet-container">-->
   <div class="amp-ad"> <!--<amp-ad>-->
      <iframe src="https://de.wikipedia.org/wiki/Accelerated_Mobile_Pages"></iframe>
   </div>
 </div>
</div>

<p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p><p>Content</p>
Run Code Online (Sandbox Code Playgroud)