Lazy Load Iframe Only After Modal is Triggered - css

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>

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:
You'll re-use the modal window AND iframe HTML code.
That you want to display a different URL each time the modal is opened
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:
The current checkbox - (denoted by this)
The ID of the iframe you want to change make sure its a string with quotes
The URL you want to load in the iFrame also in a string

Related

CSS - onhover pulls down div vertically when page width is small

I am working on a site where there is an info icon next to the logo in the center of the page. When hovering over the info icon, a text box displays. For some reason, when the screen width is shorter than around 1300px, the entire logo as well as the info box is pulled down vertically. Not sure what aspect of onhover could be causing this.
I tried to manually move down the info icon with media queries but that is not a good way of doing it.
Here is react component:
function HomeContent() {
return (
<>
<div className="center-div">
<img src={tenGreenLogo} className="ten-green-logo" alt=""></img>
<div className="info-div">
<img src={infoIcon} alt="" className="info-icon"></img>
<p className="hidden-info">
The 10Green Score indicates the health of your environment using a
number from 0 to 10. The higher the score, the healthier your
environment.
<br></br>
<br></br>
Factors that can reduce your score include unhealthy air quality
readings and poor environmental monitoring.
</p>
</div>
</div>
<Globe />
</>
);
}
export default HomeContent;
and here is CSS for that component:
.center-div {
display: flex;
justify-content: center;
align-items: center;
padding-top: 7rem;
padding-bottom: 0rem;
scroll-behavior: smooth;
}
.ten-green-logo {
max-width: 40%;
animation: transitionIn 1s;
padding-right: 1rem;
}
.info-div {
width: 2rem;
margin-top: auto;
margin-bottom: 0;
}
.info-icon {
width: 2rem;
animation: transitionIn 1s;
}
.hidden-info {
display: none;
}
.info-icon:hover + .hidden-info {
display: block;
position: relative;
background-color: white;
padding: 0.6rem;
border-radius: 5%;
width: 20rem;
font-size: 80%;
right: 7.5rem;
top: 10.5rem;
}
.info-icon:hover {
position: relative;
top: 10.6rem;
}
#keyframes transitionRight {
from {
transform: translateX(0rem);
}
to {
transform: translateX(2rem);
}
}
#keyframes transitionIn {
from {
opacity: 0;
transform: translateY(4rem);
}
to {
opacity: 1;
transform: translateY(0rem);
}
}
Any help would be greatly appreciated.
use this style, you have to use position absolute on hidden-info
.info-div {
position: relative;
}
.hidden-info {
display: none;
position: absolute;
background-color: white;
padding: 0.6rem;
border-radius: 5%;
width: 20rem;
font-size: 80%;
right: 7.5rem;
top: 10.5rem;
}
.info-icon:hover + .hidden-info {
display: block;
}

Move vue-particles component to the back and use it as the background

I want the Vue-Particles component to be at the back, but somehow I cannot make this to work. All my components and HTML tags are behind the particles.
What I've tried is to fix it using the z-index CSS property.
Using z-index: 0 on the particle-js component:
h1 {
z-index: 999;
}
#particles-js {
position: absolute;
background-size: cover;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-y: hidden;
z-index: 0;
}
Shows like this:
Using z-index: -1 on the particle-js component moves the component to the bottom, not to the background like I want. See the new problem here:
EDIT: All my code is here, I am using Bootstrap-vue also:
<template>
<div id="app">
<Navbar />
<vue-particles color="#e60000"></vue-particles>
<h1>Hola</h1>
</div>
</template>
<script>
import Navbar from '../../components/Navbar.vue'
export default {
name: 'app',
components: {
Navbar
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
}
h1 {
z-index: 999;
}
#particles-js {
/*position: absolute;
background-size: cover;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-y: hidden;
z-index: 0;*/
width: 100%;
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 0;
}
</style>
The effect I want is something like this, where the lines don't cover anything of the title:
I was able to overlap text divs and vue-particle by setting the the text div position as absolute and specifying vertical and horizontal positioning. For example, to place something in the middle of the screen on top of the particles:
html:
<vue-particles color="#dedede"></vue-particles>
<div class="centered-text">
<p> Hello World </p>
</div>
css:
#particles-js {
height: 100vh;
}
.centered-text {
color: #ffffff;
position: absolute;
text-align: center;
top: 40%;
width: 100%;
}

