Full screen background HTML5 video with cover image - css

I'm trying to add full screen background video to my site. I want to add a cover image too, because on mobile devices the video just does not play (because without user interaction the browser just won't load it).
So I added the video, positioned it properly, then I added the image. The image is the first frame of the video. Here is the problem: the position of the video and the image is not the same. So first the user sees the cover image, then after a moment the video starts playing, but there is a jump, because the video is not positioned the same as the image. Please note you may need to resize the browser window to see the problem. On 1920x1080 resolution it is barely visible.
How to position the video and the cover image properly?
See the demo code below. The video starts playing after 2 seconds, so you can see the image and then the video.
Here is a demo video in which you see the image and then the paused video, the cover image and the video.
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<style>
html,
body,
div,
video {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.video {
position: fixed;
top: 50%;
left: 50%;
z-index: 1;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.panel-cover {
position: fixed;
background-image: url(cover.jpg);
z-index: 2;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<video id="background-video" class="video" muted loop preload="auto">
<source src="Palm_Trees.mp4" type="video/mp4">
</video>
<div class="panel-cover"></div>
<script>
(function () {
function playVideo(video) {
setTimeout (function () {
video.play();
document.querySelector(".panel-cover").style.background = 'none';
}, 2000);
}
window.onload = function () {
var video = document.querySelector("#background-video");
video.addEventListener("canplay", function () {
playVideo(video);
}, false);
if (video.readyState > 3) {
playVideo(video);
}
}
})();
</script>
</body>
</html>

I have this working on one of my sites so will just paste you full code and you can adjust to your needs.
<div class="bgBox">
<div class="bgBox__cover cover_60"></div>
<div class="bgBox__holder" style="background-image: url('PATH/TO/IMAGE/COVER');">
<video loop="" muted="" autoplay="" class="bgBox__video">
<source type="video/mp4" src="PATH/TO/VIDEO">
</video>
</div>
</div>
And CSS:
.bgBox {
position: fixed;
z-index: -1;
}
.bgBox__cover {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 2;
margin: 0;
padding: 0;
}
.cover_60 {
background-color: rgba(0,0,0,.6);
}
.bgBox__holder {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100%;
z-index: 1;
margin: 0;
padding: 0;
background-size: cover;
background-repeat: no-repeat;
background-position: center center;
}
.bgBox__video {
-webkit-transition: opacity 1s ease;
-khtml-transition: opacity 1s ease;
-moz-transition: opacity 1s ease;
-ms-transition: opacity 1s ease;
-o-transition: opacity 1s ease;
transition: opacity 1s ease;
filter: alpha(opacity=100);
-ms-filter: "alpha(Opacity=100)";
-webkit-opacity: 1;
-khtml-opacity: 1;
-moz-opacity: 1;
-ms-opacity: 1;
-o-opacity: 1;
opacity: 1;
position: fixed;
top: 50%;
left: 50%;
z-index: 1;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translate(-50%,-50%);
}
I hope that helps.
Image needs to have the same aspect ration as the video.

I ended up using a simple workaround: slowly fading out the cover image:
.panel-cover {
...
transition: opacity 1s;
}
document.querySelector(".panel-cover").style.opacity = 0;

The problem was really the aspect ratio of the video. It's not 1:1, but 16:9.
So:
Removed Javascript, added the autoplay attribute. The video is a child of the cover image's div. If the video starts playing, the cover image won't be visible, if not, then the cover image will be visible.
Width/Height of the video and the cover image. It depends on the aspect ratio of the video and the browser window. So once you need width: 100%; height: auto; and in other cases you need the opposite: width: auto; height: 100%;
Therefore I added the appropriate #media queries:
#media (min-aspect-ratio: 16/9)
#media (max-aspect-ratio: 16/9)
If you have a simple 1:1 video, then maybe it just doesn't matter.
The final solution:
<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<style>
html,
body,
div,
video {
margin: 0;
padding: 0;
}
html,
body {
height: 100%;
}
.video {
position: fixed;
top: 50%;
left: 50%;
z-index: -100;
min-width: 100%;
min-height: 100%;
-webkit-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
.video-cover {
position: fixed;
z-index: -200;
min-width: 100%;
min-height: 100%;
width: 100%;
height: 100%;
background-image: url(cover.jpg);
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
#media (min-aspect-ratio: 16/9) {
.video {
width: 100%;
height: auto;
}
}
#media (max-aspect-ratio: 16/9) {
.video {
width: auto;
height: 100%;
}
}
</style>
</head>
<body>
<div class="video-cover">
<video class="video" muted loop autoplay preload="auto">
<source src="Palm_Trees.mp4" type="video/mp4">
</video>
</div>
</body>
</html>

Related

jumping button and White space in the bottom of the page

my HTML looks like this. i was trying to make a landing page with a cover and a button. this is my first time working on a real project and stumble upon this problem where the page does not have much elements and just a button
html, body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
}
.wrap {
background-image: url("../desktop.jpg");
background-repeat: no-repeat;
background-size: 100%;
background-attachment: fixed;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
#media (max-width: 39.9375em) {
.wrap {
background-image: url("../mobile.jpg");
}
}
.btn {
font-size: 1rem;
display: inline-block;
padding: 1rem 4rem;
background: #e6a503;
border: 0;
border-radius: 50px;
cursor: pointer;
font-weight: 900;
color: black;
-webkit-transition: opacity 100ms ease-in-out;
transition: opacity 100ms ease-in-out;
text-decoration: none;
}
.btn:hover {
opacity: 0.9;
}
.btn:active {
-webkit-transform: scale(0.98);
transform: scale(0.98);
}
.btn-container {
position: absolute;
bottom: 20%;
left: 25%;
}
#media (max-width: 39.9375em) {
.btn-container {
top: 35%;
left: 70;
}
}
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="dist/style.css" />
<title>title</title>
</head>
<body>
<div class="wrap">
<div class="btn-container">
<a href="https://www.google.com/" class="btn" target="_blank"
>အကောင့်ဖွင့်ရန်</a
>
</div>
</div>
</body>
</html>
what is causing the white space? also my button is jumping around in different browsers
pls help. thanks in advance.
this white space
Your problem is the css used to place the background image. If you want the image to cover all the background you first need to place it on the body. Not on the wrap.
Then use the following css:
body {
background-image: url(../desktop.jpg);
background-repeat: no-repeat;
background-size: cover;
background-position: center;
}
As you can see I changed background-position to center.
In case you really wanted to use the image only on the wrap then also change the background-position to center. Also you need the following css on wrap to ensure it fits the whole page:
position: absolute;
top: 0;
width: 100%;
height: 100vh;
Notice the position: absolute; which is necessary in order to top:0 to work. In desktop it works just fine. It may be possible that on mobile the wrap component isn't covering the whole windows.
Regarding the centering of your button take a look at this. Just use the following css on the button container:
.btn-container{
margin: 0;
position: absolute;
top: 50%;
left: 50%;
-ms-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
As you can see, instead of using top and left with 33% it uses 50% and then it transforms the position of the button 50% to the left of the button (this last 50% is accordint to the button size).

PNG stripe pattern over image - blinking/flashing when scrolling

I need to add a very thin stripes pattern over an image in html. I can't really add it to the image itself for multiple reasons (images are uploaded in a CMS, must be used in other places without the stripes, and i also want the pattern to remain unscaled, whereas the images do scale...).
So i made a transparent PNG with the pattern, put it over the image with a pseudo element and use background-repeat to loop it over the entire image (see snippet).
The problem i have is that the image is blinking/flashing when i scroll the page down. Tested on Firefox & Chrome with the same result. I tried different other options like using a very big stripe image to avoid background-repeat, or using a non transparent image with mix-blend-mode:multiply, but the result is always the same.
I also tried a pure css solution with repeating linear background but the rendering is not very good because the pattern is too thin.
The only way i can have a clean rendering is by inlaying the pattern in the original image, no blinking then, but this is not really an option for the reasons mentionned above.
Any ideas ? Thanks :-)
#container {
position: relative;
}
#container:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url(https://indelebil.fr/stripes.png) repeat;
}
img {
display: block;
max-width: 100%;
}
<div id="container">
<img src="https://indelebil.fr/sample.jpg" />
</div>
We can do this with linear-gradient
No need to use strips.png
body {
height: 300vh;
}
#container {
position: relative;
overflow: hidden;
}
#container:after {
content: '';
position: absolute;
top: -200vh;
left: 0;
right: 0;
bottom: 0;
width: 200vw;
height: 400vh;
background-size: 3px 44px;
background-repeat: repeat;
background-image: linear-gradient(to left, transparent -5px, #000000a3 8px, transparent 26px, transparent);
transform: rotate(-45deg) scale(1.5);
}
img {
display: block;
max-width: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stack Overflow</title>
<link rel="stylesheet" href="./styles.css">
</head>
<body>
<div id="container">
<img src="https://indelebil.fr/sample.jpg" />
</div>
</body>
</html>
I finally found a workaround, the flashing effect tends to disappear by lowering the pattern opacity, it is still present but it becomes kinda acceptable under 0.6% alpha.
By the way if anyone has a better way keeping 100% opacity i would be happy to hear about it !
#container {
position: relative;
}
#container:after {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url(https://indelebil.fr/stripes.png) repeat;
opacity:.5;
}
img {
display: block;
max-width: 100%;
}
<div id="container">
<img src="https://indelebil.fr/sample.jpg" />
</div>

