megclaypool
9/4/2018 - 3:39 PM

Fluid width responsive video

[Fluid width responsive video]

Note: The javascript and bootstrap embed-responsive methods do NOT play nicely together!!! The bootstrap method depends on the iframe height being set to 100%, and the script adds inline css setting the iframe height to 0 😛 So if you want to use the bootstrap embed-responsive, make sure the javascript is NOT being used!

More info can be read in a the CSS Tricks: Fluid Width Video article at https://css-tricks.com/NetMag/FluidWidthVideo/Article-FluidWidthVideo.php.

var videoEmbeds = document.querySelectorAll(
  ".wp-block-embed.is-type-video iframe" // Change this selector to match embedded videos on your site/platform
);

if (videoEmbeds !== undefined && wpVideoEmbeds.length > 0) {
  videoEmbeds.forEach(setVideoRatio);
}

function setVideoRatio(current) {
  var videoRatio = getVideoRatio(current);
  var videoParent = current.parentNode;
  videoParent.classList.add("video-ratio");
  videoParent.style.paddingTop = videoRatio * 100 + "%";
}

// get the proportions of the width and height of the video
function getVideoRatio(iframe) {
  // if there's a videoRatio already set, just use it
  if (iframe.hasAttribute("videoRatio")) {
    videoRatio = Number(iframe.getAttribute("videoRatio"));
  } else {
    if (iframe.height && iframe.width) {
      videoRatio = iframe.height / iframe.width;
      iframe.removeAttribute("height");
      iframe.removeAttribute("width");
    } else {
      // default to 9 : 16 if no other info given!
      videoRatio = 9 / 16;
    }
    iframe.setAttribute("videoRatio", videoRatio);
  }
  return videoRatio;
}
//adjust the wrapper classes to suit your site/platform
.wp-block-embed.is-type-video {
  .wp-block-embed__wrapper.video-ratio {
    position: relative;

    iframe {
      bottom: 0;
      height: 100%;
      left: 0;
      position: absolute;
      right: 0;
      top: 0;
      width: 100%;
    }
  }
}
(function($) {
  $(document).ready(function() {
    var $allVideos = $("iframe[src*='//player.vimeo.com'], iframe[src*='//www.youtube.com'], object, embed"),
    $fluidEl = $("figure");

    $allVideos.each(function() {

      $(this)

        // jQuery .data does not work on object/embed elements
        .attr('data-aspectRatio', this.height / this.width)
        .removeAttr('height')
        .removeAttr('width');
    });

    $(window).resize(function() {
      var newWidth = $fluidEl.width();
      $allVideos.each(function() {
        var $el = $(this);
        $el
          .width(newWidth)
          .height(newWidth * $el.attr('data-aspectRatio'));
      });
    }).resize();
  });
})(jQuery);

Below is the (slightly adapted) script I got working on a Radicati site:

Just enclose the oEmbed field in <figure></figure> tags and the video will automatically resize to fit. Ex:

<figure>
    {{ post.get_field('video') }}
</figure>

Make sure the javascript file is either concatenated into your main site.js or is enqueued or whatever needs to happen (depends on how your site is organized).

Note: It looks like there might be a more recent version of this fluid-video project at https://github.com/davatron5000/FitVids.js

The easiest method is if you're using Bootstrap (which we nearly always are). Bootstrap has responsive video classes built in. Setting class=“embed-responsive embed-responsive-16by9” works for YouTube videos, which are all widescreen. Also available are 4by3 (Fullscreen) and 21by9 (Cinematic Widescreen). This method is nice in that it doesn’t require javascript; it’s all css-based.

{{ attach_library('radicati_d8/video-ratio') }}

{#
This is just a duplicate of the field.html.twig file, with the appropriate library attached at the top
#}


{# Naked divs are no good -- I'd like to be able to target paragraph fields based on field name. I lean towards field name rather than label, because the field label might get changed in the gui, but user won't be changing the field name -- Meg 6/1/20 #}
{% set field_classes = [
  'field--' ~ label|lower|replace({' ': '_'}),
  field_name|clean_class
  ]
%}

{%
  set title_classes = [
  'field__label',
  label_display == 'visually_hidden' ? 'visually-hidden',
]
%}
<div {{ attributes.addClass(field_classes) }}>

  {% block content %}
    {% if not label_hidden %}
      <div{{ title_attributes.addClass(title_classes) }}>{{ label }}</div>
    {% endif %}

    {% if multiple %}
      {% for item in items %}
        <div{{ item.attributes }}>{{ item.content }}</div>
      {% endfor %}
    {% else %}
      {% for item in items %}
        {{ item.content }}
      {% endfor %}
    {% endif %}
  {% endblock %}
</div>
...

video-ratio:
  version: 1.x
  js:
    patterns/_patterns/10-atoms/99-media/01-video-ratio.js: {}

...