【问题标题】:Is there any cross-browser javascript for making vh and vw units work是否有任何跨浏览器 javascript 可以使 vh 和 vw 单元工作
【发布时间】:2012-12-06 14:07:24
【问题描述】:

注意:好的,当我输入这个问题时,我遇到了this 建议使用@media query 但被问回的问题 2011...

如您所知,CSS3 引入了新的Viewport-percentage length unitsvhvw,我觉得它们对于可靠的响应式布局非常有用,所以我的问题是,有没有 JavaScript/jQuery 替代方案?除了将它用于字体大小之外,用于调整元素大小是否安全?像例子

div {
   height: 6vh;
   width: 20vh;  /* Note am using vh for both, do I need to use vw for width here? */
}

【问题讨论】:

  • 这是一个由 19.2k 编辑的 10.9k 问题,由 15.4k 回答..aaaaah
  • @Ben 巨人之战 (:
  • 我花了一段时间,我被这个问题迷住了,很大的挑战。
  • @Ben:由 140k 重新标记。抱歉,标签让我非常困扰:)
  • 如果还有人喜欢这个,我已经做了一个很好用的网格插件,如果你们想试试看这里github.com/elclanrs/jquery.columns

标签: javascript jquery css


【解决方案1】:

更新 5: .css(property) 修复 像fancyBox 这样的插件使用.css('margin-right') 来获取元素的右边距,使用.css('margin-right', '12px') 来设置元素的右边距。这被破坏了,因为没有检查 props 是否是一个字符串以及是否有多个参数。通过检查 props 是否为字符串来修复它。如果是这样并且有多个参数,则将参数重写为一个对象,否则不使用parseProps( $.extend( {}, props ) )

更新 4: 用于响应式布局的插件 https://github.com/elclanrs/jquery.columns(正在开发中)

我给了这个(长时间)尝试。首先是 CSS 示例:http://jsbin.com/orajac/1/edit#css。 (调整输出面板的大小)。请注意,font-size 不适用于视口单元,至少在最新的 Chrome 上是这样。

这是我尝试使用 jQuery 来实现的。也可以使用该字体的 jQuery 演示位于 http://jsbin.com/izosuy/1/edit#javascript。尚未对其进行广泛测试,但它似乎适用于大多数属性,因为它只是将值转换为像素,然后通过在 window.resize 上调用插件,它会不断更新。

更新:更新了代码以适用于许多浏览器。如果您使用的是 Chrome 以外的任何东西,请在本地进行测试,因为 jsBin 对 window.resize 的行为有点奇怪。

更新 2: 扩展原生 css 方法。

更新 3: 在插件内部处理 window.resize 事件,因此现在可以无缝集成。

要点(本地测试): https://gist.github.com/4341016

/*
 * CSS viewport units with jQuery
 * http://www.w3.org/TR/css3-values/#viewport-relative-lengths
 */
;(function( $, window ){

  var $win = $(window)
    , _css = $.fn.css;

  function viewportToPixel( val ) {
    var percent = val.match(/[\d.]+/)[0] / 100
      , unit = val.match(/[vwh]+/)[0];
    return (unit == 'vh' ? $win.height() : $win.width()) * percent +'px';
  }

  function parseProps( props ) {
    var p, prop;
    for ( p in props ) {
      prop = props[ p ];
      if ( /[vwh]$/.test( prop ) ) {
        props[ p ] = viewportToPixel( prop );
      }
    }
    return props;
  }

  $.fn.css = function( props ) {
    var self = this
      , originalArguments = arguments
      , update = function() {
          if ( typeof props === 'string' || props instanceof String ) {
            if (originalArguments.length > 1) {
              var argumentsObject = {};
              argumentsObject[originalArguments[0]] = originalArguments[1];
              return _css.call(self, parseProps($.extend({}, argumentsObject)));
            } else {
              return _css.call( self, props );
            }
          } else {
            return _css.call( self, parseProps( $.extend( {}, props ) ) );
          }
        };
    $win.resize( update ).resize();
    return update();
  };

}( jQuery, window ));

// Usage:
$('div').css({
  height: '50vh',
  width: '50vw',
  marginTop: '25vh',
  marginLeft: '25vw',
  fontSize: '10vw'
});

