web-dev-qa-db-fra.com

jQuery/JavaScript: convertissez facilement les pixels en em

Je cherche un moyen simple d’ajouter une ligne de code à un de mes plugins, de convertir quelques valeurs de pixel en valeurs em, car la présentation de mon projet doit être dans ems. Existe-t-il un moyen simple de procéder, car je ne souhaite pas ajouter de plug-in tiers au site.

Le code ne sera pas posté ici, car il n'a rien à voir avec le plugin lui-même.

Merci.

Exemple: 13px -> ?? em

22
user759235

Je pense que votre question est très importante. Étant donné que les classes de résolutions d’affichage augmentent rapidement, utiliser le positionnement em pour prendre en charge une large gamme de résolutions d’écran est une approche très séduisante. Mais peu importe la difficulté avec laquelle vous essayez de tout conserver - parfois vous obtenez une valeur en pixels, que ce soit par glisser-déposer JQuery ou par une autre bibliothèque, et vous souhaitez convertir cette valeur en em avant de la renvoyer au serveur pour la persistance. Ainsi, la prochaine fois que l'utilisateur regardera la page, l'élément sera correctement positionné, quelle que soit la résolution de l'écran du périphérique utilisé. 

Les plugins JQuery ne sont pas très effrayants lorsque vous pouvez réviser le code, spécialement s’ils sont courts et faciles comme ce plugin convertit les valeurs de pixels en em comme vous le souhaitez. En fait, il est si court que je vais coller le tout ici. Pour les droits d'auteur, voir le lien.

$.fn.toEm = function(settings){
    settings = jQuery.extend({
        scope: 'body'
    }, settings);
    var that = parseInt(this[0],10),
        scopeTest = jQuery('<div style="display: none; font-size: 1em; margin: 0; padding:0; height: auto; line-height: 1; border:0;">&nbsp;</div>').appendTo(settings.scope),
        scopeVal = scopeTest.height();
    scopeTest.remove();
    return (that / scopeVal).toFixed(8) + 'em';
};


$.fn.toPx = function(settings){
    settings = jQuery.extend({
        scope: 'body'
    }, settings);
    var that = parseFloat(this[0]),
        scopeTest = jQuery('<div style="display: none; font-size: 1em; margin: 0; padding:0; height: auto; line-height: 1; border:0;">&nbsp;</div>').appendTo(settings.scope),
        scopeVal = scopeTest.height();
    scopeTest.remove();
    return Math.round(that * scopeVal) + 'px';
};

Exemple d'utilisation: $(myPixelValue).toEm(); ou $(myEmValue).toPx();.

Je viens de tester cela dans mon application, cela fonctionne très bien. Alors j'ai pensé partager.

18
Aras

Ce qui suit semble correspondre à vos besoins, bien qu'il soit basé sur le font-size du parent et de l'élément lui-même, renvoyé dans px:

function px2em(elem) {
    var W = window,
        D = document;
    if (!elem || elem.parentNode.tagName.toLowerCase() == 'body') {
        return false;
    }
    else {
        var parentFontSize = parseInt(W.getComputedStyle(elem.parentNode, null).fontSize, 10),
            elemFontSize = parseInt(W.getComputedStyle(elem, null).fontSize, 10);

        var pxInEms = Math.floor((elemFontSize / parentFontSize) * 100) / 100;
        elem.style.fontSize = pxInEms + 'em';
    }
}

JS Fiddle preuve de concept .

Remarques:

  • La fonction renvoie false si l'élément que vous essayez de convertir en em est body, mais c'est parce que je ne pouvais pas déterminer s'il était judicieux de définir la valeur sur 1em ou de simplement la laisser seule.

  • Il utilise window.getComputedStyle(), donc il ne fonctionnera pas avec IE, sans quelques ajustements.

Références:

15
David Thomas

Les pixels et les ems sont fondamentalement différents types d'unité. Vous ne pouvez pas simplement convertir entre eux.

Par exemple, un utilisateur avec une taille de police par défaut de 16 px sur un site où les en-têtes de niveau supérieur sont stylés avec une taille de police de 200%, 1em peut être égal à 32 px. Déplacez l'en-tête ailleurs dans le document, cela pourrait être 64px ou 16px. Donnez le même document à un autre utilisateur, par exemple 30/60/15px. Commencez à parler d'un élément différent, et il peut changer à nouveau.

Le plus proche de ce que vous voulez est de convertir les pixels en ems + document + contexte + paramètres. Mais si quelqu'un vous a demandé de présenter votre projet avec ems, il ne sera probablement pas ravi que vous essayiez de le convertir en pixels, puis de le "convertir".

3
Jim

