Issue: I am currently developing a 3 column layout where certain columns need to remain sticky at the top of the viewport. In one section, I want to use the same video as a background for all 3 columns, with the specific effect of having the middle column stay 'sticky-top' while allowing the left and right columns to scroll up.
I attempted a solution using <Canvas>, but encountered a few issues. Canvases are unable to render frames without a blurry effect, especially in webkit browsers (though it seems to work better in Firefox). If jsFiddle doesn't play the video correctly, you may need to insert Bootstrap's CDN links to view the sample solution I'm aiming for here. I also tried inserting videos in the left and right columns and adjusting margins to create a seamless effect, but encountered synchronization issues where the videos would eventually go out of sync, losing the cohesive visual effect. You can check out the solution with 3 background videos here.
<!-- HTML structure for the columns and videos will go here -->
/* CSS styles for the layout */
.o-col-3-c {
flex:0 0 auto;
width:30%;
}
.o-col-4-c {
flex:0 0 auto;
width:40%;
}
.o-cont-m {
block-size:100vh;
}
.col-transparent{
background: rgba(0, 0, 0, .5);
}
video{
width:100vw;
height:100%;
display:block;
object-fit:fill;
}
.container-left,
.container-middle,
.container-right {
overflow:hidden;
}
// JavaScript code for handling the video structures and synchronization
const middleCol = document.querySelector('.container-middle');
const middleColOffsetLeft = middleCol.offsetLeft;
console.log(middleColOffsetLeft);
const rightCol = document.querySelector('.container-right');
const rightColOffsetLeft = rightCol.offsetLeft;
console.log(rightColOffsetLeft);
const bgVideo = document.getElementById('video-bg-middle');
bgVideo.style.marginLeft = `-${middleColOffsetLeft}px`
const canvasLeft = document.getElementById("canvas-left");
const canvasRight = document.getElementById("canvas-right");
canvasRight.style.marginLeft = `-${rightColOffsetLeft}px`;
const ctx = canvasLeft.getContext("2d");
const ctx1 = canvasRight.getContext("2d");
function drawFrames() {
if (!bgVideo.paused && !bgVideo.ended) {
ctx.drawImage(bgVideo, 0, 0, canvasLeft.width, canvasLeft.height);
ctx1.drawImage(bgVideo, 0, 0, canvasRight.width, canvasRight.height);
}
requestAnimationFrame(drawFrames); // Call drawFrames again on the next animation frame
}
bgVideo.addEventListener('play', () => {
drawFrames();
});
//Continuation of the HTML structure for handling multiple videos
<!-- HTML structure for multiple videos goes here -->
// CSS styles for handling multiple videos
.o-col-3-c {
flex:0 0 auto;
width:30%;
}
.o-col-4-c {
flex:0 0 auto;
width:40%;
}
.o-cont-m {
block-size:100vh;
}
.col-transparent{
background: rgba(0, 0, 0, .5);
}
video{
width:100vw;
height:100%;
display:block;
object-fit:fill;
}
.container-left,
.container-middle,
.container-right {
overflow:hidden;
}
// JavaScript code for handling multiple videos structure and synchronization
const updateLeftMargin = () => {
const middleCol = document.querySelector('.container-middle');
const rightCol = document.querySelector('.container-right');
const middleColOffsetLeft = middleCol.offsetLeft;
const rightColOffsetLeft = rightCol.offsetLeft;
const updateBackground = (elementId, marginLeft, width) => {
const element = document.getElementById(elementId);
if (element) {
if (marginLeft !== null) {
element.style.marginLeft = marginLeft < 0 ? `${marginLeft}px` : `-${marginLeft}px`;
}
if (width !== null) {
element.style.width = `${width}px`;
}
}
};
updateBackground('video-bg-middle', middleColOffsetLeft, null);
updateBackground('video-bg-right', -rightColOffsetLeft, null);
};
updateLeftMargin();
window.addEventListener('resize', updateLeftMargin);