流体宽度视频

Avatar of Chris Coyier
Chris Coyier

DigitalOcean 提供适用于您旅程各个阶段的云产品。立即开始使用 价值 200 美元的免费信用额度!

在网页上响应式和流体布局的世界中,有一种媒体类型阻碍了完美的和谐:视频。网站上有很多种方式可以显示视频。您可能自托管视频,并通过 HTML5 的 <video> 标签呈现它。您可能使用 YouTube、Vimeo 或其他提供 <iframe> 代码来显示视频的视频提供商。让我们了解如何使它们都具有流体宽度,同时根据它们的纵横比保持适当的高度。

在这些视频嵌入场景中,声明静态 widthheight 非常常见。

<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 窄?它会爆出,看起来可能很荒谬和尴尬。

breakout
简单且人为,但仍然很荒谬且尴尬。

那么我们不能只这样做吗?

<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 时,我们会得到 150px1 的静态高度,这对于大多数视频来说太矮了,并且会造成更多的 R&E(荒谬且尴尬)。

幸运的是,这里有几个可能的解决方案。其中一个是由 Thierry Koblentz 首创,并在 2009 年的 A List Apart 上发表:为视频创建固有比例。使用此技术,您将视频包装在另一个具有固有纵横比的元素中,然后在该元素内绝对定位视频。这样,我们可以获得流体宽度和我们可以依靠的合理高度。

<div class="videoWrapper">
  <!-- Copy & Pasted from YouTube -->
  <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 JavaScript 库,看起来像这样

// 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。这比需要绑定到窗口调整大小处理程序要高效得多

改为使用纯 JavaScript

如今,jQuery 已经不受欢迎了。幸运的是,Dave 还有一个 Vanilla 版本(需要自行提供 CSS)

  1. 从字面上看,所有浏览器都会将 iframe、canvas、embed 和 object 标签呈现为 300px × 150px,如果没有其他声明。即使 UA 样式表中不存在此内容。