The width=100% height="auto" scales my videos to fit the whole width of the browser window, but if the height of the window is lower than the aspect ratio the video gets cropped in height.
I want the video to scale to fit either width or height so that I can always see the whole video without crop, filling the closest ratio (adding empty space to sides if window ratio is lower).
I can't figure out how to do this however.
First any height value, % or px, seems to be disregarded, I can't set the size at all using height, only width. Same for min-width/height.
How can this be done?
My code:
<video id="video" width=100% height="auto" onclick=playPause()></video>
Video is loaded by javascript where v is a video link from an array:
video.addEventListener('play', function() { v.play();}, false);
Try wrapping the value inside quotes
<div class="videoContainer">
<video id="video" width="100%" height="auto" onclick="playPause();"></video>
</div>
you can add these class
.videoContainer
{
position:absolute;
height:100%;
width:100%;
overflow: hidden;
}
.videoContainer video
{
min-width: 100%;
min-height: 100%;
}
Or alternatively use this
video {
object-fit: cover;
}
Solved it myself with a javascript function:
window.addEventListener('resize', resize, false);
video.height = 100; /* to get an initial width to work with*/
resize();
function resize() {
videoRatio = video.height / video.width;
windowRatio = window.innerHeight / window.innerWidth; /* browser size */
if (windowRatio < videoRatio) {
if (window.innerHeight > 50) { /* smallest video height */
video.height = window.innerHeight;
} else {
video.height = 50;
}
} else {
video.width = window.innerWidth;
}
};
There's a great auto width/height trick called intrinsic ratios that can be used on images/videos and the likes! The trick is to have your desired element in a wrapper that then has a percentage-valued padding applied to it.
Your markup would then be:
<div class="video-wrapper">
<video class="video" id="video" onclick=playPause()></video>
</div>
And your CSS:
.video-wrapper {
position: relative;
padding-bottom: 20%;
height: 0;
}
.video {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #ccc; /* Random BG colour for unloaded video elements */
}
You can limit the dimensions of your video container by playing with min-width or max-width of the .video-wrapper styles.
Hope this helps!
I had a similar problem. I have made a `slideshow' with various objects as slides, some of them are videos of various sizes. I did not found any conceptual solution, so I have found a trick.
I have explicitely specified all real video sizes in tags and collected the information of all of them:
var vids = document.getElementsByClassName("vid"); // videos
var vidl = vids.length;
var vidH = [ ];
var vidW = [ ];
// Get original widths and heights of videos
for (i=0; i<vidl; i++) { // >
vidH.push(vids[i].height);
vidW.push(vids[i].width);
}
Then (when necessary) I define the window size as follows:
// Current inner height of the browser window (in pixels)
var iH = window.innerHeight
|| document.documentElement.clientHeight
|| document.body.clientHeight;
// Current inner width of the browser window (in pixels)
var iW = window.innerWidth
|| document.documentElement.clientWidth
|| document.body.clientWidth;
To rescale a rectangle into another rectangle we have to find a minimal scale:
var r, rh, rw;
// Scale videos to fit window
for (i=0; i<vidl; i++) { // >
rh=iH / vidH[i]; rw=iW / vidW[i]; r=Math.min(rh, rw);
if (rh>rw) {
vids[i].height=Math.floor(vidH[i]*r);
vids[i].width=iW;
}
else {
vids[i].height=iH-5;
vids[i].width=Math.floor(vidW[i]*r);
}
}
Unfotunately, here appeared some extra space; in FireFox I have found its minimal value as 5 that I negate form windows height value (iH) as the new video size.
Duplicate issue on the height posted at HTML5 Video dimensions in Safari IOS
Pure CSS solution provided in: https://stackoverflow.com/a/60878701/2486998
You can add style:
object-fit: contain;
In Angular if video player (shaka player in my case) is a separate component, this works perfectly (either height or width of container will cause resize of the player)
HTML
<div id="videoContainer"
class="videoContainer">
<video id="videoPlayer"></video>
</div>
CSS
.videoContainer
{
height:100%;
width:100%;
}
.videoContainer video
{
width: 100%;
height: auto;
max-width: 100%;
max-height: 100%;
}
Related
Hello everyone~ I have a problem but my English is not good. I will try my best to express it completely! If the explanation is not clear enough, everyone is welcome to tell me~ The
problem is like this, today there is a block for users to upload photos !
The width and height of this photo after uploading by the user
cannot exceed 360px, the minimum cannot be less than 100px, the
maximum height cannot exceed 200px, and the minimum cannot be less than 100px
.
What I want to ask everyone here is, can this requirement be accomplished only by CSS?
Or can it be accomplished by using JavaScript? But if I use JavaScript, I don't know how to start, because my JavaScript is very poor. I hope I can get your valuable suggestions here, thank you.
I wrote an example. The original picture size is only 50PX in height. How can the height of the photo reach 100PX without affecting the ratio?
.photo{
width: 360px;
height: 200px;
object-fit:contain;
object-position:left center
}
<div class="demo">
<img class="photo" src="https://upload.cc/i1/2021/09/30/s73jb5.jpg" alt="">
</div>
I think this is what you want to do.
Image should have maximum-width to be 360px and minimum height should be 100px.
And also if you want to add min-width and max-height you can add in imageSettings variable in javascript.
If you have multiple images, simply add imageContainerForJS class to img parent element.
(()=>{
let imgContainers = Array.from(document.querySelectorAll('.imageContainerForJS'));
const imageSettings = {
"max-width": 360,
"min-height": 100,
}
for(let imgContainer of imgContainers) {
let img = imgContainer.querySelector('img');
if(!img) continue;
let imageSource = img.src;
let image = new Image();
let maxWidth = imageSettings['max-width'] || null;
let minWidth = imageSettings['min-width'] || 0;
let maxHeight = imageSettings['max-height'] || null;
let minHeight = imageSettings['min-height'] || 0;
image.onload = function() {
let width = this.width;
let height = this.height;
if(maxWidth && width > maxWidth) width = maxWidth;
if(minWidth && width < minWidth) width = minWidth;
if(minHeight && height < minHeight) height = minHeight;
if(maxHeight && height > maxHeight) height = maxHeight;
imgContainer.style.width = width+'px';
imgContainer.style.height = height+'px';
}
image.src = imageSource;
}
})();
.photo{
object-fit: cover;
object-position: center;
width: 100%;
height: 100%;
}
<div class="demo imageContainerForJS">
<img class="photo" src="https://upload.cc/i1/2021/09/30/s73jb5.jpg" alt="">
</div>
You can use object-fit:cover to make your image proportionally expand to fill its container.
Set the container to the dimensions you want, then have the image fill it by setting its width and height be 100%.
By default cover will position the image in the centre.
.demo {
width: 360px;
height: 200px;
}
.demo .photo {
width: 100%;
height: 100%;
object-fit: cover;
/*object-position: left center;*/
}
<div class="demo">
<img class="photo" src="https://upload.cc/i1/2021/09/30/s73jb5.jpg" alt="">
</div>
I'm using a full screen canvas as background of the first section of my page. But as soon as I add the second section and vertical scrollbar appears, the height of canvas reduces a little bit and a gap appears. here's my code:
P.S: Sorry, my code contained bugs, I fixed them. now you can see the red gap.
var canvas = document.getElementById('canvas')
var c = canvas.getContext('2d')
scaleCanvas()
window.addEventListener("resize", scaleCanvas)
function scaleCanvas() {
canvas.width = window.innerWidth
canvas.height = window.innerHeight
c.fillStyle = 'black'
c.fillRect(0, 0, canvas.width, canvas.height)
}
* {
box-sizing: border-box;
max-width: 100%;
}
body {
margin: 0;
padding: 0;
}
#first-section {
position: relative;
min-height: 100vh;
background-color: red; /* to see the gap */
}
#content {
position: relative;
z-index: 2;
}
#second-section {
min-height: 100vh;
background-color: blue;
}
#canvas {
display: block;
padding: 0;
margin: 0;
border: none;
position: absolute;
top: 0;
left: 0;
z-index: 1;
}
<div id="first-section">
<canvas id="canvas"></canvas>
<div id="content">content</div>
</div>
<div id="second-section"></div>
Assuming you mean full screen, and not full page. The two are very different.
If you mean full page then the link to the Screen API will also give you details on obtaining the page size.
Size full screen canvas.
The problem is that you have content that extends outside the page width and height (innerWidth, innerHeight)
The elements with ids first-section, content, and second-section must be inside the display area or else you will get a scroll bar. The scroll bar will change the innerWidth, innerHeight values subtracting the scrollbar width or height depending on which is visible.
To prevent scroll bars the best option is to keep all content inside innerWidth, and innerHeight
Full screen with scroll bars.
If you want have the scroll bars and you are using full screen you can use the Screen API to get the width and height of the display in pixels. You can set the canvas size to match the screen without the scroll bars effecting its size.
Note Do read the provided link to Screen as what defines the screen may not be as expected. EG more than one monitor, or device orientation will effect how you use the API.
Basic example
Thus when in full-screen mode you can set the canvas size and ignore scroll bars with
function sizeFullScreenCanvas() {
canvas.width = screen.width;
canvas.height= screen.height;
}
I've got a background video playing on a web page, and this CSS;
#video_background {
position: fixed;
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
top: 0px;
left: 0px;
z-index: -1000;
overflow: hidden;
}
..is keeping it centered, like I want it to, but it's keeping all of the edges within the browser window, rather than always being full-bleed. I'm trying to replicate what this site is doing;
http://marisapassos.com/#home
This site appears to have two sets of rules, one on a div that contains the video, and one on the video itself. Could someone explain to me why that works and what I'm doing doesn't? Is there also js working to keep the video on the linked site centered?
Yes, look at the video_background.js in the source of the website you linked to, specifically at the $(window).resize function:
$(window).resize(function() {
var windowWidth = $(window).width();
var windowHeight = $(window).height();
var width;
var height;
//size
width = windowWidth;
height = width*formH/formW;
if(height<windowHeight){
height = windowHeight;
width = formW*height/formH;
}
$div_holder.css("width", width);
$div_holder.css("height", height);
$div_holder.css("left", windowWidth/2-width/2);
$div_holder.css("top", windowHeight/2-height/2);
});
Left and top are defined in terms of both the windowWidth and (video) width which keeps the video centered.
I would like to have my element keep its aspect ratio but act as a 'full-bleed' or rather full browser experience. The video should up or down to accommodate the new browser window dimensions, but also be centered in the browser window. At times, some video will get cropped – that's ok with me. I am trying to recreate the background cover CSS property for the video element using pure JS, if that helps you to imagine it. For those who do not know what that is, heres the following:
.bkgdCover{
background: no-repeat center center;
-webkit-background-size: 100% 100%;
-moz-background-size: cover;
-o-background-size: cover;
background-size: cover;
}
The following is my attempt to do the same in pure javascript:
function getWinSize(){
var wid = 0, hei = 0;
if (document.documentElement && document.documentElement.clientHeight){
wid = parseInt(window.innerWidth,10);
hei = parseInt(window.innerHeight,10);
} else if (document.body){
wid = parseInt(document.body.offsetWidth,10);
hei = parseInt(document.body.offsetHeight,10);
}
return [wid,hei];
}
this.resize2 = function(){
fullBleedVideoPlayer();
};
function fullBleedVideoPlayer() {
var viewport=getWinSize();
var videoRatio = 1080 / 1920;
var browserHeight = viewport[0];
var browserWidth = viewport[1];
var tmp_windowRatio = viewport[1] / viewport[0];
if (videoRatio > tmp_windowRatio) {
tmp_height = Math.round(browserWidth * videoRatio);
_player.style.width= browserWidth+ "px";
_player.style.height= tmp_height+ "px";
_player.style.marginLeft = 0 + 'px';
_player.style.marginTop = -Math.round((tmp_height - browserHeight) / 2) + 'px';
} else {
tmp_width = Math.round(browserHeight * (1 / videoRatio));
_player.style.width= tmp_width+ "px";
_player.style.height= browserHeight+ "px";
_player.style.marginLeft = -Math.round((tmp_width - browserWidth) / 2) + 'px';
_player.style.marginTop = 0 + 'px';
}
}
Unfortunately, this does not reproduce CSS cover. If you can see where I made a mistake or have done the same yourself, I'd love to hear from you. Only pure JS solutions please.
I just did something like this except it wasn't completely full screen, it was the background video of a page header which had a height of 450px'ish'. I say ish because I'm using 25vw and it's changing height based on viewport width. I basically wanted the video to stay centered, but how?
HTML
<section id="homepage--hero">
<div class="fullpage-video-wrapper">
<video id="video_background" preload="auto" autoplay="true" loop="loop" muted="muted" volume="0">
<source src="http://vjs.zencdn.net/v/oceans.mp4" type="video/mp4">
<source src="http://vjs.zencdn.net/v/oceans.webm" type="video/webm">
<!-- doesnt support video -->
<img src="#" style="width: 100%; height: auto;" />
</video>
</div>
</section>
CSS
#homepage-hero {
display: block;
height: 35vw;
width: 100%;
position:
relative;
overflow: hidden;
}
.fullpage-video-wrapper {
position: absolute;
bottom: 0px;
left: 0px;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -1000;
overflow: hidden;
}
.fullpage-video-wrapper {
min-height: 100%;
min-width: 100%;
}
JS
if( $('.fullpage-video-wrapper').length > 0 ) {
var videoWrapper = $('.fullpage-video-wrapper'),
videoParentWrapper = $(videoWrapper).parent();
if($(videoWrapper).height() > $(videoParentWrapper).height() ) {
var difference = ($(videoWrapper).height() - $(videoParentWrapper).height()) / 4
$(videoWrapper).css({
bottom: -parseInt(difference)
});
}
$(window).resize(function(){
if($(videoWrapper).height() > $(videoParentWrapper).height() ) {
var difference = ($(videoWrapper).height() - $(videoParentWrapper).height()) / 4
$(videoWrapper).css({
bottom: -parseInt(difference)
});
}
});
}
What this does is makes the video stay the same aspect ratio even when resizing window, positions it to the bottom of the homepage-hero, which this caused it to respond well without causing you to see the background color of the video-wrapper, but obviously not centered.
The jQuery is just setting the videowrapper to be offset the difference in height of the video wrapper element height and it's parent elements height. allowing the aspect ratio to stay the same, bleeding the video when needed but allowing it to be centered in it's parents element vertically.
This was super rough, since I was just working on this about an hour ago, so I'm sure theres plenty I need to rework through and get dialed in, but hopefully this helps you along your path, should be the same solution except your doing your height checks on the video element or video wrap element outerHeight and the viewport height.
I have a problem to get my window size, I try this code:
Javascript
var game;
function game() {
this.canvas = document.getElementById('canvas');
this.canvasWidth = window.innerWidth;
this.canvasHeight = window.innerHeight;
this.initCanvas = function() {
this.canvas.style.width = this.canvasWidth + "px";
this.canvas.style.height = this.canvasHeight + "px";
}
this.run = function() {
this.initCanvas();
}
}
game = new game();
game.run();
I also have
CSS
html, body {
padding: 0;
margin: 0;
}
I only have a canvas in my body.
Problem is, that I have a vertical and horizontal scroll bar. This means the size of canvas is too large. How to make it of the window size without the scroll bars appearing?
It looks like you're just trying to make your canvas have a width and height of 100%. You can do this with just css:
HTML
<body>
<canvas id="canvas"></canvas>
</body>
CSS
body, html {
height: 100%;
width: 100%;
margin: 0px;
}
canvas {
background: #ffcccc;
height: 100%;
width: 100%;
display: block;
}
Demo
Or if you want to use your code but get rid of the scroll bars on the window, you need to specify block on the canvas tag.
CSS
canvas {
display: block;
}
Demo
When you use CSS to style your <canvas> element it will get scaled instead of sized. Be sure to set the .width and .height properties on the canvas element instead (ie canvas.width not canvas.style.width).
jsfiddle example
In the example the first canvas element is scaled correctly, the second (using CSS) is not scaled properly. This has to do with a default canvas element size (300x150) that CSS scales.
To prevent getting scrollbars when setting the <canvas> to the full window width/height set the body to overflow:hidden; as used in the jsfiddle above.