Подтвердить что ты не робот

Получить значение свойства CSS элемента (ширина/высота) по мере его установки (в процентах/em/px/etc)

Как можно получить свойство CSS элементов (например, width/height), поскольку оно было задано с помощью правил CSS, в любых единицах, которые были установлены (например,%/em/px)? (В Google Chrome, предпочтительно без рамки).

Использование getComputedStyle возвращает текущее значение в пикселях, поэтому css() в jQuery.

Например:

<div class="b">first</div>
<div id="a" class="a">second</div>

<style>
     div      { width: 100px; }
     x, div#a { width: 50%;   }
     .a       { width: 75%;   }
</style>

Повторяя все div элементы в этом примере, я бы хотел получить вторую ширину div как 50% (и первый как 100px).


Инспектор элементов Chrome может отображать значение свойства CSS, поскольку они были установлены, поэтому это должно быть возможно в Chrome.

Chrome element inspector showing property value as they were set


Не точный дубликат связанного вопроса, так как там принятый ответ есть простой хак, который производит процентную ширину независимо от того, какая ширина установлена. А для остальных вам нужно знать селектор, используемый для создания активного правила? Как узнать это?

4b9b3361

Ответ 1

Хорошая новость! Кажется, есть CSS Typed OM на своем пути в черновиках w3.

Быстрое чтение этого документа, кажется, что целью этой, возможно, быть спецификации, является облегчение доступа к значениям CSSOM из javascript.

Очень важная часть этого для нас здесь заключается в том, что у нас будет CSSUnitValue API, который сможет анализировать значения CSS для объекта формы

{
  value: 100,
  unit: "percent", // | "px" | "em" ...
  type: "percent"  // | "length"
}

И метод Window.getComputedStyleMap(), из которого мы сможем получить значения, фактически применяемые к нашим элементам.

На сегодняшний день кажется, что Chrome только начал его реализовывать, и вам нужно включить флаг функций Experimental Web Platform в about:flags...

(() => {
  if (!window.getComputedStyleMap && !Element.prototype.computedStyleMap) {
    console.error("Your browser doesn't support CSS Typed OM");
    return;
  }
  document.querySelectorAll('.test')
    .forEach((elem) => {
      let styleMap;
      // As defined in specs' drafts
      if (window.getComputedStyleMap) {
        styleMap = window.getComputedStyleMap(elem);
      }
      // Currently Chrome attaches it to the Element proto
      else styleMap = elem.computedStyleMap();

      const widthValue = styleMap.get('width');
      console.log(elem, widthValue);
    });

/* outputs

  <div class="b test">first</div>
  CSSUnitValue {
    "type": "length",
    "unit": "px",
    "value": 100,
    [__proto__]
  }
  
  <div id="a" class="a test">second</div>
  CSSUnitValue {
    "type": "percent",
    "unit": "percent",
    "value": 50,
    [__proto__]
  }

*/

})();
div.test {  width: 100px; }
x,div#a {  width: 50%; }
.a {  width: 75%; }
<div class="b test">first</div>
<div id="a" class="a test">second</div>

Ответ 2

Это не так просто, как просто вызов WebKits getMatchedCSSRules(), он возвращает согласованные правила в порядке приоритета (хотя я не видел упоминания этого порядка в документах), но заказ не учитывает свойство важный приоритет и не включает стили элементов. Поэтому я закончил эту функцию:

getMatchedStyle

function getMatchedStyle(elem, property){
    // element property has highest priority
    var val = elem.style.getPropertyValue(property);

    // if it important, we are done
    if(elem.style.getPropertyPriority(property))
        return val;

    // get matched rules
    var rules = getMatchedCSSRules(elem);

    // iterate the rules backwards
    // rules are ordered by priority, highest last
    for(var i = rules.length; i --> 0;){
        var r = rules[i];

        var important = r.style.getPropertyPriority(property);

        // if set, only reset if important
        if(val == null || important){
            val = r.style.getPropertyValue(property);

            // done if important
            if(important)
                break;
        }
    }

    return val;
}

Пример

Учитывая следующие правила кода и стиля:

<div class="b">div 1</div>
<div id="a" class="a d2">div 2</div>
<div id="b" class="b d3" style="width: 333px;">div 3</div>
<div id="c" class="c d4" style="width: 44em;">div 4</div>

<style>
div      { width: 100px; }
.d3      { width: auto !important; }
div#b    { width: 80%;   }
div#c.c  { width: 444px; }
x, div.a { width: 50%;   }
.a       { width: 75%;   }
</style>

этот код JS

var d = document.querySelectorAll('div');

for(var i = 0; i < d.length; ++i){
    console.log("div " + (i+1) + ":  " + getMatchedStyle(d[i], 'width'));
}

дает следующие ширины для div s:

div 1:  100px
div 2:  50%
div 3:  auto
div 4:  44em

(В jsFiddle)

Ответ 4

Там более новый дубликат сообщения с отличным ответом здесь. Этот ответ был для jQuery, но легко реализовать в чистом js.

function getDefaultStyle(element, prop) {
    var parent = element.parentNode,
        computedStyle = getComputedStyle(element),
        value;
    parent.style.display = 'none';
    value = computedStyle.getPropertyValue(prop);
    parent.style.removeProperty('display');
    return value;
}