【讨论】:

  • 这在 chrome 22 上运行良好,但在 17.0.1 上失败 :) 但不错的尝试 +1...想要一个跨浏览器,我可以肯定离开 IE7,8..但至少ff,chrome,opera(不会工作,很好),ie9/10
  • @Mr.Alien:问题出在prop = viewportToPixel( prop ) 行。我改为prop[p] = viewportToPixel( prop ),现在在所有浏览器中都可以正常工作。测试一下! jsbin.com/ugefub/1/edit#javascript
  • @Mr.Alien:jsBin 在除 Chrome 之外的所有浏览器中都对 window.resize 做了一些奇怪的事情。在本地尝试,它在 FF、Opera 和 Chrome AFAIK 中运行良好。这是一个要点gist.github.com/4341016
  • 现在太棒了...谢谢您,这真的会帮助很多人,顺便说一句,您的网站很优雅...
  • @Mr.Alien:我在这里jsbin.com/evupug/1 进行了一些网格测试(本地效果更好)。它实际上工作得很好,结合媒体查询,这似乎非常强大,尽管可能只对正文级别的元素和动态字体大小调整有用。对于儿童元素,我猜最好使用实际百分比......
【解决方案2】:

我在使用 Android 4.3 股票浏览器时遇到了这个问题(不支持 vw、vh 等)。 我解决这个问题的方法是使用 'rem' 作为字体大小单位,并使用 javascript 动态更改 的字体大小

function viewport() {
    var e = window, a = 'inner';
    if (!('innerWidth' in window )) {
        a = 'client';
        e = document.documentElement || document.body;
    }
    return { width : e[ a+'Width' ] , height : e[ a+'Height' ] };
}
jQuery(window).resize(function(){
    var vw = (viewport().width/100);
    jQuery('html').css({
        'font-size' : vw + 'px'
    });
});

在你的 css 中你可以使用 'rem' 而不是 px、ems 等

.element {
    font-size: 2.5rem; /* this is equivalent to 2.5vw */
}

这是代码演示:http://jsfiddle.net/4ut3e/

【讨论】:

  • 关于rems,有一些Android版本(不记得是哪个)有最小字体大小(在我的例子中是8px)。因此,如果您的根字体大小最终小于 8px,它将自动舍入为 8px,并可能会破坏您的布局。
【解决方案3】:

我写了一个小助手来处理这个问题。它在所有主要浏览器上都受支持并使用 jQuery。
这里是:

支持VhVw.js

function SupportVhVw() {

    this.setVh = function(name, vh) {

        jQuery(window).resize( function(event) {
            scaleVh(name, vh);
        });

        scaleVh(name, vh);
    }

    this.setVw = function(name, vw) {

        jQuery(window).resize( function(event) {
            scaleVw(name, vw);
        });

        scaleVw(name, vw);
    }

    var scaleVw = function(name, vw) {

        var scrWidth = jQuery(document).width();
        var px = (scrWidth * vw) / 100;
        var fontSize = jQuery(name).css('font-size', px + "px");
    }


    var scaleVh = function(name, vh) {

        var scrHeight = jQuery(document).height();

        var px = (scrHeight * vh) / 100;
        var fontSize = jQuery(name).css('font-size', px + "px");
    }
};

如何在 HTML 中使用它的简单示例:

<head>

    <title>Example</title>

    <!-- Import all libraries -->
    <script type="text/javascript" src="js/libs/jquery-1.10.2.min.js"></script>
    <script type="text/javascript" src="js/libs/SupportVhVw.js"></script>

</head>
<body>

                    <div id="textOne">Example text one (vh5)</div>
                    <div id="textTwo">Example text two (vw3)</div>
                    <div id="textThree" class="textMain">Example text three (vh4)</div>
                    <div id="textFour" class="textMain">Example text four (vh4)</div>

            <script type="text/javascript">

                    // Init object
                    var supportVhVw = new SupportVhVw();

                    // Scale all texts
                    supportVhVw.setVh("#textOne", 5);
                    supportVhVw.setVw("#textTwo", 3);
                    supportVhVw.setVh(".textMain", 4);

            </script>

</body>

在 GitHub 上可用:
https://github.com/kgadzinowski/Support-Css-Vh-Vw

JSFiddle 上的示例: http://jsfiddle.net/5MMWJ/2/

【讨论】:

  • 你为什么要处理 attachEvent 和 addEventListener 并导入 jQuery?
  • 这是一个小错误,与正确的代码行为无关。如果代码运行良好且易于使用,我看不出有理由拒绝投票:/ 我已经修正了我的答案。
  • 我没有投反对票,我只是在问。自己处理这些情况然后在其他地方使用 jQuery 看起来很愚蠢。
  • @Konrad 感谢您的回答,我为您的努力投了赞成票 :) 感谢...如果您也在这里提供演示,使用 jsfiddle 会更好:)
  • 我已经按照你的要求添加了 JSFiddle 演示 :)