LESS/ CSS : Writing a static text on image

I have following image as following,
How can i write text on image above and achieve the outcome as the following?
Try this, I hope it'll help you out. Thanks
.wrapper {
position: relative;
}
.wrapper img {
width: 100%;
}
.wrapper label {
color: #fff;
font-size: 24px;
position: absolute;
}
.wrapper #id1 {
left: 20px;
top: 20px;
}
.wrapper #id2 {
right: 20px;
top: 20px;
}
.wrapper #id3 {
left: 20px;
bottom: 20px;
}
.wrapper #id4 {
right: 20px;
bottom: 20px;
}
.wrapper #id5 {
right: 20px;
top: 50%;
transform: rotate(90deg)
}
.wrapper #id6 {
left: 20px;
top: 50%;
transform: rotate(-90deg)
}
<div class="wrapper">
<label id="id1">Text Left!</label>
<label id="id2">Text Right!</label>
<label id="id3">Text Bottom Left!</label>
<label id="id4">Text Bottom Right!</label>
<label id="id5">Text Rotate Right!</label>
<label id="id6">Text Rotate Left!</label>
<img src="https://keyassets.timeincuk.net/inspirewp/live/wp-content/uploads/sites/12/2015/07/Depth-of-field-landscape.jpg" alt="" />
</div>
Assuming you have HTML like:
<div class="container">
<img />
<p>Foo</p>
</div>
something like this would work (you'll have to fiddle the values obviously):
.container {
position: relative;
img{ z-index: 1; // img styles here }
p { position: absolute; left: 0.5rem; top: 0.5rem; z-index: 3; transform: rotate(90deg) }
}
Step by step:
Position the text absolutely
Rotate it 90 degrees
Set a Z-index higher than the image
Position the text correctly on the image
Profit ...

Microsoft Edge not respecting certain pseudo elements' CSS

The code in question: http://jsbin.com/bisimeyija/edit?html,css,output
It works fine in Chrome / Safari / Firefox and even IE11 i believe.
HTML
<div class="img-Offset">
<div class="img-Offset_ImageContainer">
<img src="http://placehold.it/430x350" alt="">
</div>
<p class="img-Offset_Caption">Scott Preston and his wife Laura</p>
</div>
:root {
--Theme_Primary-dark: #f98183;
}
CSS
.img-Offset {
position: relative;
z-index: 1;
max-width: 520px;
width: 100%;
}
.img-Offset::after {
content: '';
position: absolute;
top: 90px;
right: 0;
bottom: 0;
left: 0;
z-index: -1;
display: block;
background-color: var(--Theme_Primary-dark);
border-radius: 5px;
}
.img-Offset_ImageContainer {
position: relative;
padding-left: 90px;
border-radius: 5px;
border-bottom-right-radius: 0;
}
.img-Offset_Caption {
margin-top: 14px;
padding-right: 30px;
padding-bottom: 21px;
padding-left: 90px;
font-weight: 500;
color: #fff;
}
In Edge it looks like:
It should look like:
So for some reason the border-radius and top aren't working on the pseudo but everything else is.
It appears to be a problem relating to the use of CSS variables. If you change the background colour to be a simple hex value, the problem goes away.

How to close CSS3 Lightbox by clicking outside of the current image?

I try to close lightbox by clicking outside of the current image, but I don't how to do.
I just have a link "Back" in order to close this lightbox...
I use only CSS3, maybe Script is the solution, thanks for your help.
Here's a short CSS :
/*thumbnails*/
.album {
position: relative;
width:1200px;
height:auto;
float: left;
}
/*fullscreen*/
.overlay {
position: fixed;
left: 258px;
top: 0px;
padding: 0px;
overflow: hidden;
}
/*close fullscreen, back to thumbnails*/
.close {
position: absolute;
top: 50px;
left: 50%;
}
HTML
<ul class="album">
<li>
<img src="images/thumbs/example.jpg>
<div class="overlay" id="example">
<img src="images/full/example.jpg" />
BACK
</div>
</li>
</ul>
You could use a pseudo-element on the .close element and position that between the lightbox and the image using z-index.
.overlay:target .close:before {
position: fixed;
content: '';
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
}
.overlay { z-index: 5; }
.lightbox image { z-index: 15; }

Resources