Responsive YouTube embed not displaying in Firefox - javascript

This embed method appears to be working on all browsers except Firefox; I signed up for a free trial at crossbrowsertesting.com to check. I’m not doing a direct iFrame embed, and all the questions and answers I’ve found relate to that. I’m using this method: A Better Method for Embedding YouTube Videos on your Website. This method:
embeds the thumbnail image of a YouTube video and the actual video player is loaded only when the user manually clicks the thumbnail
The closest issue I could find on Stack Overflow was YouTube embed not working in Firefox. But this does not apply.
Here are screenshots of it displaying properly in Chrome:
And not displaying in Firefox:
In the Firefox image you can see the margin showing up in the inspector as I hover that <div>.
When I set an explicit height value this thumbnail does show up in Firefox, but it negates the responsiveness of the method.
document.addEventListener("DOMContentLoaded",
function() {
var div, n,
v = document.getElementsByClassName("youtube-player");
for (n = 0; n < v.length; n++) {
div = document.createElement("div");
div.setAttribute("data-id", v[n].dataset.id);
div.innerHTML = labnolThumb(v[n].dataset.id);
div.onclick = labnolIframe;
v[n].appendChild(div);
}
});
function labnolThumb(id) {
var thumb = '<img src="https://i.ytimg.com/vi/ID/hqdefault.jpg">',
play = '<div class="play"></div>';
return thumb.replace("ID", id) + play;
}
function labnolIframe() {
var iframe = document.createElement("iframe");
var embed = "https://www.youtube.com/embed/ID?autoplay=1";
iframe.setAttribute("src", embed.replace("ID", this.dataset.id));
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("allowfullscreen", "1");
this.parentNode.replaceChild(iframe, this);
}
.youtube-player {
position: relative;
padding-bottom: 56.23%;
/* Use 75% for 4:3 videos */
height: 0;
overflow: hidden;
max-width: 100%;
background: #000;
margin: 5px;
}
.youtube-player iframe {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 100;
background: transparent;
}
.youtube-player img {
bottom: 0;
display: block;
left: 0;
margin: auto;
max-width: 100%;
width: 100%;
position: absolute;
right: 0;
top: 0;
border: none;
height: auto;
cursor: pointer;
-webkit-transition: .4s all;
-moz-transition: .4s all;
transition: .4s all;
}
.youtube-player img:hover {
-webkit-filter: brightness(75%);
}
.youtube-player .play {
height: 72px;
width: 72px;
left: 50%;
top: 50%;
margin-left: -36px;
margin-top: -36px;
position: absolute;
background: url("//i.imgur.com/TxzC70f.png") no-repeat;
cursor: pointer;
}
<div class="youtube-player" data-id="VIDEO_ID"></div>

I solved this by removing redundant flexbox classes from the parent div. Specifically:
frow direction-column
(these are from the nice flexbox grid framework FrowCSS)
I don't fully understand why, but these must have been interfering with the requried styles in FireFox. Glad I figured it out, I had been wrestling with this 2-3 hours before I posted on SO. Hope this helps someone else in future.

I wrapped a div around the youtube-player and set that to display block and added a width of 100%. That solved the problem. Adding those to the youtube-player itself didn't work though.

Related

How can I make a real fullscreen on a galaxy s10

PICTURE of the issue
I observed that when you fullscreen a div on a galaxy s10 on chrome, because of the camera, there is a blank space. I suppose there is some sort of safe space so the content can be fully displayed...
I tried searching on the fullscreen mdn docs but found nothing about that specific issue.
Is there a way I can make my div take the whole screen including that black area or maybe choose a color ?
Here is how I fullscreen my div right now:
// fullscreen btn
document.querySelector(".fullscreen").onclick = function(){
if (window.innerHeight == screen.height) {
document.exitFullscreen();
} else {
document.querySelector(".app").requestFullscreen();
}
}
and here is the div's and button's css :
*{
margin: 0;
padding: 0;
}
.app{
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
background-color: crimson;
}
.fullscreen{
position: fixed;
top: 10px;
left: 10px;
height: 30px;
width: 30px;
background-color: burlywood;
}
I see is it possible to get a look at your HTML file so that I can test it out on my computer to understand the issue better?
But if your saying that the div should take up the entire screen then try
.fullscreen{
position: fixed;
top: 10px;
left: 10px;
height: 100%;
width: 100%;
background-color: burlywood;
}
Sorry if I'm wrong. If it doesn't work then consider giving me a look at the HTML file.