【解决方案4】:

Vminpoly 是我所知道的唯一 polyfill——它正在开发中,但在这篇文章中可以使用。 Jquery Columns-prefix-free 项目中也有静态 polyfill。

【讨论】:

    【解决方案5】:

    我刚刚用纯 CSS(不需要 JS)为此做了一个非常丑陋但完美的解决方法。 我遇到了一个 CSS 样式表,其中充满了需要为原生 Android 浏览器重写的“vw”声明(也用于高度和顶部/底部属性)(在 4.3 及以下版本中不支持“vw”单位)。

    我没有将所有内容重写为与父宽度相关的百分比(因此在 DOM 中越深,计算就越复杂),即使在我到达第一个 { height: Xvw } 声明之前,这也会让我头疼,我为自己生成了以下样式表: http://splendige.pl/vw2rem.css

    我猜你们都熟悉“em”单位(如果不熟悉:http://www.w3schools.com/cssref/css_units.asp)。经过一些测试,我发现旧的 Android 浏览器(以及所有其他浏览器)完全支持 'rem' 单位,其工作方式与 'em' 相同,但与 ROOT 元素的字体大小声明相关(在大多数情况下, html标签)。

    所以最简单的方法是为 html 标签声明字体大小,它等于视口宽度的 1%,例如19.2px 用于 1920px 视口,并在整个 1920-320px 范围内使用大量媒体查询。通过这种方式,我在所有分辨率下使“rem”单位等于“vw”(步长为 10px,但您甚至可以尝试为每 1px 声明 html{font-size})。然后我只是用 'rem' 批量替换了 'vw' 并欣赏了 Android 4.3 本机浏览器上的工作布局。

    此外,您甚至可以为整个正文标签重新声明字体大小(以您想要的任何单位:px、em、pt 等)并且它不会影响 'rem' 与 'vw' 的相等性整个样式表。

    希望这会有所帮助。我知道它看起来有点傻,但就像一个魅力。请记住:如果某件事看起来很愚蠢,但有效,那么它并不愚蠢:)

    【讨论】:

    • 能否再次上传 vw2rem 样式表?找不到链接。谢谢。
    【解决方案6】:

    “jquery.columns”是迄今为止最好的解决方案。

    https://github.com/elclanrs/jquery.columns

    您只需要 2 行代码就可以将“vh”变成“全浏览器规模”。

    在html中声明一个类:

    <img src="example.jpg" class="width50vh" />
    

    然后在javascript中:

    $('.width50vh').css({width: '50vw'});
    

    【讨论】:

    • 如果不支持vwvh,这将如何工作? Javascript css 是否在内部设置了 50vw 以外的其他内容?如果没有,您只需在不支持的单位中设置一个值,我认为这不起作用。
    • 是的,它也适用于旧版 IE。 jquery.columns 覆盖 jquery 的 css() 函数并在其声明期间将 'vw' 转换为像素。
    【解决方案7】:

    我发现的最简单和最优雅的解决方案是简单地制作一个高度为 1vh; 的 div。和宽度:1vw;当页面加载时,使用 getBoundingClientRect() 将这些值作为像素获取。然后在文档中添加一个监听器来监听屏幕调整大小并在调整屏幕大小时更新大小。

    我以像素为单位保存 vh 和 vw 的值,然后每当我需要使用 vh 时,我只会说 100 * vh,这将给我 100vh。

    这是一个关于它的实现的代码 sn-p,我的答案是 vanilla js,不需要 jquery。

    function getViewportUnits(){
      const placeholder = document.getElementById("placeholder");
      const vh = placeholder.getBoundingClientRect().height;
      const vw = placeholder.getBoundingClientRect().width;
      console.log({vh: vh, vw: vw});
    }
    #placeholder{
      background: red;
      height: 1vh;
      width: 1vw;
    }
    <body onload="getViewportUnits()">
    <div id="placeholder"></div>

    【讨论】:

      【解决方案8】:

      我发布了一个小型库,可以简化视口相关尺寸的使用。请记住,它不是 polyfill,因此它要求您在要调整大小的元素上应用类。例如,&lt;div class="vh10 vw30"&gt;hello&lt;/div&gt; 将填充 10% 的高度和 30% 的宽度。

      查看:https://github.com/joaocunha/v-unit

      【讨论】:

      猜你喜欢
      • 2014-09-12
      • 2021-10-12
      • 2010-12-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多