Search code examples
javascripthtmlcssiframeyoutube-iframe-api

How can I make a YouTube embed iframe act like part of the html body for mouse coordinates?


I'm trying to make a mouse trailer for my site, but when hovering over a YouTube iframe the trailer does not follow it into the iframe area. (I'm using js to extract the x and y coordinates of the mouse from the body) I have like no idea how to make this work so any help or ideas would be much appreciated!

Code below:

there are ">"s next to important code

html

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="homestyle.css">
        
        <link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100;200;300;400;500;600;700;800;900&display=swap" rel="stylesheet">
<title>****************</title>
    </head>
<body>
    <div id="trailer">
        
    </div>
    <script src="homescript.js"></script>
    <div class="navbaralign">
        <ul class="navbar">
            <li><a href="#toppage">Home</a></li>
            <li><a href="#about">About</a></li>
            <li><a href="#mywork">My Work</a></li>
            <li><a href="#contact">Contact</a></li>
        </ul>
    </div>

<div id="toppage" class="toppage">

    <div class="maintitle">
        <h1>****************</h1>
        <h2>Front-end web developer, music producer, and 3d animator/artist.</h2>
    </div>
</div>
<div id="about" class="about">
    <h3>About Me</h3>
</div>
    

> <div id="mywork" class="mywork">
>             <iframe class="interactable" src="https://www.youtube.com/embed/B6ipLAQ7lM4" title="bowling alley
> animations be like" frameborder="0" allow=""></iframe>
>             <iframe class="interactable" src="https://www.youtube.com/embed/kJniNIlKIDE" title="Ktashi - HOLD
> ON" frameborder="0" allow=""></iframe>
>     </div>

</body>
</html>

css

html {
    scroll-behavior: smooth;
}

#trailer {
    height: 20px;
    width: 20px;
    background-color: #ffffff;
    border-radius: 20px;

    position: fixed;
    left: 0;
    top: 0;
    z-index: 10000;

    pointer-events: none;
    opacity: 0;
    transition: opacity 500ms ease;
}

body:hover > #trailer {
    opacity: 1;
}

body {
    background-color: #FF4722;
    margin: 0;
}

h1 {
    font-family: Inter;
    font-weight: 900;
    color: #FFFFFF;
    font-size: 48px;
    line-height: 48px;
    text-align: center;
    padding-left: 10vw;
    padding-right: 10vw;
}

h2 {
    font-family: Inter;
    font-weight: 300;
    color: #FFF9D1;
    font-size: 24px;
    line-height: 24px;
    text-align: center;
    padding-left: 10vw;
    padding-right: 10vw;
}

h3 {
    font-family: Inter;
    font-weight: 600;
    color: #ffffff;
    font-size: 24px;
    line-height: 12px;
    text-align: left;
}

.toppage {
    height: 100vh;
    display: grid;
    place-items: center;
}

.navbaralign {
    display: flex;
    justify-content: center;
}

.navbar {
    display: flex;
    justify-content: space-between;
    height: 5vh;
    padding: 0;
    list-style: none;
    align-items: center;
    background-color: #000000;
    box-shadow: 0 3px 5px rgba(0, 0, 0, 0.50);
    margin: 0;
    position: fixed;
    top: 1vh;
    width: 80%;
    border-radius: 6vh;
    padding: 2.5vh;
    box-sizing: border-box;
    padding-top: 3vh;
    padding-bottom: 3vh;
}

.maintitle {
    display: grid;
    place-items: center;
    user-select: none;
}

a {
    text-decoration: none;
    color: #ffffff;
    font-family: Inter;
    font-weight: 600;
    font-size: 18px;
    transition: color 500ms ease;
    background-color: linear-gradient(#ffffff, #000000)
}

a:hover {
    color: #FFF9D1;
}

@media (max-width: 700px) and (orientation: portrait) {
    .navbar {
        flex-direction: column;
        height: 20vh;
    }
}

.mywork {
    display: flex;
    gap: 2vw;
    padding: 2vw;
    background-image: linear-gradient(#FF4722, #000000)
}

iframe {
    aspect-ratio: 16 / 9;
    flex-grow: 1;
    flex-shrink: 0;
    flex-basis: 0;
}

.interactable {
    transition: background-size 500ms ease, opacity 500ms ease;
}

.interactable:hover {
    background-size: 105%;
    opacity: 0.8;
}

js

const trailer = document.getElementById("trailer");

window.onmousemove = e => {
    const x = e.clientX - trailer.offsetWidth / 2,
          y = e.clientY - trailer.offsetHeight / 2;

    const keyframes = {
        transform: `translate(${x}px, ${y}px)`
    };

    trailer.animate(keyframes, {
        duration: 800,
        fill: "forwards"
    });
};

I've tried adding

    pointer-events: none;

to the iframes' class in css and I had a feeling that that wouldn't work. I was right. but I honestly have no idea what else could work. 😅


Solution

  • For security reasons, browsers don't allow you to get information about interactions made on cross-domain iframes. In this case, youtube.com is a different domain than the original website(ie cross-domain), and thus you can't get mouse information while the user is interacting with youtube. This is done to prevent things like embedding banking websites and getting the user's interactions made on logins etc... You can normally get around this by putting a transparent div over the original iframe, but that would also block any mouse interaction with the youtube iframe in the process. This would mean that while the circle would follow the mouse while you were over the youtube window, you would be unable to start the video since you couldn't interact with the youtube page. There isn't really a way to get around this issue, since it is caused by your web browser's security. Hopefully, this helps :)