Lazy Load Iframe Only After Modal is Triggered

↘锁芯ラ 提交于 2021-01-25 01:42:32

问题


Issue: I cannot natively lazy load an iframe on a modal window. When I check the waterfall in Inspect element > Network, the iframe loads immediately.

Goal: The iframe should load ONLY when modal is triggered. Can you help please?

I don't use dependencies like jQuery, but javascript is OK if it provides a solution. I tried the native and several other lazy loading solutions with no success.

My code:

.modal-state {
  display: none
}

.modal-state:checked+.modal {
  opacity: 1;
  visibility: visible
}

.modal-state:checked+.modal .modal__inner {
  top: 0
}

.modal {
  opacity: 0;
  visibility: hidden;
  position: fixed;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  text-align: left;
  background: #f2f2f2;
  transition: opacity .01s ease;
  z-index: 7;
  display: flex;
  flex-direction: column;
  height: 100vh;
  overflow-y: auto
}

.modal__bg {
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;
  cursor: pointer
}

.modal__inner {
  transition: top .01s ease;
  height: max-content;
  position: relative;
  max-width: 1200px;
  width: -webkit-fill-available;
  margin: auto;
  padding: 1em 1em;
}

.modal__close {
  position: absolute;
  right: 1.1em;
  top: 0;
  /*-.3em*/
  width: 1.1em;
  height: 1.1em;
  cursor: pointer;
  z-index: 1
}

.modal__close:after,
.modal__close:before {
  content: '';
  position: absolute;
  width: 2px;
  height: 1.5em;
  background: #999;
  display: block;
  transform: rotate(45deg);
  left: 50%;
  margin: -3px 0 0 -1px;
  top: 0
}

.modal__close:hover:after,
.modal__close:hover:before {
  background: #000
}

.modal__close:before {
  transform: rotate(-45deg)
}

.container-pay {
  position: relative;
  width: 100%;
  height: 200px;
  overflow: hidden;
  padding-top: 56.25%;
  /* 16:9 Aspect Ratio */
}

.responsive-iframe-pay {
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0;
  right: 0;
  width: 100%;
  height: 100%;
  border: none;
}
<p>In our <label for="modal-store">merchandize store</label>.</p>


<input class="modal-state" id="modal-store" type="checkbox" />

<div class="modal">
  <label class="modal__bg" for="modal-store"></label>
  <div class="modal__inner"><label class="modal__close" for="modal-store"></label>
    <p>
      <div class="container-pay">
        <iframe loading="lazy" class="responsive-iframe-pay" src="https://store.website.com"></iframe>
      </div>
    </p>
  </div>
</div>

回答1:


iFrames load when they're encountered in the rendered HTML DOM. Since your iFrame exists as part of the initially loaded code, it will load when the parser hits that portion of the HTML.

You can defeat that initial load action by either adding the iFrame to the DOM or modifying the URL right before the modal window is opened.

Modifying the <iframe src="" /> is likely the best solution since it will keep the loaded content for any additional times the modal is displayed.

You can do this by adding an "onchange" event to the checkbox which will run the javascript to change the src attribute of the iframe.

Make sure to change the src on the iframe to an empty string"" so it doesn't try to load anything right away.

var toggle = document.getElementById('modal-store');
var frame = document.getElementById('the-iframe');
var urlTarg = "https://google.com";
// put the page you want to load in the frame in the urlTarg

function toggleModal() {
  if(toggle.checked && frame.src != urlTarg){
     frame.src = urlTarg;
  }
}
.modal-state {
      display: none
    }

    .modal-state:checked+.modal {
      opacity: 1;
      visibility: visible
    }

    .modal-state:checked+.modal .modal__inner {
      top: 0
    }

    .modal {
      opacity: 0;
      visibility: hidden;
      position: fixed;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      text-align: left;
      background: #f2f2f2;
      transition: opacity .01s ease;
      z-index: 7;
      display: flex;
      flex-direction: column;
      height: 100vh;
      overflow-y: auto
    }

    .modal__bg {
      position: absolute;
      top: 0;
      right: 0;
      bottom: 0;
      left: 0;
      cursor: pointer
    }

    .modal__inner {
      transition: top .01s ease;
      height: max-content;
      position: relative;
      max-width: 1200px;
      width: -webkit-fill-available;
      margin: auto;
      padding: 1em 1em;
    }

    .modal__close {
      position: absolute;
      right: 1.1em;
      top: 0;
      /*-.3em*/
      width: 1.1em;
      height: 1.1em;
      cursor: pointer;
      z-index: 1
    }

    .modal__close:after,
    .modal__close:before {
      content: '';
      position: absolute;
      width: 2px;
      height: 1.5em;
      background: #999;
      display: block;
      transform: rotate(45deg);
      left: 50%;
      margin: -3px 0 0 -1px;
      top: 0
    }

    .modal__close:hover:after,
    .modal__close:hover:before {
      background: #000
    }

    .modal__close:before {
      transform: rotate(-45deg)
    }

    .container-pay {
      position: relative;
      width: 100%;
      height: 200px;
      overflow: hidden;
      padding-top: 56.25%;
      /* 16:9 Aspect Ratio */
    }

    .responsive-iframe-pay {
      position: absolute;
      top: 0;
      left: 0;
      bottom: 0;
      right: 0;
      width: 100%;
      height: 100%;
      border: none;
    }
    <p>In our <label for="modal-store">merchandize store</label>.</p>

    <input class="modal-state" id="modal-store" type="checkbox" onchange="toggleModal" />

    <div class="modal">
      <label class="modal__bg" for="modal-store"></label>
      <div class="modal__inner"><label class="modal__close" for="modal-store"></label>
        <p>
          <div class="container-pay">
            <iframe id="the-iframe" loading="lazy" class="responsive-iframe-pay" src=""></iframe>
          </div>
        </p>
      </div>
    </div>

Edit: Apply to multiple different buttons showing content in the same iframe

You can apply this to multiple iframe targets on the same page or the same site with a few modifications. This assumes that:

  1. You'll re-use the modal window AND iframe HTML code.
  2. That you want to display a different URL each time the modal is opened
  3. The modal window HTML exists on each HTML page that you want to have modal + iframe.

You would modify the Javascript to something like this:

    // you'll pass all the required values to the function

    function toggleModal(checkbox, frameTarg, urlTarg) {
      var frame = document.getElementById(frameTarg);
      if(checkbox.checked && frame.src != urlTarg){
         frame.src = urlTarg;
      }
    }

You will only need the javascript once per parent page since the same function can work for any combo of checkboxes, iframes, and URLs

And the checkbox HTML to: (Note: the same function could be applied to a button, link, etc)

<input class="modal-state" 
   id="modal-store" 
   type="checkbox" 
   onchange="toggleModal(this, 'the-iframe', 'https://theurltoloadinframe.com')" 
/>

<input class="modal-state2" 
   id="modal-store" 
   type="checkbox" 
   onchange="toggleModal(this, 'iframe2', 'https://someotherurltoload.com')" 
/>

Basically, the function expects you to pass in:

  1. The current checkbox - (denoted by this)
  2. The ID of the iframe you want to change make sure its a string with quotes
  3. The URL you want to load in the iFrame also in a string


来源:https://stackoverflow.com/questions/65707707/lazy-load-iframe-only-after-modal-is-triggered

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!