HTML i dynamiczne dostosowanie rozmiaru video do szerokości i wysokości ekranu

Dziś mniej dywagacji, a trochę konkretów. Czyli jak dynamicznie dostosować w HTML rozmiar video do szerokości i wysokości ekranu.

W listopadzie pracowałam nad stroną rener.in i moim głównym zadaniem było poprawne wyświetlenie filmu – video miało zajmować cały ekran i dynamicznie dostosowywać się do zmiany szerokości ekranu (tzw. resize event). Nigdy wcześniej nie pracowałam z video w HTML-u, ale gdy zgłosili się do mnie sympatyczni panowie z Rener i przedstawili swoje oczekiwania, nie mogłam odmówić i nie skorzystać z wyzwania. Wzięłam się więc ochoczo do pracy.

W ruch poszedł Stack Overflow – jedno z moich ulubionych miejsc w sieci. Jak zgrabnie dostosować to video? (I jak je w ogóle wyświetlić???) Pomysłów było sporo, ale żaden mi nie odpowiadał. Jestem zwolenniczką prostych rozwiązań, a do tego perfekcjonistką, więc żaden zawiły lub prawie działający kod nie miał u mnie szans. Pozostała kartka papieru i długopis i powstało moje autorskie rozwiązanie. Działa tylko, jeśli znane są proporcje filmu – u mnie było to 16:9.

Najsampierw umieszczamy znacznik <video> w kodzie strony:

<video id="video" playsinline muted onplaying="this.controls=false" autoplay loop>
    <source id="mp4" src="" type="video/mp4">
    <source id="webm" src="" type="video/webm">
</video>

src dla <source> ustawiamy dynamicznie w JavaScript w zależności od szerokości ekranu.

I do dzieła!

window.addEventListener('resize', resize, false);

function resize() {
    if (window.innerWidth != previous_width) {
        previous_width = window.innerWidth;
  	var video = document.getElementById('video');
  	if (video) {
  	    var delta = 20;
  	    var window_width = window.innerWidth;
  	    var window_height = window.innerHeight;

  	    var width = window_width + delta;
  	    var height = width * 9 / 16;
  	    if (height < window_height) {
                height = window_height + delta;
                width = height * 16 / 9;
            }
            video.width = width;
            video.height = height;
        }
    }
}

gdzie previous_width jest ustawione na 0 przy załadowaniu strony (onLoad()), a delta to nasz bufor bezpieczeństwa, w razie gdyby dzielenie nie było całkowite.

Co tu się dzieje? Najpierw zakładamy, że szerokość ekranu jest większa niż jego wysokość i na jej podstawie obliczamy wysokość video (* 9 / 16). Potem sprawdzamy, czy wyliczona wysokość jest mniejsza niż wysokość ekranu. Jeśli tak, przyjmujemy wysokość ekranu za wysokość video i na jej podstawie obliczamy szerokość.

Myślę, że jest to dość eleganckie i proste rozwiązanie, a do tego przetestowane w BrowserStack.

Kompletny przykład

Poniżej kompletny przykład, który można skopiować. Wystarczy podmienić ścieżki do plików i ewentualnie zmodyfikować wysokość elementu fullscreen-video.

<div class="fullscreen-video">
  <video id="video" playsinline muted onplaying="this.controls=false" autoplay loop>
    <source id="mp4" src="" type="video/mp4">
    <source id="webm" src="" type="video/webm">
  </video>
</div>

<style>
  .fullscreen-video {height: calc(100vh - 60px); width: 100%; overflow: hidden; position: relative;}
  .fullscreen-video video {object-fit: cover; position: absolute; top: 0; left: 0;}
</style>

<script>
window.addEventListener('resize', resize, false);
window.addEventListener('load', onLoad, false);
function onLoad() {
  previous_width = 0;
  var video = document.getElementById('video');
  var mp4video = document.getElementById('mp4');
  var webmvideo = document.getElementById('webm');
  if (video) {
    resize();
    if (window.innerWidth < 576) {
      mp4video.src = "/wp-content/uploads/videos/film_small.mp4";
      webmvideo.src = "/wp-content/uploads/videos/film_small.webm";
      video.load();
    } else if (window.innerWidth < 1200) {
      mp4video.src = "/wp-content/uploads/videos/film_medium.mp4";
      webmvideo.src = "/wp-content/uploads/videos/film_medium.webm";
      video.load();
    } else {
      mp4video.src = "/wp-content/uploads/videos/film_medium.mp4";
      webmvideo.src = "/wp-content/uploads/videos/film_big.webm";
      video.load();
    }
  }
}

function resize() {
  if (window.innerWidth != previous_width) {
    previous_width = window.innerWidth;
    var video = document.getElementById('video');
    if (video) {
      var delta = 50;
      var window_width = window.innerWidth;
      var window_height = window.innerHeight;

      var width = window_width + delta;
      var height = width * 9 / 16;
      if (height < window_height) {
        height = window_height + delta;
        width = height * 16 / 9;
      }
      video.width = width;
      video.height = height;
    }
  }
}
var previous_width;
</script>
Pani Marta
Jestem Marta. Pani Marta. Od kilku lat pracuję w WordPressie i ciągle jestem pod wrażeniem jego możliwości. Na moim blogu dzielę się prostymi sposobami na bezwtyczkowe ulepszenie swojej strony. Jeśli brakuje Ci czegoś w tym wpisie lub chcesz, abym poruszyła temat, na którym Ci zależy, daj znać w komentarzu!

Dodaj komentarz

*

*

*

Twój adres e-mail nie zostanie opublikowany.

Komentarze

  1. Cześć, można to zastosować do strony opartej o WordPress? Próbuje zastosować to do Divi builder do modułu kod al e coś to nie działa.

    1. Cześć Rafał, jasne, powinno zadziałać. Dodałam do wpisu kompletny przykład i możesz go wypróbować. Jeśli chcesz, żeby video zajmowało cały ekran, to kontener, w którym znajduje się video, też powinien być szerokości i wysokości ekranu.

      1. Dziękuje bardzo za przykład. Teraz kod działa. Jednak on ma zastosowanie do innego przypadku niż myślałem. Czy da się zrobić tak aby były zachowane proporcie wideo? Mam wideo o rozdzielczości 1920×1080. Wideo nie musi być na całą szerokość strony ale żeby było na wysokość strony, a szerokość była obliczana zachowując proporcie wideo. Jeśli szerokość będzie mniejsza niż wysokość (smartfon) to wtedy wideo powinno być na pełną szerokość, a wysokość powinna być obliczana na podstawie szerokości zachowują proporcie wideo.

        1. Ten przykład zachowuje proporcje dla filmu o proporcjach 16:9, więc powinien dla Ciebie działać. Musisz jednak zmodyfikować funkcję resize(), żeby działała dla Twojego konkretnego przypadku. Np. dla smartfonów video.width = window.innerWidth, a video.height = 9 * window.innerWidth / 16. Pokombinuj 🙂