How to disable background scroll on pop-up?

I'm new to the web development world and wanted to know if there is a way to disable background scrolling.
I've tried z-index for the pop-up to display above all the elements, but some background content was getting overlapped with the pop-up.
I'm not much familiar with JS but was not able to get any help.
Below please find my code
body {
height: 200vh;
}
.bg-noscroll {
}
.overlay {
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
background: rgba(0, 0, 0, 0.7);
transition: opacity 500ms;
visibility: hidden;
opacity: 0;
}
.overlay:target {
visibility: visible;
opacity: 1;
}
.popup {
transform: translateY(-60px);
margin: 70px auto;
padding: 20px;
background: #fff;
border-radius: 5px;
width: 30%;
position: relative;
transition: all 5s ease-in-out;
}
.popup .close {
position: absolute;
top: 20px;
right: 30px;
transition: all 200ms;
font-size: 30px;
font-weight: bold;
text-decoration: none;
color: #333;
}
.content {
height: 250px;
}
.popup .content {
overflow-y: scroll;
}
#media screen and (max-width: 700px){
.popup{
width: 70%;
}
<body class="bg-noscroll bg-scroll">
<span><a class="popupBG-Disable" href="#popup">Full Recipe</a></span>
<div id="popup" class="overlay">
<div class="popup">
<h3>Foxtail Millet Porridge:</h3>
<a class="close" href="#">×</a>
<div class="content">
<span>Ingredients:<br>here are some things that you'd use to make this<br> isn't this amazing?<br>Yes, it is!<br>
this is getting loooooong<br>this will take me a while!<br>oh... yes it will<br>we're getting close<br>and we should be there <br>or not...<br>Im losing hope<br>and patience<br>with how long this is taking<br>I could really cry<br>
but we'll get there soon<br>safe and sound<br>free as pie<br>I dont know what I meant by that<br>
this is taking long mannnn<br>
</span>
Thank you for your help!
I have a live codepen with your original code so you can just copy and paste if you wish.
Using Jquery, we can enable and disable overflow using some simple code:
const modal = document.querySelector("#btn");
const body = document.querySelector("body");
const showModal = function (e) {
modal.classList.toggle("hidden");
if (!modal.classList.contains("hidden")) {
body.style.overflow = "hidden";
} else {
body.style.overflow = "hidden";
}
}; // just reversed for re-enabling scroll, as seen in the codepen
Currently, you have to make use of javascript and add or remove the scrollbar-properties or css-class using a hashchange event-listener for example:
window.addEventListener("hashchange", event => {
const newHash = new URL(event.newURL).hash,
el = document.getElementById(newHash.substr(1));
if (el && el.classList && el.classList.contains("overlay")) {
document.body.style.overflow = "hidden";
// or document.body.classList.add("bg-noscroll");
} else {
document.body.style.overflow = "";
// or document.body.classList.remove("bg-noscroll");
}
});
Starting from chromium 101 the support for the :has()-selector has been implemented (experimental flag only) and the current chromium 105 dev channel brings the :has()-selector enabled by default.
With the has()-selector it will be possible using:
body:has(.overlay:target) {
overflow: hidden;
}
Keep also mind, it may take some more time for other browsers to implement the has()-selector. Therefor the best would be to stick with the javascript method for a while.

What's causing the paint event in this CSS animation?

