skip to Main Content

The following page displays a thumbnail image, that when clicked, brings up a Bootstrap 3 modal with the video. It works, but if the video is too tall for the window, it extends below the window, and the user can’t see the entire video (and has to scroll). I’ve tried various resizing strategies, but nothing seems to work. Suggestions appreciated. URLs obscured, sorry. And I’m required to use Bootstrap 3.

<!DOCTYPE html>
<html>
    <head>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
        <script src="https://vjs.zencdn.net/7.8.4/video.js"></script>
        <link href="https://vjs.zencdn.net/7.8.4/video-js.css" rel="stylesheet">
    </head>
    <body>
        <a href="#" data-toggle="modal" data-target="#viewVideoModal" data-video-url="https://VIDEOFILE" class="video-link">
            <img id="img-401" src="https://VIDEOFILE?thumb=1" height="280" width="157">
        </a>
        <div class="modal fade" id="viewVideoModal" tabindex="-1" role="dialog" aria-labelledby="viewVideoModalLabel">
            <div class="modal-dialog" role="document" style="margin-top:50px;">
                <div class="modal-content">
                    <div class="modal-header">
                        <button type="button" class="close" data-dismiss="modal">
                            <span aria-hidden="true">
                                &times;
                            </span>
                            <span class="sr-only">
                                Close
                            </span>
                        </button>
                    </div>
                    <div class="modal-body" id="viewVideoBody"></div>
                </div>
            </div>
        </div>
        <script>
    var player;
    $('#viewVideoModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget); // Button that triggered the modal
        var videoSrc = button.data('video-url');
        var videoTag = document.createElement('video');
        videoTag.setAttribute('class', 'video-js vjs-fluid center-block vjs-default-skin');
        videoTag.setAttribute('controls', '');
        videoTag.setAttribute('preload', 'auto');
        videoTag.setAttribute('data-setup', '{}');

        // Create a new source tag
        var sourceTag = document.createElement('source');
        sourceTag.setAttribute('src', videoSrc);
        sourceTag.setAttribute('type', 'video/mp4');

        // Append the source tag to the video tag
        videoTag.appendChild(sourceTag);

        // Get the modal body and clear its contents
        var modalBody = document.getElementById('viewVideoBody');
        modalBody.innerHTML = '';

        // Append the video tag to the modal body
        modalBody.appendChild(videoTag);

        // Initialize the video player
        player = videojs(videoTag);
    });
        </script>
    </body>
</html>

2

