¿Cómo puedo simular la funcionalidad de background-size:cover
un elemento html como <video>
o <img>
?
Me gustaría que funcionara como
background-size: cover;
background-position: center center;
¿Cómo puedo simular la funcionalidad de background-size:cover
un elemento html como <video>
o <img>
?
Me gustaría que funcionara como
background-size: cover;
background-position: center center;
Respuestas:
Esto es algo por lo que me saqué el pelo por un tiempo, pero encontré una gran solución que no usa ningún script y puede lograr una simulación de portada perfecta en video con 5 líneas de CSS (9 si cuenta selectores y paréntesis) ) Esto tiene 0 casos extremos en los que no funciona perfectamente, salvo la compatibilidad con CSS3 .
Puedes ver un ejemplo aquí
El problema con la solución de Timothy es que no maneja la escala correctamente. Si el elemento circundante es más pequeño que el archivo de video, no se reduce. Incluso si le da a la etiqueta de video un tamaño inicial pequeño, como 16px por 9px, auto
termina forzándolo a un mínimo de su tamaño de archivo nativo. Con la solución actual más votada en esta página, fue imposible para mí reducir la escala del archivo de video, lo que resultó en un efecto de zoom drástico.
Sin embargo, si se conoce la relación de aspecto de su video, como 16: 9, puede hacer lo siguiente:
.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 */
}
Si el elemento principal del video está configurado para cubrir toda la página (como position: fixed; width: 100%; height: 100vh;
), entonces el video también lo hará.
Si desea que el video también se centre, puede usar el enfoque de centrado seguro:
/* 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 */
}
Por supuesto, vw
, vh
, y transform
son CSS3, así que si necesita compatibilidad con navegadores mucho más antiguas , que necesita para el uso de la escritura.
vh
y vw
qué hacer con algo?
El uso de la cubierta de fondo está bien para las imágenes, y también el ancho al 100%. Estos no son óptimos <video>
y estas respuestas son demasiado complicadas. No necesita jQuery o JavaScript para lograr un fondo de video de ancho completo.
Tenga en cuenta que mi código no cubrirá un fondo completamente con un video como lo hará la cubierta, sino que hará que el video sea tan grande como sea necesario para mantener la relación de aspecto y aún cubrir todo el fondo. Cualquier exceso de video se desangrará del borde de la página, cuyos lados dependen de dónde se ancla el video.
La respuesta es bastante simple.
Simplemente use este código de video HTML5, o algo por el estilo: (prueba en página completa)
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>
La altura mínima y la anchura mínima permitirán que el video mantenga la relación de aspecto del video, que generalmente es la relación de aspecto de cualquier navegador normal con una resolución normal. Cualquier exceso de video sale por el costado de la página.
min-width
omin-height
hace el truco.
position: absolute; left: 50%; top: 50%; transform: translateX(-50%) translateY(-50%);
.
height: 100%; width: 100%;
. gracias por esta respuesta moderna
Así es como hice esto. Un ejemplo de trabajo está en este 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%; }
y funciona de maravilla.
background-size: cover
para un video.
Las otras respuestas fueron buenas, pero incluyen JavaScript o no centran el video horizontal y verticalmente.
Puede usar esta solución CSS completa para tener un video que simule el tamaño de fondo: propiedad de portada:
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;
}
Basado en la respuesta y los comentarios de Daniel de Wit , busqué un poco más. Gracias a él por la solución.
La solución es usar object-fit: cover;
un soporte excelente (todos los navegadores modernos lo admiten). Si realmente desea admitir IE, puede usar un polyfill como object-fit-images o object-fit .
Demos:
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"/>
y con un padre:
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
y width
y height
configurado al 100%, obtienes una escala proporcional img
o video
ampliada en el centro sin ningún problema.
La solución de M-Pixel es excelente ya que resuelve el problema de escala de la respuesta de Timothy (el video se ampliará pero no se reducirá, por lo que si su video es realmente grande, hay buenas posibilidades de que solo vea un pequeño zoom en una parte). Sin embargo, esa solución se basa en suposiciones falsas relacionadas con el tamaño del contenedor de video, es decir, que es necesariamente el 100% del ancho y alto de la ventana gráfica. He encontrado algunos casos en los que no funcionó para mí, así que decidí abordar el problema yo mismo y creo que se me ocurrió la solución 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%);
}
También se basa en la proporción del video, por lo que si su video tiene una proporción diferente a 16/9, querrá cambiar el% del relleno inferior. Aparte de eso, funciona fuera de la caja. Probado en IE9 +, Safari 9.0.1, Chrome 46 y Firefox 41.
Desde que he publicado esta respuesta que he escrito un pequeño módulo de CSS para simular tanto background-size: cover
y background-size: contain
en <video>
elementos: http://codepen.io/benface/pen/NNdBMj
Admite diferentes alineaciones para el video (similar a background-position
). También tenga en cuenta que la contain
implementación no es perfecta. A diferencia background-size: contain
, no escalará el video más allá de su tamaño real si el ancho y la altura del contenedor son mayores, pero creo que aún puede ser útil en algunos casos. También he añadido especial fill-width
y fill-height
clases que se pueden utilizar junto con contain
obtener una mezcla especial de contain
e cover
... probarlo, y sentir la libertad de mejorarla!
object-fit: cover
para FF y Chrome y su solución con Modernizr para IE
object-fit: cover
es la mejor respuesta con este IE, Safari polyfill.
https://github.com/constancecchen/object-fit-polyfill
Es de apoyo img
, video
y picture
elementos.
CSS y little js pueden hacer que el video cubra el fondo y se centre 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: (une esto con el cambio de tamaño de la ventana y llama una vez por separado)
$('#bgvid').css({
marginLeft : '-' + ($('#bgvid').width()/2) + 'px'
})
Justo después de nuestra larga sección de comentarios, creo que esto es lo que estás buscando, está basado en 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;
}
El código anterior está usando el ancho y la altura de los navegadores si hicieras esto dentro de un div, deberías cambiarlo a algo como esto:
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;
}
También debo decir que solo he probado que esto es Google Chrome ... aquí hay un jsfiddle: http://jsfiddle.net/ADCKk/
La respuesta principal no reduce el video cuando se encuentra en anchos de navegador inferiores al ancho de su video. Intenta usar este CSS (con #bgvid como la identificación de tu video):
#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
necesario lo negativo ?
También voy a publicar esta solución, ya que tuve este problema pero las otras soluciones no funcionaron para mi situación ...
Creo que para simular correctamente la background-size:cover;
propiedad css en un elemento en lugar de una propiedad de imagen de fondo de los elementos, tendría que comparar la relación de aspecto de las imágenes con la relación de aspecto de Windows actual, así que no importa qué tamaño (y también en caso de que la imagen sea más alto que más ancho) la ventana es el elemento que llena la ventana (y también la centra, aunque no sé si eso era un requisito) ...
usando una imagen, solo por simplicidad, estoy seguro de que un elemento de video también funcionará bien.
primero obtenga la relación de aspecto de los elementos (una vez cargada), luego adjunte el controlador de cambio de tamaño de la ventana, actívelo una vez para el tamaño 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();
}
luego, en su controlador de cambio de tamaño, primero debe determinar si se debe llenar el ancho o la altura del relleno comparando la relación de aspecto actual de la ventana con la relación de aspecto original de la imagen.
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";
}
}
Este enfoque solo usa css y html. En realidad, puedes apilar un div debajo del video fácilmente. Está cubierto pero no centrado mientras cambia el tamaño.
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 pregunta tiene una recompensa abierta por valor de +100 reputación de Hidden Hobbes que termina en 6 días. Uso ingenioso de las unidades de ventana gráfica para obtener una solución flexible de solo CSS.
Abriste una recompensa por esta pregunta para una solución única de CSS, así que lo intentaré. Mi solución a un problema como este es usar una relación fija para decidir la altura y el ancho del video. Usualmente uso Bootstrap, pero extraje el CSS necesario de allí para que funcione sin él. Este es un código que he usado anteriormente para centrar, entre otras cosas, un video incrustado con la proporción correcta. Se debe trabajar para <video>
y <img>
elementos también Es la parte superior que es relevante aquí, pero les dio a los otros dos, así como ya tenía ellos por ahí. ¡La mejor de las suertes! :)
Ejemplo de pantalla completa de 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 al comentario de Weotch de que la respuesta de Timothy Ryan Carpenter no tiene en cuenta cover
el centrado del fondo, ofrezco esta solución rápida de CSS:
CSS:
margin-left: 50%;
transform: translateX(-50%);
Agregar estas dos líneas centrará cualquier elemento. Aún mejor, todos los navegadores que pueden manejar video HTML5 también admiten transformaciones CSS3, por lo que esto siempre funcionará.
El CSS completo se ve así.
#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%);
}
Hubiera comentado directamente sobre la respuesta de Timothy, pero no tengo suficiente reputación para hacerlo.
Chicos, tengo una solución mejor, es corta y funciona perfectamente para mí. Lo usé para video. Y emula perfectamente la opción de portada en 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%");
}
});
Si voltea el if, de lo contrario obtendrá contener.
Y aquí está el CSS. (No necesita usarlo si no desea posicionamiento central, el div padre debe ser " position: relative ")
CSS
video {
position: absolute;
-webkit-transform: translateX(-50%) translateY(-50%);
transform: translateX(-50%) translateY(-50%);
top: 50%;
left: 50%;}
Acabo de resolver esto y quería compartir. Esto funciona con Bootstrap 4. Funciona con img
pero no lo probé video
. Aquí está el HAML y 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>
Antigua pregunta, pero en caso de que alguien vea esto, la mejor respuesta en mi opinión es convertir el video en un GIF animado. Esto te da mucho más control y puedes tratarlo como una imagen. También es la única forma de que funcione en dispositivos móviles, ya que no puede reproducir videos automáticamente. Sé que la pregunta es hacerlo en una <img>
etiqueta, pero realmente no veo la desventaja de usar ay <div>
hacerbackground-size: cover
.gif
es mucho más grande, pero también más borroso. Mi opinión ha cambiado desde que escribí esta respuesta. Es una pena que no puedas combinar lo mejor de ambos.