background-attachment: fixed in Firefox or Edge versus Chrome

body {
height: 150vh;
}
#hero {
position: relative;
border: none;
height: 100vh;
}
#hero .hero-image {
background-image: url(https://images.unsplash.com/photo-1518791841217-8f162f1e1131);
background-attachment: fixed;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
height: 95%;
}
#hero .hero-image:after {
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0,0,0,0.2);
}
#hero .skewhero-mask {
height: 100%;
position: absolute;
top: 0;
left: 10vw;
width: 45vw;
overflow: hidden;
transform: skew(24deg) translateX(0vh) translateY(0%);
}
#hero .skewhero-parallax {
transform: translateX(0vh);
width: 200%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
}
#hero .skewhero-image {
background-image: url(https://images.unsplash.com/photo-1518791841217-8f162f1e1131);
height: 100%;
background-size: 110% auto;
background-attachment: fixed;
transform-origin: right top;
transform: skew(-24deg);
}
<section id="hero">
<div class="hero-image">
</div>
<div class="skewhero-mask">
<div class="skewhero-parallax">
<div class="skewhero-image"></div>
</div>
</div>
</section>
I am really stuck with this one. I'm designing a parallax effect where I shift the background-position property of a fixed background using jQuery. The jQuery isn't at fault here, so I won't include it here to reduce the complexity of the question.
In Chrome, I get the desired effect. In Firefox or Edge, it's a nightmare. I have not tested it on Opera as of yet. When removing the background-attachment: fixed from the class .skewhero-image in those browsers, I notice there's no difference whatsoever. The property doesn't do anything, because when I remove the same property in Chrome, I get the same undesirable result as in the other browsers.
How can I change my code as to achieve the exact same effect as I have now in Chrome, but in all other desktop browsers as well? Mobile browsers excluded.
Basically, the image of the cat must not move, only the container surrounding it. In Chrome, this works as intended. In Firefox or Edge, the cat moves with the container, it isn't fixed to the viewport.
Edit: I have found out that leaving out all transform properties, from itself and all parents, fixes the image to the viewport. Anything to remedy this?
I am not sure what version of Firefox you are using but I just created codepen and it is working fine
<https://codepen.io/anon/pen/ZgpgZP>
If you are still have problem, please describe in details
$(function() {
"use strict";
var $skp = $('.skewhero-parallax');
var $skm = $('.skewhero-mask');
var $hi = $('.hero-image');
function calcParallax() {
var $scroll = $(document).scrollTop();
$skm.css({'transform':'skew(24deg) translateX(-' + (0.445 * $scroll) + 'px)'});
$skp.css({'transform':'translateY(' + $scroll + 'px)'});
$hi.css({'transform':'translateY(' + $scroll + 'px)'});
}
$(window).on('scroll', function () {
calcParallax();
});
$(window).resize(function() {
calcParallax();
});
});
body {
height: 150vh;
}
#hero {
position: relative;
border: none;
height: 100vh;
}
#hero .hero-container {
height: 95%;
overflow: hidden;
}
#hero .hero-container:after {
content: "";
position: absolute;
background: rgba(0,0,0,0.2);
height: 95%;
top: 0;
left: 0;
right: 0;
}
#hero .hero-image {
height: 100%;
background-image: url(https://images.unsplash.com/photo-1518791841217-8f162f1e1131);
background-repeat: no-repeat;
background-size: cover;
will-change: transform;
}
#hero .skewhero-mask {
height: 100%;
position: absolute;
top: 0;
left: 10vh;
width: 45vw;
overflow: hidden;
transform: skew(24deg) translateX(0vh);
will-change: transform;
}
#hero .skewhero-parallax {
width: 200%;
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
transform: translateY(0px);
will-change: transform;
}
#hero .skewhero-image {
background-image: url(https://images.unsplash.com/photo-1518791841217-8f162f1e1131);
background-repeat: no-repeat;
height: 100%;
background-size: 110% auto;
background-position: 0px -35px;
transform-origin: right top;
transform: skew(-24deg);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="hero">
<div class="hero-container">
<div class="hero-image"></div>
</div>
<div class="skewhero-mask">
<div class="skewhero-parallax">
<div class="skewhero-image"></div>
</div>
</div>
</section>
I have found an alternative solution to fix my problem. Also, it seems browsers are able to deal with this solution a lot better. background-attachment:fixed is causing serious performance issues. This is because the browsers have to repaint the entire image when scrolled. Source #1 and Source #2. I have tested this myself and can confirm there's heavy lag when scrolling. I have started using the transform: translate() property, which is a lot more optimized for this as browsers don't have to repaint the entire image.
As I want to animate my parallax effect with jQuery, I've mimicked the fixed background effect in my code. I have added a code snippet of the desired effect, which works in Chrome, Firefox and Edge.

How to Make an Image Fill the Container Height and Retail Aspect Ratio with Bootstrap 4

How can an image fill the parent container height, and retain the aspect ratio?
I have used a similar pattern before (see below), but I believe that Bootstrap 4 may be interfering here. When viewing the image in a mobile view port, the image is stretching vertically.
div#parent { position: relative; }
h1 { color: #FFF }
img#child {
position: absolute;
min-width: 100%;
min-height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -100;
}
<div id="parent">
<img id="child"
src="https://cdn.pixabay.com/photo/2016/07/08/08/59/background-1503863_1280.png" alt="Background" />
<h1>Very very very very very very very very very very very long heading
to go over image in mobile view. The image should not stretch
vertically.</h1>
</div>
Add background-size: contain; to your CSS
img#child {
position: absolute;
min-width: 100%;
min-height: 100%;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
z-index: -100;
background-size: contain;
}
Output:
For more info: https://www.w3schools.com/csSref/css3_pr_background-size.asp

