網站搜尋

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 的特殊混合效果……試試看,並隨時提升它吧!