javascript - 在 <video> 或 <img> 上模擬 background-size:cover
我如何在像 <video> 或 <img> 這樣的 HTML 元素上模擬 background-size:cover 的功能?
我希望它可以像…一樣運作
background-size: cover;
background-position: center center;
答案#1
這件事我為此曾經非常煩惱,但我找到了一個極佳的解決方案,不需要使用任何腳本,只用五行 CSS(如果算上選擇器和大括號則為九行)就能在影片上達到完美的遮罩模擬效果。除了 CSS3 相容性問題以外,這幾乎沒有任何例外情況會導致它無法完美運作。
你可以在這裡看到一個範例 這裡(已存檔)
提摩太的解決方案的問題在於,它無法正確處理縮放。如果周圍的元素比影片檔案小,它不會縮小。即使你給影片標籤一個非常小的初始尺寸,例如16px乘9px,auto仍會將其強制設為原始檔案尺寸的最小值。根據這個頁面上目前票選最高的解決方案,我無法讓影片檔案縮小,導致出現極大的縮放效果。
然而,如果已知影片的寬高比,例如 16:9,你可以進行以下操作:
.parent-element-to-video {
overflow: hidden;
}
video {
height: 100%;
width: 177.77777778vh; /* 100 * 16 / 9 */
min-width: 100%;
min-height: 56.25vw; /* 100 * 9 / 16 */
}
如果視頻的父元素設置為覆蓋整個頁面(例如 position: fixed; width: 100%; height: 100vh;),那麼視頻也會如此。
如果你也想讓影片置中,你可以使用可靠的置中方法:
/* merge with above css */
.parent-element-to-video {
position: relative; /* or absolute or fixed */
}
video {
position: absolute;
left: 50%; /* % of surrounding element */
top: 50%;
transform: translate(-50%, -50%); /* % of current element */
}
當然,vw、vh 和 transform 都是 CSS3,因此如果你需要與較舊的瀏覽器兼容,就需要使用腳本。
答案#2
對於某些瀏覽器你可以使用
object-fit: cover;
http://caniuse.com/object-fit
答案#3
jsFiddle
對於圖片使用背景覆蓋是可以的,寬度設為100%也可以。但這些對於<video>並非最佳選擇,而且這些答案過於複雜。你不需要 jQuery 或 JavaScript 就可以實現全寬的視頻背景。
請記住,我的程式碼不會像 cover 那樣完全用影片覆蓋背景,而是會讓影片保持所需的大小以維持長寬比,同時仍能覆蓋整個背景。任何多餘的影片部分將超出頁面邊緣,超出的邊界取決於你將影片錨定的位置。
答案非常簡單。
只需使用這段 HTML5 視頻代碼,或類似的東西:(在全頁模式下測試)
html, body {
width: 100%;
height:100%;
overflow:hidden;
}
#vid{
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -1000;
overflow: hidden;
}<video id="vid" video autobuffer autoplay>
<source id="mp4" src="http://grochtdreis.de/fuer-jsfiddle/video/sintel_trailer-480.mp4" type="video/mp4">
</video>最小高度和最小寬度將允許視頻保持視頻的長寬比,這通常是任何正常瀏覽器在正常分辨率下的長寬比。任何多餘的視頻會從頁面的一側溢出。
答案#4
這是我如何做到的。這個 jsFiddle 中有一個可運作的範例。
var min_w = 300; // minimum video width allowed
var vid_w_orig; // original video dimensions
var vid_h_orig;
jQuery(function() { // runs after DOM has loaded
vid_w_orig = parseInt(jQuery('video').attr('width'));
vid_h_orig = parseInt(jQuery('video').attr('height'));
$('#debug').append("<p>DOM loaded</p>");
jQuery(window).resize(function () { resizeToCover(); });
jQuery(window).trigger('resize');
});
function resizeToCover() {
// set the video viewport to the window size
jQuery('#video-viewport').width(jQuery(window).width());
jQuery('#video-viewport').height(jQuery(window).height());
// use largest scale factor of horizontal/vertical
var scale_h = jQuery(window).width() / vid_w_orig;
var scale_v = jQuery(window).height() / vid_h_orig;
var scale = scale_h > scale_v ? scale_h : scale_v;
// don't allow scaled width < minimum video width
if (scale * vid_w_orig < min_w) {scale = min_w / vid_w_orig;};
// now scale the video
jQuery('video').width(scale * vid_w_orig);
jQuery('video').height(scale * vid_h_orig);
// and center it by scrolling the video viewport
jQuery('#video-viewport').scrollLeft((jQuery('video').width() - jQuery(window).width()) / 2);
jQuery('#video-viewport').scrollTop((jQuery('video').height() - jQuery(window).height()) / 2);
// debug output
jQuery('#debug').html("<p>win_w: " + jQuery(window).width() + "</p>");
jQuery('#debug').append("<p>win_h: " + jQuery(window).height() + "</p>");
jQuery('#debug').append("<p>viewport_w: " + jQuery('#video-viewport').width() + "</p>");
jQuery('#debug').append("<p>viewport_h: " + jQuery('#video-viewport').height() + "</p>");
jQuery('#debug').append("<p>video_w: " + jQuery('video').width() + "</p>");
jQuery('#debug').append("<p>video_h: " + jQuery('video').height() + "</p>");
jQuery('#debug').append("<p>vid_w_orig: " + vid_w_orig + "</p>");
jQuery('#debug').append("<p>vid_h_orig: " + vid_h_orig + "</p>");
jQuery('#debug').append("<p>scale: " + scale + "</p>");
};#video-viewport {
position: absolute;
top: 0;
overflow: hidden;
z-index: -1; /* for accessing the video by click */
}
#debug {
position: absolute;
top: 0;
z-index: 100;
color: #fff;
font-size: 12pt;
}<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="video-viewport">
<video autoplay controls preload width="640" height="360">
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4"type="video/mp4" />
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.webm"type="video/webm" />
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.ogv"type="video/webm" />
</video>
</div>
<div id="debug"></div>答案#5
根據 Daniel de Wit 的回答和評論,我又多搜尋了一些。感謝他提供的解決方案。
解決方案是使用 object-fit: cover;,它有很好的支援(每個現代瀏覽器都支援)。如果你真的想支援 IE,你可以使用像 object-fit-images 或 object-fit 這樣的 polyfill。
示範:
img {
float: left;
width: 100px;
height: 80px;
border: 1px solid black;
margin-right: 1em;
}
.fill {
object-fit: fill;
}
.contain {
object-fit: contain;
}
.cover {
object-fit: cover;
}
.none {
object-fit: none;
}
.scale-down {
object-fit: scale-down;
}<img class="fill" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
<img class="contain" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
<img class="cover" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
<img class="none" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
<img class="scale-down" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>以及和父母一起:
div {
float: left;
width: 100px;
height: 80px;
border: 1px solid black;
margin-right: 1em;
}
img {
width: 100%;
height: 100%;
}
.fill {
object-fit: fill;
}
.contain {
object-fit: contain;
}
.cover {
object-fit: cover;
}
.none {
object-fit: none;
}
.scale-down {
object-fit: scale-down;
}<div>
<img class="fill" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="contain" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="cover" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="none" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div><div>
<img class="scale-down" src="http://www.peppercarrot.com/data/wiki/medias/img/chara_carrot.jpg"/>
</div>答案#6
其他答案不錯,但它們涉及到 JavaScript,或者它們無法水平和垂直地置中視頻。
你可以使用這個完整的 CSS 解決方案來讓影片模擬 background-size: cover 屬性:
video {
position: fixed; // Make it full screen (fixed)
right: 0;
bottom: 0;
z-index: -1; // Put on background
min-width: 100%; // Expand video
min-height: 100%;
width: auto; // Keep aspect ratio
height: auto;
top: 50%; // Vertical center offset
left: 50%; // Horizontal center offset
-webkit-transform: translate(-50%,-50%);
-moz-transform: translate(-50%,-50%);
-ms-transform: translate(-50%,-50%);
transform: translate(-50%,-50%); // Cover effect: compensate the offset
background: url(bkg.jpg) no-repeat; // Background placeholder, not always needed
background-size: cover;
}
答案#7
M-Pixel 的解決方案很棒,因為它解決了 Timothy 回答中的縮放問題(視頻會放大但不會縮小,所以如果你的視頻真的很大,很可能你只會看到其中的一小部分放大畫面)。然而,這個解決方案是基於關於視頻容器大小的錯誤假設,即它必須是視口寬度和高度的 100%。我發現有一些情況下它對我不起作用,所以我決定自己解決這個問題,我相信我想出了一個終極解決方案。
HTML
<div class="parent-container">
<div class="video-container">
<video width="1920" height="1080" preload="auto" autoplay loop>
<source src="video.mp4" type="video/mp4">
</video>
</div>
</div>
CSS
.parent-container {
/* any width or height */
position: relative;
overflow: hidden;
}
.video-container {
width: 100%;
min-height: 100%;
position: absolute;
left: 0px;
/* center vertically */
top: 50%;
-moz-transform: translate(0%, -50%);
-ms-transform: translate(0%, -50%);
-webkit-transform: translate(0%, -50%);
transform: translate(0%, -50%);
}
.video-container::before {
content: "";
display: block;
height: 0px;
padding-bottom: 56.25%; /* 100% * 9 / 16 */
}
.video-container video {
width: auto;
height: 100%;
position: absolute;
top: 0px;
/* center horizontally */
left: 50%;
-moz-transform: translate(-50%, 0%);
-ms-transform: translate(-50%, 0%);
-webkit-transform: translate(-50%, 0%);
transform: translate(-50%, 0%);
}
它也基於影片的比例,因此如果你的影片比例不是16/9,你會想要更改底部填充的百分比。除此之外,它可以直接使用。已在IE9+、Safari 9.0.1、Chrome 46和Firefox 41中測試過。
編輯(2016年3月17日)
自從我發佈這個答案後,我寫了一個小型 CSS 模組來模擬 background-size: cover 和 background-size: contain 在 <video> 元素上的效果: http://codepen.io/benface/pen/NNdBMj
它支援影片的不同對齊方式(類似於 background-position)。此外請注意,contain 的實作並不完美。與 background-size: contain 不同,它不會在容器的寬度和高度較大時超過影片的實際大小進行縮放,但我認為在某些情況下仍然可以使用。我還添加了特殊的 fill-width 和 fill-height 類別,你可以與 contain 一起使用,以獲得 contain 與 cover 的特殊混合效果……試試看,並隨時提升它吧!