I'm building an animated menu based off of Smooth as Butter: Achieving 60 FPS Animations with CSS3.
The canonical demo which I'm comparing my code against is: http://codepen.io/Onyros/pen/jAJxkW
This is my demo code:
var navLayer = document.querySelector('.nav-layer'),
open = document.querySelector('.open'),
close = document.querySelector('.close');
function toggleNav() {
navLayer.classList.add('nav-layer__animating');
if (navLayer.classList.contains('nav-layer__visible')) {
navLayer.classList.remove('nav-layer__visible');
} else {
navLayer.classList.add('nav-layer__visible');
}
}
open.addEventListener('click', toggleNav, false);
close.addEventListener('click', toggleNav, false);
navLayer.addEventListener('transitionend', function() {
navLayer.classList.remove('nav-layer__animating');
}, false);
.nav-layer {
position: fixed;
top: 0;
left: 0;
height: 100vh;
width: 100vw;
z-index: 2;
pointer-events: none;
}
.nav-layer__visible {
pointer-events: auto;
}
.header {
position: fixed;
top: 0;
left: 0;
background-color: beige;
height: 10vh;
width: 100vw;
z-index: 1;
}
.nav {
position: relative;
height: 100vh;
width: 90vw;
background-color: aquamarine;
z-index: 3;
transform: translateX(-91vw);
will-change: transform;
}
.nav-layer__animating .nav {
transition: all 300ms ease-in;
}
.nav-layer__visible.nav-layer__animating .nav {
transition: all 300ms ease-out;
}
.nav-layer__visible .nav {
transform: none;
}
<div class="nav-layer">
<nav class="nav">
<button class="close">Close</button>
</nav>
</div>
<header class="header"><button class="open">Menu</button></header>
<article>
<p>O hai</p>
</article>
When I run the canonical demo with paint flashing enabled in Chrome DevTools, I don't see any paint events.
When I run my demo, I see a flash of paint when I close the menu.
The event log in DevTools shows that there was a paint on #document and another on nav.nav.
The answer I'm looking for here is: find the CSS property in the canonical demo which is preventing this flash of paint. Or, maybe the difference is in how I've structured my HTML. I think the JS is equivalent, so it's unlikely to be there.
Please provide your methodology, too!

Javascript/jQuery - replace a video iframe with a placeholder image

