В мире адаптивных и гибких макетов в Интернете, один единственный медиа тип стоит на пути к идеальной гармонии - видео. Существует множество способов отображения видео на вашем сайте. Возможно, вы самостоятельно размещаете видео и проигрываете его через тег video. Возможно, вы используете YouTube, Vimeo или другой видео сервис, который предоставляет iframe для отображения видео. Давайте рассмотрим, как сделать их адаптивными, сохраняя при этом соответствующую высоту и не нарушая пропорции.

Очень часто, при встраивании видео, width и height объявлены прямо в HTML:

<video width="400" height="300" controls ... ></video>

<iframe width="400" height="300" ... ></iframe>

<!-- maybe even super old school -->
<object width="400" height="300" ... />
<embed width="400" height="300" ... />

Угадай, что не так?
Объявление статической ширины - это не очень хорошая идея на сайте с изменяющейся шириной. Что если родительский контейнер для этого видео сжимается меньше чем объявленные 400px? В этом случае у нас все поломается и, будет выглядеть некрасиво и нелепо.

screenshot

Что же делать в подобной ситуации?

<video width="100%" ... ></video>

Если вы используете стандартное видео HTML5, это позволит видео соответствовать ширине контейнера. Если вы используете этот подход, важно удалить объявление height, чтобы соотношение сторон видео сохранялось по мере его увеличения и сжатия по ширине, чтобы не получить «черные полосы» для заполнения пустого пространства (в отличие от изображений, само видео сохраняет свое соотношение сторон независимо от размера элемента).

Вы можете переопределить эти стили через CSS (и не беспокоиться о том, что объявлено в HTML) следующим образом:

video {
  /* override other styles to make responsive */
  width: 100%    !important;
  height: auto   !important;
}

Iframe-видео (YouTube, Vimeo и т.д.)

Наш маленький трюк описанный выше не поможет нам при работе с видео, которое добавлено через iframe. Принудительное увеличение ширины до 100% эффективно, но когда мы устанавливаем height: auto;, мы получаем статическую высоту 150px, которая слишком приземистая для большинства видео. Практически все браузеры будут отображать теги iframe, canvas, embed и object как 300px × 150px, если не указано иное. Даже если этого нет в пользовательской таблице стилей.

К счастью, здесь есть несколько возможных решений. Один из них был впервые предложен Тьерри Кобленцем и представлен в A List Apart в 2009 году: Создание внутренних соотношений для видео. Используя эту технику, вы оборачиваете видео в другой элемент с внутренним соотношением сторон, а затем размещаете видео в этом абсолютном положении. Это дает нам резиновую ширину с “умной” высотой.

<div class="videoWrapper">
  <iframe width="560" height="349" src="http://www.youtube.com/embed/n_dZNLr2cME?rel=0&hd=1" frameborder="0" allowfullscreen></iframe>
</div>
.videoWrapper {
  position: relative;
  padding-bottom: 56.25%; /* 16:9 */
  height: 0;
}
.videoWrapper iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

Существует еще один “хитрый” вариант”, который позволяет регулировать соотношение сторон прямо из HTML:

<div class="videoWrapper" style="--aspect-ratio: 3 / 4;">
  <iframe ...>
.videoWrapper {
  ...
  /* falls back to 16/9, but otherwise uses ratio from HTML */
  padding-bottom: calc(var(--aspect-ratio, .5625) * 100%);
}

Иногда можно встретить олдскульный вариант встраивания видео в котором используется теги object и embed, так что если вы стараетесь поддерживать все возможные варианты - добавьте для них обертку:

.videoWrapper iframe,
.videoWrapper embed,
.videoWrapper object { }

Но, но ... пропорции, легаси контент, пользователи не технари и т.д.

Вышеприведенная техника очень хороша, но имеет несколько возможных ограничений:

  1. Для ее применения требуется элемент-обертка, поэтому невозможно прямое копирование/вставка кода с YouTube. Пользователи должны быть опытными.
  2. Если у вас есть легаси контент, и вы хотите сделать новый дизайн более отзывчивым, то все старые видео будут требовать корректировку HTML.
  3. Все видео должны иметь одинаковое соотношение сторон. В противном случае они будут переведены в другое соотношение сторон, и вы получите «черные полосы заполнения». Или же вам понадобится инструмент с определенным набором классов которые вы будете применять для регулировки соотношения сторон, что тоже является дополнительной сложностью.

Если к вам применимо любое из этих ограничений, то вы можете использовать JavaScript решение.

Представьте себе: при загрузке страницы все видео просматриваются и их соотношение сторон сохраняется. Каждый раз, когда размер окна изменяется, размер всех видео изменяется, чтобы заполнить доступную ширину и сохранить их соотношение сторон. Используя jQuery, это выглядит так:

// Find all YouTube videos
// Expand that selector for Vimeo and whatever else
var $allVideos = $("iframe[src^='//www.youtube.com']"),

  // The element that is fluid width
  $fluidEl = $("body");

// Figure out and save aspect ratio for each video
$allVideos.each(function() {

  $(this)
    .data('aspectRatio', this.height / this.width)

    // and remove the hard coded width/height
    .removeAttr('height')
    .removeAttr('width');

});

// When the window is resized
$(window).resize(function() {

  var newWidth = $fluidEl.width();

  // Resize all videos according to their own aspect ratio
  $allVideos.each(function() {

    var $el = $(this);
    $el
      .width(newWidth)
      .height(newWidth * $el.data('aspectRatio'));

  });

// Kick off one resize to fix all videos on page load
}).resize();

А вот вариант с плагином FitVids.js

Кроме того, что FitVids.js, отслеживает изменения размеров, он перебирает все видео и добавляет соотношение сторон, позволяющее использовать HTML-оболочку и необходимый CSS. Это намного эффективнее, чем привязка к обработчику изменения размера окна!

тот же плагин на чистом JS

В наши дни jQuery не в фаворе. К счастью, у Дэйва есть версия Vanilla JS: