Chrome 不尊重视频源内联媒体查询

Posted

技术标签:

【中文标题】Chrome 不尊重视频源内联媒体查询【英文标题】:Chrome not respecting video source inline media queries 【发布时间】:2014-11-12 12:20:51 【问题描述】:

使用以下内容,Chrome 不尊重媒体查询以根据设备宽度显示正确的视频源。 Chrome 正在播放它找到的第一个源,如您在此处看到的:http://homeglobal.ch/。我该如何解决这个问题?

    <video id="intro-video" poster="img/poster.png" controls>
        <source src="videos/intro.mp4" type="video/mp4" media="all and (min-device-width:1600px)">
        <source src="videos/intro.webm" type="video/webm" media="all and (min-device-width:1600px)">
        <source src="videos/intro-1600.mp4" type="video/mp4" media="all and (min-device-width:1100px)">
        <source src="videos/intro-1600.webm" type="video/webm" media="all and (min-device-width:1100px)">
        <source src="videos/intro-1100.mp4" type="video/mp4" media="all and (min-device-width:481px)">
        <source src="videos/intro-1100.webm" type="video/webm" media="all and (min-device-width:481px)">
        <source src="videos/intro-480.mp4" type="video/mp4">
        <source src="videos/intro-480.webm" type="video/webm">
    </video>

【问题讨论】:

出于一些恼人的原因:“资源的预期媒体的媒体查询;这应该只在 元素中使用。” developer.mozilla.org/en-US/docs/Web/html/Element/source 【参考方案1】:

很遗憾,Chrome 不支持对 video html 5 标签的媒体查询。解决此问题的方法是使用纯 javascript 或 Jquery。它不漂亮,但即使在 chrome 中也可以使用。

var video = $('#myvideo');

var WindowWidth = $(window).width();

if (WindowWidth < 1200) 
    //It is a small screen
    video.append("<source src='/img/homepage/640/splash.m4v' type='video/mp4' >");
 else 
    //It is a big screen or desktop
    video.append("<source src='/img/homepage/1080/uimain-1080.mp4' type='video/mp4' >");

【讨论】:

我想知道这是否仍然有必要,或者 Chrome 是否开始承认这一点? 截至 2019 年 6 月还没有 >. 男人!太可惜了,这适用于图片标签,但不适用于视频。适用于 Firefox。我希望他们尽快增加支持。很高兴看到为海报图片添加了一个选项。 2021.09。仍然没有支持。 永远不会有支持 - 它已在 Chrome 34 中撤消 来源:walterebert.com/playground/video/media-queries【参考方案2】:

我在 Vanilla JS 上的实现。

video 标记中,作为data-src 属性,指定默认视频的路径。在video标签内,在source标签内,我们指定data-srcdata-mw这两个属性的值。

data-src - 是视频文件的路径。

data-mw - 是显示此视频的最大屏幕宽度。

当屏幕宽度发生变化时,此解决方案会自动工作。这是使用resize() 函数完成的。

<video id="intro-video" data-src="/path/default.mp4" poster="img/poster.png" controls>
    <source data-src="/path/1600.mp4" data-mw="1600">
    <source data-src="/path/900.mp4" data-mw="900">
    <source data-src="/path/480.mp4" data-mw="480">
</video>
class VideoResponser 
    constructor(selector) 
        const $video = document.querySelector(selector);
        this.options =  
            selector, 
            breakpoints:  default:  src: $video.getAttribute('data-src')   
        ;

        // get a list of video switching points and links to the videos themselves 
        $video.querySelectorAll('[data-src]').forEach(element => this.options.breakpoints[element.getAttribute('data-mw')] =  src: element.getAttribute('data-src') );
        $video.innerHTML = ''; // we clean up so that there is nothing superfluous 
        
        // run the handler and track the change in screen width
        this.responseVideo(this.options);
        this.resizer();
    

    /** Function runs on resize  */
    resizer() 
        window.addEventListener("resize", () => this.responseVideo(this.options));
    

    /** 
     * Change src value of video link to fit screen width 
     * 
     * @param Object options object with options 
     */
    responseVideo(options) 
        const selector, breakpoints = options; // get options
        let $video = document.querySelector(selector);
        const widthNow = $video.getAttribute('data-width-now') || null;
        const maxBreakpoint = Math.max(Object.keys(breakpoints).filter(key => key >= document.body.clientWidth));
        const nowBreakpoint = maxBreakpoint || 'default'; // choose either the maximum value, if not, then the default 

        if(widthNow && widthNow == nowBreakpoint) return; // check if the video needs to be changed 

        $video.setAttribute('data-width-now', nowBreakpoint);
        $video.src = breakpoints[nowBreakpoint].src;
    


new VideoResponser("#intro-video");

【讨论】:

非常好的脚本。我只需要更改 maxBreakpoint 常量的行以使其工作: const maxBreakpoint = Math.max.apply(Math, Object.keys(breakpoints).filter(key => key 感谢@Patricks,我也需要这样做。【参考方案3】:
<video class="desktop-video" autoplay playsinline preload="auto" muted loop >
    <source src="$pdict.desktop_video" type="video/mp4">
    <source src="$pdict.desktop_video" type="video/mov">
    Sorry, your browser doesn't support embedded videos.
</video>
<video class="mobile-video" autoplay playsinline preload="auto" muted loop >
    <source src="$pdict.mobile_video" type="video/mp4">
    <source src="$pdict.mobile_video" type="video/mov">
    Sorry, your browser doesn't support embedded videos.
</video>

可以在 CSS 中完成

.desktop-video 
    display: grid;

    @include media-breakpoint-down(lg) 
        display: none;
    


.mobile-video 
    display: none;

    @include media-breakpoint-down(lg) 
        display: grid;
    

【讨论】:

这将预加载两个视频,即使其中一个被隐藏,这对性能不利,尤其是在移动设备中。【参考方案4】:

我使用了object-fit: cover;的解决方案

.video-wrapper 
    position: relative;
    max-width: 100%;
    height: auto;
    overflow: hidden;
    margin-bottom: 0;
    padding-top: 100%;


@media (min-width: 768px) 
        .video-wrapper 
                padding-top: 50%;
        
    

.video-item 
    position: absolute;
    top: 0;
    left: 0;
    height: 100%;
    width: 100%;
    object-fit: cover;

代码笔here

【讨论】:

这不会解决每个断点的不同视频格式的问题,它只会显示“更好”的一个视频。

以上是关于Chrome 不尊重视频源内联媒体查询的主要内容,如果未能解决你的问题,请参考以下文章

Chrome + css3:媒体查询缩放错误

Safari 打印媒体查询与其他浏览器不匹配/中断

Chrome 设备模式模拟媒体查询不起作用

使用媒体查询内联样式[重复]

Styled Components - 内联样式与媒体查询样式重叠

带有内联样式表和媒体查询的 Razor 视图 [重复]