web-dev-qa-db-fra.com

Cross-browser (IE8-) getComputedStyle avec Javascript?

Puisque IE8 ne supporte pas getComputedStyle, nous ne pouvons utiliser que currentStyle. Toutefois, il ne renvoie pas la valeur "calculée" réelle de certaines propriétés.

Par exemple:

<style type="text/css">
#div {/* no properties are defined here */}
</style>
<div id="div">div</div>
// returns "medium" instead of 0px
document.getElementById('div').currentStyle.borderLeftWidth

// returns "auto" instead of 0px
document.getElementById('div').currentStyle.marginLeft

// returns "undefined" instead of 1
document.getElementById('div').currentStyle.opacity

Quelqu'un at-il une solution multi-navigateur pour toutes les propriétés sans utiliser jQuery ou d'autres bibliothèques Javascript?

23
user1643156

Vous ne voulez pas utiliser jQuery mais rien ne vous empêche de regarder dans le code et de voir comment ils l'ont traité :-)

Dans le code jQuery, il y a une référence à propos de ce commentaire qui semble aller droit au but (lisez également l'intégralité de l'article) . Voici le code jQuery qui devrait traiter votre problème:

else if ( document.documentElement.currentStyle ) {
    curCSS = function( elem, name ) {
        var left, rsLeft,
            ret = elem.currentStyle && elem.currentStyle[ name ],
        style = elem.style;

    // Avoid setting ret to empty string here
    // so we don't default to auto
    if ( ret == null && style && style[ name ] ) {
        ret = style[ name ];
    }

    // From the awesome hack by Dean Edwards
    // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

    // If we're not dealing with a regular pixel number
    // but a number that has a weird ending, we need to convert it to pixels
    // but not position css attributes, as those are proportional to the parent element instead
    // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
    if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {

        // Remember the original values
        left = style.left;
        rsLeft = elem.runtimeStyle && elem.runtimeStyle.left;

        // Put in the new values to get a computed value out
        if ( rsLeft ) {
            elem.runtimeStyle.left = elem.currentStyle.left;
        }
        style.left = name === "fontSize" ? "1em" : ret;
        ret = style.pixelLeft + "px";

        // Revert the changed values
        style.left = left;
        if ( rsLeft ) {
            elem.runtimeStyle.left = rsLeft;
        }
    }

    return ret === "" ? "auto" : ret;
};
}
7
user1047100

Voici une fonction multi-navigateur pour obtenir un style calculé ...

getStyle = function (el, prop) {
    if (typeof getComputedStyle !== 'undefined') {
        return getComputedStyle(el, null).getPropertyValue(prop);
    } else {
        return el.currentStyle[prop];
    }
}

Vous pouvez le stocker en tant qu'utilitaire dans un objet ou simplement l'utiliser tel que fourni. Voici un exemple de démo!

// Create paragraph element and append some text to it
var p = document.createElement('p');
p.appendChild(document.createTextNode('something for fun'));

// Append element to the body
document.getElementsByTagName('body')[0].appendChild(p);

// Set hex color to this element
p.style.color = '#999';

// alert element's color using getStyle function
alert(getStyle(p, 'color'));

Consultez cette démo pour la voir en action:

getStyle = function(el, prop) {
  if (getComputedStyle !== 'undefined') {
    return getComputedStyle(el, null).getPropertyValue(prop);
  } else {
    return el.currentStyle[prop];
  }
}

// Create paragraph element and append some text to it
var p = document.createElement('p');
p.appendChild(document.createTextNode('something for fun'));

// Append element to the body
document.getElementsByTagName('body')[0].appendChild(p);

// Set hex color to this element
p.style.color = '#999';

// alert element's color using getStyle function
console.log(getStyle(p, 'color'));
p {
  color: red;
}

16
Gabriel kyabu

au lieu de :

getComputedStyle !== 'undefined'

cA devrait etre :

typeof getComputedStyle !== 'undefined'

sinon cela ne fonctionnerait jamais.

7
Eugen Mihailescu

Cela ne fonctionnera pas pour tous les styles mais fonctionnera pour les dimensions (c'est ce dont j'avais besoin). 

Au lieu d'essayer de deviner quels styles sont appliqués, utilisez simplement la position en pixels de chacun des quatre côtés d'un élément de type boîte pour calculer les dimensions. Cela fonctionnera également vers IE 5 et FF 3.

height = elem.getBoundingClientRect().bottom - elem.getBoundingClientRect().top;
width = elem.getBoundingClientRect().right - elem.getBoundingClientRect().left;

Voir aussi: getBoundingClientRect is awesome

Si cela ne fonctionne toujours pas pour vous, consultez ce violon je mets ensemble pour calculer la largeur intérieure d'une boîte. Il utilise les éléments suivants comme calage pour getComputedStyle:

/**
 * getComputedStyle function for IE8
 * borrowed from:
 * http://missouristate.info/scripts/2013/common.js
 */
"getComputedStyle" in window || function() {
  function c(a, b, g, e) {
    var h = b[g];
    b = parseFloat(h);
    h = h.split(/\d/)[0];
    e = null !== e ? e : /%|em/.test(h) && a.parentElement ? c(a.parentElement, a.parentElement.currentStyle, "fontSize", null) : 16;
    a = "fontSize" == g ? e : /width/i.test(g) ? a.clientWidth : a.clientHeight;
    return "em" == h ? b * e : "in" == h ? 96 * b : "pt" == h ? 96 * b / 72 : "%" == h ? b / 100 * a : b;
  }
  function a(a, c) {
    var b = "border" == c ? "Width" : "", e = c + "Top" + b, h = c + "Right" + b, l = c + "Bottom" + b, b = c + "Left" + b;
    a[c] = (a[e] == a[h] == a[l] == a[b] ? [a[e]] : a[e] == a[l] && a[b] == a[h] ? [a[e], a[h]] : a[b] == a[h] ? [a[e], a[h], a[l]] : [a[e], a[h], a[l], a[b]]).join(" ");
  }
  function b(b) {
    var d, g = b.currentStyle, e = c(b, g, "fontSize", null);
    for (d in g) {
      /width|height|margin.|padding.|border.+W/.test(d) && "auto" !== this[d] ? this[d] = c(b, g, d, e) + "px" : "styleFloat" === d ? this["float"] = g[d] : this[d] = g[d];
    }
    a(this, "margin");
    a(this, "padding");
    a(this, "border");
    this.fontSize = e + "px";
    return this;
  }
  b.prototype = {};
  window.getComputedStyle = function(a) {
    return new b(a);
  };
}();
4
Kyle Falconer

C'était trop gros pour un montage, il a donc été créé mais il ne fournit pas une réponse complète à la question posée.


La réponse de Gabriel échoue avec une propriété telle que "backgroundColor" ou "background-color" en fonction de la version du navigateur, car .getPropertyValue attend le nom de la propriété CSS et el.currentStyle[prop] requiert la version en chameau. 

Voici une version corrigée qui attend toujours la version camel-case:

function getStyle(el, prop) {
    return (typeof getComputedStyle !== 'undefined' ?
        getComputedStyle(el, null) :
        el.currentStyle
    )[prop]; // avoid getPropertyValue altogether
}
2
Emile Bergeron