I've had one question involving this piece of code answered by the very helpful people here, but now I have another one which is slightly different. I have a placeholder image which sits in a carousel slide, which when clicked on gets replaced by a youtube video using the default youtube iframe embed.
What I would like to do is, after a user has clicked on the image and has played the video, when they click away from the carousel slide the video is embedded in (for example, by clicking on a carousel arrow or pagination dot) it resets it back to how it was before the video was displayed.
I hope that makes sense. Basically, I need help reverse engineering this code so that the video gets replaced again by it's placeholder image on a click of another element/div.
Here is the HTML:
<div class="youtube_video">
<img src="img/video_poster_carousel.jpg" width="986" height="308">
<!-- <iframe width="986" height="555" src="https://www.youtube.com/embed/Wt_Ruy_ejPY?enablejsapi=1&list=PL027E2B6D9900A88F&showinfo=0&controls=1" frameborder="0" allowfullscreen></iframe> -->
</div>
And the CSS:
/* video */
.youtube_video { position: relative; padding-bottom: 31.65%; height:0; }
.youtube_video img { position: absolute; display: block; top: 0; left: 0; /*width: 100%; height: 100%;*/ z-index: 20; cursor: pointer; }
.youtube_video:after { content: ""; position: absolute; display: block;
background: url(play-button.png) no-repeat 0 0;
top: 45%; left: 45%; width: 46px; height: 36px; z-index: 30; cursor: pointer; }
.youtube_video iframe { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/* image poster clicked, player class added using js */
.youtube_video.player img { display: none; }
.youtube_video.player:after { display: none; }
And the Javascript:
$(function() {
var videos = $(".youtube_video");
videos.on("click", function(){
var elm = $(this),
conts = elm.contents(),
le = conts.length,
ifr = null;
for(var i = 0; i<le; i++){
if(conts[i].nodeType == 8) ifr = conts[i].textContent;
}
elm.addClass("player").html(ifr);
elm.off("click");
});
});
This below line actually does a innerHTML which means your img tag is lost
you may have to move the IMG tag out of the youtube_video container and do a hide and show toggle mechanism for the youtube_video container and the IMG tag
elm.addClass("player").html(ifr);

Preloading a youtube embed

I want to have an embedded chromeless youtube video preload its video WITHOUT playing when the page loads. Right now I'm using an awkward "play then quickly pause" script which causes small problems (half-second audio leaks and fails quite a bit). For this seemingly simple functionality, is there a better/more elegant way to preload?
I had the same question and came across this question. After some research, I think I found a cleaner, albeit similar, answer.
When the JavaScript API calls OnYouTubePlayerReady, you press play and add an event listener to onStateChange that will be called every time the player changes from buffering to play.
For example, inside the function you listen for state 3, which is buffering, and as soon as it's called, you pause the video.
You can see this technique in action in this jsFiddle.
Side note: I refrained from using a JavaScript framework in my example, but you could easily put one into place here.
Also, I was unable to abstract the script tag out of the body of the HTML using jsFiddle, but an external script.js file works just fine on my own server.
If we view this: https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
Preloading the Iframe may help:
<link rel="preload" href="https://www.youtube.com/embed/dQw4w9WgXcQ" as="document">
Call
player.cueVideoById(videoId:String);
Instead of
player.loadVideoById(videoId:String);
I was looking for a solution to this problem and ran across this article:
Embed YouTube Videos Responsively without Increasing Load Time
The summary states: This method will reduce the size of your webpages by 300-400 KB while making your site mobile friendly.
Paste this on the page:
<div class="youtube-container">
<div class="youtube-player" data-id="VIDEOID"></div>
</div>
The javascript:
<script>
(function() {
var v = document.getElementsByClassName("youtube-player");
for (var n = 0; n < v.length; n++) {
var p = document.createElement("div");
p.innerHTML = labnolThumb(v[n].dataset.id);
p.onclick = labnolIframe;
v[n].appendChild(p);
}
})();
function labnolThumb(id) {
return '<img class="youtube-thumb" src="//i.ytimg.com/vi/' + id + '/hqdefault.jpg"><div class="play-button"></div>';
}
function labnolIframe() {
var iframe = document.createElement("iframe");
iframe.setAttribute("src", "//www.youtube.com/embed/" +
this.parentNode.dataset.id + "? autoplay=1&autohide=2&border=0&wmode=opaque&enablejsapi=1&controls=0&showinfo=0");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("id", "youtube-iframe");
this.parentNode.replaceChild(iframe, this);
}
</script>
The CSS:
<style>
.youtube-container {
display: block;
margin: 20px auto;
width: 100%;
max-width: 600px;
}
.youtube-player {
display: block;
width: 100%;
/* assuming that the video has a 16:9 ratio */
padding-bottom: 56.25%;
overflow: hidden;
position: relative;
width: 100%;
height: 100%;
cursor: hand;
cursor: pointer;
display: block;
}
img.youtube-thumb {
bottom: 0;
display: block;
left: 0;
margin: auto;
max-width: 100%;
width: 100%;
position: absolute;
right: 0;
top: 0;
height: auto
}
div.play-button {
height: 72px;
width: 72px;
left: 50%;
top: 50%;
margin-left: -36px;
margin-top: -36px;
position: absolute;
background: url("http://i.imgur.com/TxzC70f.png") no-repeat;
}
#youtube-iframe {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
}
</style>
Refer to the original article comments for additional modification suggestions and improvements.

Categories