Кросс-браузер (IE8-) getComputedStyle с Javascript?

Поскольку IE8 не поддерживает getComputedStyleмы можем использовать только currentStyle, Однако он не возвращает реальное "вычисленное" значение для некоторых свойств.

Например:

<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

У кого-нибудь есть кросс-браузерное решение для всех свойств без использования jQuery или других библиотек Javascript?

5 ответов

Решение

Вы не хотите использовать jquery, но ничто не мешает вам заглянуть в код и посмотреть, как они с ним справились:-)

Внутри jquery-кода есть ссылка на этот комментарий, которая кажется важной (читайте также всю статью). Вот код jquery, который должен решить вашу проблему:

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;
};
}

Вот кросс-браузерная функция для получения вычисленного стиля...

getStyle = function (el, prop) {
    if (typeof 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
alert(getStyle(p, 'color'));

Проверьте это демо, чтобы увидеть его в действии:

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;
}

Вместо:

getComputedStyle !== 'undefined'

так должно быть:

typeof getComputedStyle !== 'undefined'

иначе это никогда бы не сработало.

Это не будет работать для всех стилей, но будет работать для измерений (это то, что мне нужно).

Вместо того, чтобы пытаться угадать, какие стили применяются, просто используйте положение в пикселях каждой из четырех сторон коробчатого элемента для вычисления размеров. Это также вернется к IE 5 и FF 3.

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

Смотрите также: getBoundingClientRect - это круто

Если это все еще не работает для вас, посмотрите эту скрипку, которую я собрал для расчета внутренней ширины коробки. В качестве прокладки для 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);
  };
}();

Это было слишком велико для редактирования, поэтому он был дан ответ, но он не дает полного ответа на вопрос под рукой.


Габриэль не отвечает с таким свойством, как "backgroundColor" или же "background-color" в зависимости от версии браузера, потому что .getPropertyValue ожидает имя свойства CSS и el.currentStyle[prop] нужна версия на верблюжьем чехле.

Вот исправленная версия, которая всегда ожидает верблюжьей версии:

function getStyle(el, prop) {
    return (typeof getComputedStyle !== 'undefined' ?
        getComputedStyle(el, null) :
        el.currentStyle
    )[prop]; // avoid getPropertyValue altogether
}
Другие вопросы по тегам