Vieille question, mais pour référence, voici quelque chose que j'ai concocté, la portée et le suffixe sont facultatifs. Transmettez-lui une valeur rem ou em sous forme de chaîne, par exemple. '4em' [vous pouvez utiliser des espaces et des majuscules/minuscules] et la valeur px sera renvoyée. À moins que vous ne lui donniez une portée, qui serait l'élément cible pour la recherche de la valeur EM locale, il sera remplacé par défaut par body, ce qui vous donnera la valeur rem. Enfin, le paramètre de suffixe facultatif [boolean] ajoutera «px» à la valeur renvoyée, de sorte que 48 devient 48px par exemple. 

ex: emRemToPx( '3em', '#content' )

renvoyer 48 caractères sur un document de 16 px et 100% de taille de police

/**
* emRemToPx.js | @whatsnewsisyphus 
* To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
* see CC0 Public Domain Dedication <http://creativecommons.org/publicdomain/zero/1.0/>.
*/
  var emRemToPx = function( value, scope, suffix ) {
    if (!scope || value.toLowerCase().indexOf("rem") >= 0) {
      scope = 'body';
    }
    if (suffix === true) {
      suffix = 'px';
    } else {
      suffix = null;
    }
    var multiplier = parseFloat(value);
    var scopeTest = $('<div style="display: none; font-size: 1em; margin: 0; padding:0; height: auto; line-height: 1; border:0;">&nbsp;</div>').appendTo(scope);
    var scopeVal = scopeTest.height();
    scopeTest.remove();
    return Math.round(multiplier * scopeVal) + suffix;
  };
1
whatsnewsisyphus

Généralement, lorsque vous souhaitez convertir px en em, la conversion a lieu sur l'élément lui-même. getComputedStyle renvoie la valeur dans px qui brise leur réactivité. Le code ci-dessous peut être utilisé pour résoudre ce problème:

/**
 * Get the equivalent EM value on a given element with a given pixel value.
 *
 * Normally the number of pixel specified should come from the element itself (e.g. element.style.height) since EM is
 * relative.
 *
 * @param {Object} element - The HTML element.
 * @param {Number} pixelValue - The number of pixel to convert in EM on this specific element.
 *
 * @returns {Boolean|Number} The EM value, or false if unable to convert.
 */
window.getEmValueFromElement = function (element, pixelValue) {
    if (element.parentNode) {
        var parentFontSize = parseFloat(window.getComputedStyle(element.parentNode).fontSize);
        var elementFontSize = parseFloat(window.getComputedStyle(element).fontSize);
        var pixelValueOfOneEm = (elementFontSize / parentFontSize) * elementFontSize;
        return (pixelValue / pixelValueOfOneEm);
    }
    return false;
};

Son utilisation serait aussi simple que:

var element = document.getElementById('someDiv');
var computedHeightInEm = window.getEmValueFromElement(element, element.offsetHeight);
0
Nicolas Bouvrette

J'ai intégré cette fonctionnalité dans une bibliothèque, avec la vérification du type de paramètre: px-to-em

Étant donné ce code HTML:

<p id="message" style="font-size: 16px;">Hello World!</p>

Vous pouvez vous attendre à ces sorties:

pxToEm(16, message) === 1
pxToEm(24, message) === 1.5
pxToEm(32, message) === 2

Depuis que l'OP a demandé un moyen de faire cela sans bibliothèque, j'ai copié le code source de px-to-em dans une démonstration en direct:

function pxToEm (px, element) {
  element = element === null || element === undefined ? document.documentElement : element;
  var temporaryElement = document.createElement('div');
  temporaryElement.style.setProperty('position', 'absolute', 'important');
  temporaryElement.style.setProperty('visibility', 'hidden', 'important');
  temporaryElement.style.setProperty('font-size', '1em', 'important');
  element.appendChild(temporaryElement);
  var baseFontSize = parseFloat(getComputedStyle(temporaryElement).fontSize);
  temporaryElement.parentNode.removeChild(temporaryElement);
  return px / baseFontSize;
}

console.log(pxToEm(16, message), 'Should be 1');
console.log(pxToEm(24, message), 'Should be 1.5');
console.log(pxToEm(32, message), 'Should be 2');
<p id="message" style="font-size: 16px;">Hello World!</p>

J'ai appris de cette réponse qu'avec getComputedStyle, nous pouvons obtenir de manière fiable la valeur px du diviseur avec le point décimal, ce qui améliore la précision du calcul. J’ai trouvé que la réponse d’Aras pouvait être supérieure à 0,5 px, ce qui nous causait des erreurs d’arrondi.

0
Jackson

Essayez d'utiliser ceci:

parseInt(myPixelValue) / parseFloat($("body").css("font-size"));
0
Tehila