Como posso simular a funcionalidade de background-size:cover
um elemento html como <video>
ou <img>
?
Eu gostaria que funcionasse como
background-size: cover;
background-position: center center;
Como posso simular a funcionalidade de background-size:cover
um elemento html como <video>
ou <img>
?
Eu gostaria que funcionasse como
background-size: cover;
background-position: center center;
Respostas:
Isso é algo que eu deixei de lado por um tempo, mas me deparei com uma ótima solução que não usa nenhum script e pode conseguir uma simulação de capa perfeita em vídeo com 5 linhas de CSS (9 se você contar seletores e colchetes ) Isso tem 0 casos extremos nos quais não funciona perfeitamente, com falta de compatibilidade com CSS3 .
Você pode ver um exemplo aqui
O problema com a solução de Timothy é que ele não manipula a escala corretamente. Se o elemento circundante for menor que o arquivo de vídeo, ele não será reduzido. Mesmo se você der à tag de vídeo um tamanho inicial minúsculo, como 16 x 9 px, auto
acaba forçando-a a um mínimo do tamanho do arquivo nativo. Com a atual solução mais votada nesta página, era impossível reduzir o arquivo de vídeo, resultando em um efeito de zoom drástico.
Se a proporção do seu vídeo for conhecida, no entanto, como 16: 9, você poderá fazer o seguinte:
.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 */
}
Se o elemento pai do vídeo estiver definido para cobrir a página inteira (como position: fixed; width: 100%; height: 100vh;
), o vídeo também será.
Se você também deseja que o vídeo seja centralizado, use a abordagem de centralização segura:
/* 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 */
}
Claro, vw
, vh
, e transform
são CSS3, por isso, se você precisar de compatibilidade com browsers muito antigos , você precisa roteiro uso.
vh
e vw
tem a ver com alguma coisa?
O uso da capa de plano de fundo é bom para imagens e a largura é 100%. Elas não são ideais <video>
e essas respostas são excessivamente complicadas. Você não precisa de jQuery ou JavaScript para obter um plano de fundo de vídeo com largura total.
Lembre-se de que meu código não cobre completamente um plano de fundo com um vídeo como o da capa, mas aumentará o tamanho do vídeo para manter a proporção e ainda cobrir todo o plano de fundo. Qualquer excesso de vídeo sangrará na borda da página, cujos lados dependem de onde você ancora o vídeo.
A resposta é bem simples.
Basta usar este código de vídeo HTML5 ou algo assim: (teste em página inteira)
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>
A altura mínima e a largura mínima permitirão que o vídeo mantenha a proporção do vídeo, que geralmente é a proporção de qualquer navegador normal em uma resolução normal. Qualquer excesso de vídeo sangra na lateral da página.
min-width
ou min-height
faz o truque.
position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%);
.
height: 100%; width: 100%;
. obrigado por esta resposta moderna
Aqui está como eu fiz isso. Um exemplo de trabalho está neste 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>
video { min-width: 100%; min-height: 100%; }
e funciona como um encanto.
background-size: cover
um vídeo.
As outras respostas foram boas, mas envolvem javascript ou não centralizam o vídeo horizontalmente e verticalmente.
Você pode usar esta solução CSS completa para criar um vídeo que simule a propriedade 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;
}
Com base na resposta e nos comentários de Daniel de Wit , procurei um pouco mais. Obrigado a ele pela solução.
A solução é usar object-fit: cover;
um suporte excelente (todos os navegadores modernos oferecem suporte). Se você realmente deseja dar suporte ao IE, pode usar um polyfill como imagens de ajuste de objeto ou ajuste de objeto .
Demonstrações:
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"/>
e com um pai:
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>
object-fit: cover
e width
e height
definida para 100%, você tem uma proporcionalmente dimensionado img
ou video
ampliada no centro sem qualquer problema.
A solução da M-Pixel é ótima na medida em que resolve o problema de escala da resposta de Timothy (o vídeo aumenta, mas não diminui, por isso, se o seu vídeo for realmente grande, há boas chances de você ver apenas um pequeno zoom em parte dele). No entanto, essa solução é baseada em suposições falsas relacionadas ao tamanho do contêiner de vídeo, ou seja, é necessariamente 100% da largura e altura da janela de exibição. Encontrei alguns casos em que não funcionou para mim, então decidi resolver o problema pessoalmente e acredito que encontrei a solução definitiva .
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%);
}
Também se baseia na proporção do vídeo, portanto, se o seu vídeo tiver uma proporção diferente de 16/9, você desejará alterar a% do preenchimento inferior. Fora isso, funciona imediatamente. Testado no IE9 +, Safari 9.0.1, Chrome 46 e Firefox 41.
Desde que publiquei esta resposta, escrevi um pequeno módulo CSS para simular elementos background-size: cover
e background-size: contain
sobre <video>
: http://codepen.io/benface/pen/NNdBMj
Ele suporta alinhamentos diferentes para o vídeo (semelhante a background-position
). Observe também que a contain
implementação não é perfeita. Ao contrário background-size: contain
, ele não dimensionará o vídeo além do tamanho real se a largura e a altura do contêiner forem maiores, mas acho que ainda pode ser útil em alguns casos. Também adicionei aulas fill-width
e fill-height
classes especiais que você pode usar contain
para obter uma mistura especial contain
e cover
... experimentar e fique à vontade para aprimorá-la!
object-fit: cover
para FF e cromo e sua solução com Modernizr para o IE
object-fit: cover
é a melhor resposta com este polyfill do IE, Safari.
https://github.com/constancecchen/object-fit-polyfill
Está apoiando img
, video
e picture
elementos.
CSS e js pequenos podem fazer com que o vídeo cubra o plano de fundo e centralize-o horizontalmente.
CSS:
video#bgvid {
position: absolute;
bottom: 0px;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -1;
overflow: hidden;
}
JS: (vincule isso com redimensionamento de janela e chame uma vez separadamente)
$('#bgvid').css({
marginLeft : '-' + ($('#bgvid').width()/2) + 'px'
})
Logo após a nossa longa seção de comentários, acho que é isso que você está procurando, é baseado em jQuery:
HTML:
<img width="100%" id="img" src="http://uploads8.wikipaintings.org/images/william-adolphe-bouguereau/self-portrait-presented-to-m-sage-1886.jpg">
JS:
<script type="text/javascript">
window.onload = function(){
var img = document.getElementById('img')
if(img.clientHeight<$(window).height()){
img.style.height=$(window).height()+"px";
}
if(img.clientWidth<$(window).width()){
img.style.width=$(window).width()+"px";
}
}
</script>
CSS:
body{
overflow: hidden;
}
O código acima está usando a largura e a altura do navegador, se você estiver fazendo isso dentro de uma div, precisará alterá-lo para algo assim:
Para Div:
HTML:
<div style="width:100px; max-height: 100px;" id="div">
<img width="100%" id="img" src="http://uploads8.wikipaintings.org/images/william-adolphe-bouguereau/self-portrait-presented-to-m-sage-1886.jpg">
</div>
JS:
<script type="text/javascript">
window.onload = function(){
var img = document.getElementById('img')
if(img.clientHeight<$('#div').height()){
img.style.height=$('#div').height()+"px";
}
if(img.clientWidth<$('#div').width()){
img.style.width=$('#div').width()+"px";
}
}
</script>
CSS:
div{
overflow: hidden;
}
Também devo declarar que testei apenas este é o Google Chrome ... aqui está um jsfiddle: http://jsfiddle.net/ADCKk/
A resposta principal não diminui o tamanho do vídeo quando você está com larguras inferiores ao navegador. Tente usar este CSS (com #bgvid sendo o ID do seu vídeo):
#bgvid {
position: fixed;
top: 50%;
left: 50%;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
transform: translateX(-50%) translateY(-50%);
-webkit-transform: translateX(-50%) translateY(-50%);
}
z-index
necessário?
Eu também vou postar esta solução, já que tive esse problema, mas as outras soluções não funcionaram para a minha situação ...
Eu acho que para simular corretamente a background-size:cover;
propriedade css em um elemento em vez de uma propriedade de imagem de fundo de elementos, você teria que comparar a proporção da imagem com a proporção atual do Windows, portanto, independentemente do tamanho (e também no caso de a imagem ser mais alto que largo) a janela é o elemento que está preenchendo a janela (e também a centralizando, embora eu não saiba se isso era um requisito) ...
usando uma imagem, apenas por uma questão de simplicidade, tenho certeza de que um elemento de vídeo também funcionaria bem.
primeiro obtenha a proporção dos elementos (depois de carregada), depois anexe o manipulador de redimensionamento da janela e ative-o uma vez para o dimensionamento inicial:
var img = document.getElementById( "background-picture" ),
imgAspectRatio;
img.onload = function() {
// get images aspect ratio
imgAspectRatio = this.height / this.width;
// attach resize event and fire it once
window.onresize = resizeBackground;
window.onresize();
}
depois, no manipulador de redimensionamento, você deve primeiro determinar se deve preencher a largura ou a altura, comparando a proporção atual da janela com a proporção original da imagem.
function resizeBackground( evt ) {
// get window size and aspect ratio
var windowWidth = window.innerWidth,
windowHeight = window.innerHeight;
windowAspectRatio = windowHeight / windowWidth;
//compare window ratio to image ratio so you know which way the image should fill
if ( windowAspectRatio < imgAspectRatio ) {
// we are fill width
img.style.width = windowWidth + "px";
// and applying the correct aspect to the height now
img.style.height = (windowWidth * imgAspectRatio) + "px";
// this can be margin if your element is not positioned relatively, absolutely or fixed
// make sure image is always centered
img.style.left = "0px";
img.style.top = (windowHeight - (windowWidth * imgAspectRatio)) / 2 + "px";
} else { // same thing as above but filling height instead
img.style.height = windowHeight + "px";
img.style.width = (windowHeight / imgAspectRatio) + "px";
img.style.left = (windowWidth - (windowHeight / imgAspectRatio)) / 2 + "px";
img.style.top = "0px";
}
}
Essa abordagem usa apenas css e html. Você pode empilhar facilmente um divs abaixo do vídeo. É capa, mas não centralizada enquanto você redimensiona.
HTML:
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
</script>
</head>
<body>
<div id = "contain">
<div id="vid">
<video autoplay>
<source src="http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4" type="video/mp4" />
</video>
</div>
</div>
</body>
</html>
CCS:
/*
filename:style.css
*/
body {
margin:0;
}
#vid video{
position: absolute;
right: 0;
top: 0;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
}
#contain {
width:100%;
height:100%;
zoom:1%;/*Without this the video will be stretched and skewed*/
}
Esta pergunta tem uma recompensa aberta no valor de +100 reputação de Hidden Hobbes que termina em 6 dias. Uso inventivo de unidades de viewport para obter uma solução flexível apenas para CSS.
Você abriu uma recompensa nesta questão para uma solução apenas de CSS, então vou tentar. Minha solução para um problema como esse é usar uma proporção fixa para decidir a altura e a largura do vídeo. Eu normalmente uso o Bootstrap, mas extraí o CSS necessário para fazê-lo funcionar sem ele. Este é um código que usei anteriormente para centralizar, entre outras coisas, um vídeo incorporado com a proporção correta. Deve funcionar para <video>
e <img>
também para os elementos. É o principal que é relevante aqui, mas eu também dei os outros dois, já que eles já estavam por aí. Boa sorte! :)
exemplo em tela cheia jsfiddle
.embeddedContent.centeredContent {
margin: 0px auto;
}
.embeddedContent.rightAlignedContent {
margin: auto 0px auto auto;
}
.embeddedContent > .embeddedInnerWrapper {
position:relative;
display: block;
padding: 0;
padding-top: 42.8571%; /* 21:9 ratio */
}
.embeddedContent > .embeddedInnerWrapper > iframe {
position: absolute;
top: 0;
left: 0;
bottom: 0;
height: 100%;
width: 100%;
border: 0;
}
.embeddedContent {
max-width: 300px;
}
.box1text {
background-color: red;
}
/* snippet from Bootstrap */
.container {
margin-right: auto;
margin-left: auto;
}
.col-md-12 {
width: 100%;
}
<div class="container">
<div class="row">
<div class="col-md-12">
Testing ratio AND left/right/center align:<br />
<div class="box1text">
<div class="embeddedContent centeredContent">
<div class="embeddedInnerWrapper">
<iframe allowfullscreen="true" allowscriptaccess="always" frameborder="0" height="349" scrolling="no" src="//www.youtube.com/embed/u6XAPnuFjJc?wmode=transparent&jqoemcache=eE9xf" width="425"></iframe>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
Testing ratio AND left/right/center align:<br />
<div class="box1text">
<div class="embeddedContent rightAlignedContent">
<div class="embeddedInnerWrapper">
<iframe allowfullscreen="true" allowscriptaccess="always" frameborder="0" height="349" scrolling="no" src="//www.youtube.com/embed/u6XAPnuFjJc?wmode=transparent&jqoemcache=eE9xf" width="425"></iframe>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-12">
Testing ratio AND left/right/center align:<br />
<div class="box1text">
<div class="embeddedContent">
<div class="embeddedInnerWrapper">
<iframe allowfullscreen="true" allowscriptaccess="always" frameborder="0" height="349" scrolling="no" src="//www.youtube.com/embed/u6XAPnuFjJc?wmode=transparent&jqoemcache=eE9xf" width="425"></iframe>
</div>
</div>
</div>
</div>
</div>
</div>
Para responder ao comentário de Weotch de que a resposta de Timothy Ryan Carpenter não explica cover
a centralização do plano de fundo, ofereço esta rápida correção de CSS:
CSS:
margin-left: 50%;
transform: translateX(-50%);
A adição dessas duas linhas centralizará qualquer elemento. Melhor ainda, todos os navegadores que podem lidar com vídeo HTML5 também suportam transformações CSS3, portanto, isso sempre funcionará.
O CSS completo é assim.
#video-background {
position: absolute;
bottom: 0px;
right: 0px;
min-width: 100%;
min-height: 100%;
width: auto;
height: auto;
z-index: -1000;
overflow: hidden;
margin-left: 50%;
transform: translateX(-50%);
}
Eu teria comentado diretamente a resposta de Timothy, mas não tenho reputação suficiente para fazê-lo.
Gente, eu tenho uma solução melhor, é curta e funciona perfeitamente para mim. Eu usei para vídeo. E emula perfeitamente a opção de capa em css.
Javascript
$(window).resize(function(){
//use the aspect ration of your video or image instead 16/9
if($(window).width()/$(window).height()>16/9){
$("video").css("width","100%");
$("video").css("height","auto");
}
else{
$("video").css("width","auto");
$("video").css("height","100%");
}
});
Se você virar o if, senão você irá conter.
E aqui está o css. (Você não precisa usá-lo se não desejar o posicionamento central, a div principal deve ser " position: relativa ")
CSS
video {
position: absolute;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
top: 50%;
left: 50%;}
Acabei de resolver isso e queria compartilhar. Isso funciona com o Bootstrap 4. Ele funciona, img
mas eu não testei video
. Aqui está o HAML e o SCSS
HAML
.container
.detail-img.d-flex.align-items-center
%img{src: 'http://placehold.it/1000x700'}
SCSS
.detail-img { // simulate background: center/cover
max-height: 400px;
overflow: hidden;
img {
width: 100%;
}
}
/* simulate background: center/cover */
.center-cover {
max-height: 400px;
overflow: hidden;
}
.center-cover img {
width: 100%;
}
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet"/>
<div class="container">
<div class="center-cover d-flex align-items-center">
<img src="http://placehold.it/1000x700">
</div>
</div>
Pergunta antiga, mas caso alguém veja isso, a melhor resposta na minha opinião é converter o vídeo em um GIF animado. Isso lhe dá muito mais controle e você pode apenas tratá-lo como uma imagem. É também a única maneira de funcionar em dispositivos móveis, pois você não pode reproduzir vídeos automaticamente. Eu sei que a pergunta está pedindo para fazer isso em uma <img>
tag, mas realmente não vejo a desvantagem de usar <div>
aebackground-size: cover
.gif
tamanho é muito maior, além de borrado. Minha opinião mudou desde que escrevi esta resposta. É uma pena que você não possa combinar o melhor dos dois.