Answers


  1. Chosen as BEST ANSWER

    I've settled on the following solution. It's not perfect, because, depending on the aspect ratio of the video, there are black bars either on the sides of the video or above and below the video. But otherwise, it works.

    I made 3 changes to the original code I posted.

    • I manually set the width/height of the modal-dialog, to width:80vw; height: 80vh
    • I changed the vjs-fluid class to vjs-fill
    • I manually set the width and height of videoModalBody every time that a video is instantiated, to width:80vw; height: 80vh

    Here is the modified code:

    <!DOCTYPE html>
    <html>
        <head>
            <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
            <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
            <script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
            <script src="https://vjs.zencdn.net/7.8.4/video.js"></script>
            <link href="https://vjs.zencdn.net/7.8.4/video-js.css" rel="stylesheet">
        </head>
        <body>
            <a href="#" data-toggle="modal" data-target="#viewVideoModal" data-video-url="https://VIDEOFILE" class="video-link">
                <img id="img-401" src="https://VIDEOFILE?thumb=1" height="280" width="157">
            </a>
            <div class="modal fade" id="viewVideoModal" tabindex="-1" role="dialog" aria-labelledby="viewVideoModalLabel">
                <div class="modal-dialog" role="document" style="width:80vw;height:80vh">
                    <div class="modal-content">
                        <div class="modal-header">
                            <button type="button" class="close" data-dismiss="modal">
                                <span aria-hidden="true">
                                    &times;
                                </span>
                                <span class="sr-only">
                                    Close
                                </span>
                            </button>
                        </div>
                        <div class="modal-body" id="viewVideoBody"></div>
                    </div>
                </div>
            </div>
            <script>
        var player;
        $('#viewVideoModal').on('show.bs.modal', function (event) {
            var button = $(event.relatedTarget); // Button that triggered the modal
            var videoSrc = button.data('video-url');
            var videoTag = document.createElement('video');
            videoTag.setAttribute('class', 'video-js vjs-fill center-block vjs-default-skin');
            videoTag.setAttribute('controls', '');
            videoTag.setAttribute('preload', 'auto');
            videoTag.setAttribute('data-setup', '{}');
    
            // Create a new source tag
            var sourceTag = document.createElement('source');
            sourceTag.setAttribute('src', videoSrc);
            sourceTag.setAttribute('type', 'video/mp4');
    
            // Append the source tag to the video tag
            videoTag.appendChild(sourceTag);
    
            // Get the modal body and clear its contents
            var modalBody = document.getElementById('viewVideoBody');
            modalBody.setAttribute('style', 'height:80vh;width:80vw');
            modalBody.innerHTML = '';
    
            // Append the video tag to the modal body
            modalBody.appendChild(videoTag);
    
            // Initialize the video player
            player = videojs(videoTag);
        });
            </script>
        </body>
    </html>
    

  2. You are creating a new <video> tag each time the modal is shown and appending it to the modal body. The video is set to be fluid, which should make it responsive, but it seems that the modal is not responding as expected when the video dimensions exceed the viewport height.


    CSS-based solution

    One way to make the video fit within the modal (and the viewport) is to limit the height of the video by using CSS and to also ensure that the video maintains its aspect ratio. The CSS max-height and object-fit properties can be quite helpful here.

    First, add a new CSS class in the <head> section of your HTML:

    <style>
    .modal-video-container {
        max-height: 80vh;  /* Adjust this value as needed */
        overflow: auto;
    }
    .modal-video-container .video-js {
        width: 100% !important;
        height: 100% !important;
        object-fit: contain;
    }
    </style>
    

    Next, wrap your <video> element in a <div> with this class, so modify your JavaScript code like this:

    $('#viewVideoModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget); // Button that triggered the modal
        var videoSrc = button.data('video-url');
        var videoTag = document.createElement('video');
        videoTag.setAttribute('class', 'video-js vjs-fluid center-block vjs-default-skin');
        videoTag.setAttribute('controls', '');
        videoTag.setAttribute('preload', 'auto');
        videoTag.setAttribute('data-setup', '{}');
    
        // Create a new source tag
        var sourceTag = document.createElement('source');
        sourceTag.setAttribute('src', videoSrc);
        sourceTag.setAttribute('type', 'video/mp4');
    
        // Append the source tag to the video tag
        videoTag.appendChild(sourceTag);
    
        // Create a new div to contain the video, and append the video to it
        var videoContainer = document.createElement('div');
        videoContainer.setAttribute('class', 'modal-video-container');
        videoContainer.appendChild(videoTag);
    
        // Get the modal body and clear its contents
        var modalBody = document.getElementById('viewVideoBody');
        modalBody.innerHTML = '';
    
        // Append the video container to the modal body
        modalBody.appendChild(videoContainer);
    
        // Initialize the video player
        player = videojs(videoTag);
    });
    

    The 80vh value for max-height means that the video will take up to 80% of the viewport height. You can adjust this value as needed. The overflow: auto will provide a scrollbar in case the video height still exceeds the modal height. The object-fit: contain; ensures the aspect ratio of the video is maintained.

    Warning: object-fit is not supported in Internet Explorer. If you need to support IE, you may need to find a different solution or use a polyfill.


    The modal dialog is now correctly sized, but the video now has a vertical scroll bar.

    What I’m looking (hoping) for is a solution that would resize the video so that there isn’t a scroll bar.

    If you want the video to resize to fit within the modal without the need for a scroll bar, you will need to adjust the CSS and JavaScript a bit.

    First, update the CSS with max-height set to 100% and height set to auto for the .video-js class:

    <style>
    .modal-video-container {
        height: 80vh;  /* Adjust this value as needed */
    }
    .modal-video-container .video-js {
        width: 100%;
        max-height: 100%;
        height: auto;
    }
    </style>
    

    Then, modify the JavaScript. Instead of setting the height of the video directly, set the height of the modal body to a percentage of the viewport height, and then let the video fill the available space:

    $('#viewVideoModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget); // Button that triggered the modal
        var videoSrc = button.data('video-url');
        var videoTag = document.createElement('video');
        videoTag.setAttribute('class', 'video-js vjs-fluid center-block vjs-default-skin');
        videoTag.setAttribute('controls', '');
        videoTag.setAttribute('preload', 'auto');
        videoTag.setAttribute('data-setup', '{}');
    
        // Create a new source tag
        var sourceTag = document.createElement('source');
        sourceTag.setAttribute('src', videoSrc);
        sourceTag.setAttribute('type', 'video/mp4');
    
        // Append the source tag to the video tag
        videoTag.appendChild(sourceTag);
    
        // Create a new div to contain the video, and append the video to it
        var videoContainer = document.createElement('div');
        videoContainer.setAttribute('class', 'modal-video-container');
        videoContainer.appendChild(videoTag);
    
        // Get the modal body and clear its contents
        var modalBody = document.getElementById('viewVideoBody');
        modalBody.innerHTML = '';
    
        // Append the video container to the modal body
        modalBody.appendChild(videoContainer);
    
        // Initialize the video player
        player = videojs(videoTag);
    });
    

    With this adjustment, the video should fill the modal body up to its maximum height and adjust its size according to the viewport height. The video will maintain its aspect ratio due to the vjs-fluid class.
    If the aspect ratio of the video does not match the aspect ratio of the modal body, there may be some unused space in the modal body, but the video itself should fit without a scrollbar.

    Note: The value 80vh for .modal-video-container‘s height can be adjusted to suit your needs. This value means the modal body will be 80% of the viewport height.


    jQuery UI-based solution

    As an alternative, assuming you can add/use jQuery UI to your project, you could consider "Apply size of video element to bootstrap modal while scaling".

    This jQuery code uses the .resizable() function from the jQuery UI library to make the modal content resizable, and the alsoResize option to apply the same resizing to the video element.

    Then, it binds a function to the resizestop event, which is fired when the user stops resizing the element. This function adjusts the video’s height and width according to the new size of the modal content, subtracting some pixels to account for padding.

    That would be:

    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
    ...
    $('.modal-content').resizable({
        alsoResize: "#video",
        minHeight: 150,
        minWidth: 200
    }).bind({
        resizestop: function(event, ui){
            $('video').css({
                'height':ui.size.height - 60,
                'width': ui.size.width - 30
            });
        }
    });
    

    The values -60 and -30 are the padding to be removed from the calculated height and width respectively.

    Do ensure to replace "#video" with the appropriate selector for your video element. Also, you might need to adjust the padding values (-60 and -30) depending on your exact modal design and layout.

    Incorporating this new piece of code into the previous code, we can modify the ‘show.bs.modal’ event as follows:

    <script src="https://code.jquery.com/ui/1.13.2/jquery-ui.min.js"></script>
    ...
    $('#viewVideoModal').on('show.bs.modal', function (event) {
        var button = $(event.relatedTarget); // Button that triggered the modal
        var videoSrc = button.data('video-url');
        var videoTag = document.createElement('video');
        videoTag.setAttribute('id', 'video'); // Added this line to give the video an id for the jQuery selector
        videoTag.setAttribute('class', 'video-js vjs-fluid center-block vjs-default-skin');
        videoTag.setAttribute('controls', '');
        videoTag.setAttribute('preload', 'auto');
        videoTag.setAttribute('data-setup', '{}');
    
        // Create a new source tag
        var sourceTag = document.createElement('source');
        sourceTag.setAttribute('src', videoSrc);
        sourceTag.setAttribute('type', 'video/mp4');
    
        // Append the source tag to the video tag
        videoTag.appendChild(sourceTag);
    
        // Create a new div to contain the video, and append the video to it
        var videoContainer = document.createElement('div');
        videoContainer.setAttribute('class', 'modal-video-container');
        videoContainer.appendChild(videoTag);
    
        // Get the modal body and clear its contents
        var modalBody = document.getElementById('viewVideoBody');
        modalBody.innerHTML = '';
    
        // Append the video container to the modal body
        modalBody.appendChild(videoContainer);
    
        // Initialize the video player
        player = videojs(videoTag);
    }).on('shown.bs.modal', function() {
        // The modal is now fully visible so we can resize the video
        $('.modal-content').resizable({
            alsoResize: "#video",
            minHeight: 150,
            minWidth: 200
        }).bind('resizestop', function(event, ui) {
            $('#video').css({
                'height': ui.size.height - 60, // Adjust these values based on your padding
                'width': ui.size.width - 30
            });
        });
    });
    

    This code first assigns an id of ‘video‘ to the video tag so that we can select it with jQuery in the ‘shown.bs.modal‘ event.
    The shown.bs.modal event is a Bootstrap-specific event that is fired after the modal has been made visible to the user. At this point, we can resize the video to fit the modal content, taking into account any padding.

    Again, do adjust the -60 and -30 values in the resize function based on the padding in your modal. If you don’t have any padding, you can set these values to 0.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search