web-dev-qa-db-fra.com

Existe-t-il un javascript inter-navigateur pour faire fonctionner les unités vh et vw

Remarque: Ok en tapant cette question, je suis tombé sur this question qui suggère d'utiliser @media query mais qui a été posée à nouveau dans 2011 ...

Comme vous le savez, CSS3 introduit les nouveaux Viewport en pourcentage des unités de longueur , vh et vw, qui me semblent vraiment utiles pour une mise en page réactive solide. Ma question est la suivante: existe-t-il une alternative JavaScript/jQuery pour cela? De plus, mis à part son utilisation pour les tailles de police, est-il sécuritaire d'utiliser pour le dimensionnement des éléments? Comme exemple

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

Mise à jour 5: .css (propriété) corrige Des plugins tels que fancyBox utilisent .css('margin-right') pour extraire la marge droite d'un élément et .css('margin-right', '12px') pour définir la marge droite d'un élément. Cela était cassé, car il n'y avait aucune vérification si props était une chaîne et s'il y avait plusieurs arguments donnés. Corrigé en vérifiant si props est une chaîne. Si c'est le cas et qu'il y a plusieurs arguments, les arguments sont réécrits dans un objet, sinon parseProps( $.extend( {}, props ) ) n'est pas utilisé.

Mise à jour 4: Plug-in pour les dispositions réactives https://github.com/elclanrs/jquery.columns (en construction)

J'ai fait un (long) essai. Voici d'abord l'exemple CSS: http://jsbin.com/orajac/1/edit#css . (redimensionner le panneau de sortie). Notez que le font-size ne fonctionne pas avec les unités de la fenêtre d'affichage, du moins sur la dernière version de Chrome. 

Et voici ma tentative de le faire avec jQuery. La démo jQuery qui fonctionne également avec la police est disponible à l’adresse http://jsbin.com/izosuy/1/edit#javascript . Je ne l'ai pas testé de manière approfondie, mais il semble fonctionner avec la plupart des propriétés, car il ne fait que convertir les valeurs en pixels, puis en appelant le plug-in sur window.resize, il continue de se mettre à jour.

Update: Code mis à jour pour fonctionner avec de nombreux navigateurs. Testez localement si vous utilisez autre chose que Chrome, car jsBin agit un peu bizarre avec window.resize.

Mise à jour 2: Étendre la méthode native css.

Update 3: Gérer l'événement window.resize à l'intérieur du plug-in afin que l'intégration soit maintenant transparente.

The Gist (à tester localement):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'
});

15
elclanrs

Je suis confronté à ce problème avec le navigateur de stock Android 4.3 (ne prend pas en charge vw, vh, etc.). La solution que j’ai résolue consiste à utiliser 'rem' comme unité de taille de police et à modifier dynamiquement la taille de la police <html> avec 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'
    });
});

et dans votre css, vous pouvez utiliser 'rem' au lieu de px, ems, etc.

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

Voici une démo du code: http://jsfiddle.net/4ut3e/

14
Alexandru Bangală

J'ai écrit petit assistant pour traiter ce problème. Il est supporté par tous les principaux navigateurs et utilise jQuery.
C'est ici:

SupportVhVw.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");
    }
};

Exemple simple comment l'utiliser en 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>

Il est disponible sur GitHub:
https://github.com/kgadzinowski/Support-Css-Vh-Vw

Exemple sur JSFiddle: http://jsfiddle.net/5MMWJJ/2/

7
Konrad G

Vminpoly est le seul polyfill que je connaisse - il est en cours de développement mais fonctionne à partir de cet article. Il existe également des polyfills statiques dans les projets Jquery Columns et -prefix-free .

4
RobW

Je viens de faire une solution de contournement très moche, mais parfaitement adaptée à ce fichier WITH PURE CSS (aucun JS requis) . devait être réécrit pour le navigateur Android natif (qui, dans les versions 4.3 et inférieures, ne prend pas en charge les unités «vw»).

Au lieu de tout réécrire en pourcentages, qui sont relatifs à la largeur du parent (donc les calculs les plus compliqués dans DOM, le plus profond), ce qui me donnerait mal à la tête avant même que j'atteigne la première déclaration {height: Xvw}, je me suis généré le feuille de style suivante: http://splendige.pl/vw2rem.css

Je suppose que vous connaissez tous les 'em' unités (sinon: http://www.w3schools.com/cssref/css_units.asp ). Après quelques tests, j'ai découvert que les anciens navigateurs Android (ainsi que tous les autres) supportent parfaitement les unités 'rem', qui fonctionnent de la même manière que 'em', mais sont relatives à la déclaration de taille de police de l'élément ROOT (dans la plupart des cas, la balise html).

Ainsi, le moyen le plus simple de réaliser cela était de déclarer la taille de la police pour la balise HTML égale à 1% de la largeur de la fenêtre d'affichage, par exemple. 19.2px pour la fenêtre 1920px et utilisez de nombreuses requêtes multimédia pour l’ensemble de la plage 1920-320px. Ainsi, dans toutes les résolutions, l'unité 'rem' est égale à 'vw' (l'étape est 10px, mais vous pouvez même essayer de déclarer html {font-size} pour chaque 1px). Ensuite, je viens de remplacer par lot «vw» par «rem» et d'admirer la mise en page de travail sur le navigateur natif Android 4.3.

De plus, vous pouvez alors redéclarer la taille de la police même pour la balise body entière (dans les unités de votre choix: px, em, pt, etc.) et cela n'affecte PAS l'égalité 'rem' en 'vw' dans la feuille de style entière. .

J'espère que cela t'aides. Je sais que ça a l'air un peu ridicule, mais ça marche comme un charme. Rappelez-vous: si quelque chose a l'air stupide, mais fonctionne, ce n'est pas stupide :)

2
k0m0r

"jquery.columns" est jusqu'à présent la meilleure des solutions.

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

Vous n'avez besoin que de 2 lignes de codes pour transformer "vh" en "échelle de tous les navigateurs".

Déclarez une classe en HTML:

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

Puis en javascript:

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

J'ai publié une petite bibliothèque qui facilite l'utilisation des dimensions relatives à la fenêtre d'affichage. N'oubliez pas que ce n'est pas un remplissage multiple, vous devez donc appliquer des classes aux éléments que vous souhaitez redimensionner. Par exemple, <div class="vh10 vw30">hello</div> remplira 10% de la hauteur et 30% de la largeur.

Découvrez-le: https://github.com/joaocunha/v-unit

0
João Cunha

La solution la plus simple et la plus élégante que j'ai trouvée consiste simplement à créer une div de hauteur: 1vh; et largeur: 1vw; et lorsque la page se charge, récupérez ces valeurs en pixels avec getBoundingClientRect (). ajoutez ensuite un écouteur au document pour écouter le redimensionnement de l'écran et mettez à jour la taille lorsque l'écran est redimensionné.

Je sauvegarde la valeur en pixels de vh et vw et puis chaque fois que je dois utiliser vh, je dirais simplement 100 * vh, ce qui me donnerait 100vh.

Voici un extrait de code sur son implémentation, ma réponse est en vanilla js, pas besoin de 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>

0
Chance