Change opacity of background image in HTML

I have created a HTML page. There is a background image in my page. I want to change the opacitry of my background
i.e. opacity of image used in background. I am using this code to add a background image to my page:
<!DOCTYPE html>
<html>
<head>
<style>
body{background-image: url('IMG_18072014_115640.png')}
</style>
</head>
<h1>Hello world!</h1>
<body>The background image will be shown behind this text.</body>
</html>
How can I change this code to change the opacity of this background image.
Apply background-image to body's :after :pseudo-element and change its opacity, so that the body's content is not affected.
body, html {
position: absolute;
width: 100%;
height: 100%;
margin: 0;
}
body:after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url(http://www.lorempixel.com/600/400);
opacity: 0.3;
z-index: -1;
}
<h1>Hello world!</h1>
<body>The background image will be shown behind this text.</body>
I think you misunderstand some things in html,
but one simple solution would be to make a transparent background image... (PNG24 transparency)
Try this way to change opacity of psudo element : DEMO
div {
width: 200px;
height: 200px;
display: block;
position: relative;
}
div::after {
content: "";
background: url(http://s.hswstatic.com/gif/evil-robots-3b.jpg);
opacity: 0.5;
top: 0;
left: 0;
bottom: 0;
right: 0;
position: absolute;
z-index: -1;
}

Resources