Использование getComputedStyle с рамкой должно возвращать высоту без границы и отступов.

EDIT 3/Final: проблема/вопрос Computed Style объяснена ниже, но для других, которые появятся позже, моя настоящая проблема решена с помощью Flex Boxes и измерений Vx в сочетании с border-box. ИМХО "дисплей: гибкий;" является ответом на многие вопросы, и, хотя я изо всех сил пытаюсь заставить его делать то, что я хочу, избавляет вас от необходимости работать против CSS!

РЕДАКТИРОВАТЬ 2: Следующее, несомненно, нуждается в рефакторинге, но если вы можете сказать мне, что оно делает то, о чем я просил, это было бы здорово. Изменение, которое я должен был сделать, состояло в том, чтобы добавить clientTop с offsetTop в уравнении: -

function resizeContent()
{
var browserHeight = window.outerHeight;
var offesetHeight, offsetWidth;

var viewHeight = window.innerHeight;
var viewWidth  = window.innerWidth;

var chromeFootPrint = browserHeight - viewHeight;
var tmpHeight = viewHeight;

if (window.matchMedia("(orientation: portrait)").matches) {
    if (viewWidth > viewHeight) {
        viewHeight = viewWidth - chromeFootPrint;
        viewWidth = tmpHeight + chromeFootPrint;
    }
} else {
    if (viewWidth < viewHeight) {
        viewHeight = viewWidth - chromeFootPrint;
        viewWidth = tmpHeight + chromeFootPrint;
    }
}

var dimTarget  = logScroll;
var offsetTop  = dimTarget.offsetTop  + dimTarget.clientTop;
var offsetLeft = dimTarget.offsetLeft + dimTarget.clientLeft;

while (dimTarget = dimTarget.offsetParent) {
    offsetTop  += dimTarget.offsetTop  + dimTarget.clientTop;
    offsetLeft += dimTarget.offsetLeft + dimTarget.clientLeft;
}

logScrollHeight        = viewHeight - (offsetTop + fireBreak);
logScroll.style.height = logScrollHeight + "px";
logScroll.style.width  = getStyle(contentDiv).width;
logWindow.style.height = logScroll.style.height;
logWindow.style.width  = logScroll.style.width;

logWindow.scrollTop = logWindow.scrollHeight - logScrollHeight;

contentDiv.style.visibility = "visible"; // Now we're presentable
}

а это противопожарный расчет: -

var outerStyle = getStyle(wholeScreen);
fireBreak = Number(outerStyle.paddingBottom.match("[0-9.]*"))
          + Number(outerStyle.borderBottomWidth.match("[0-9.]*"))
          ;

resizeContent();            

РЕДАКТИРОВАТЬ 1: Хорошо, позвольте мне перефразировать вопрос: - Как узнать высоту моего содержимого DIV с помощью: -

width: 250px;
border: 3px solid green;    
padding: 0.5em;
box-sizing: border-box;

В настоящее время мне нужно сделать это: -

logScrollHeight = viewHeight - 
    (offsetTop + Number(getStyle(headerDiv).paddingBottom.match("[0-9.]*")));

Оригинальный вопрос: -

Это обязательно будет дубликат, но после почти часа поиска я нашел много похожих/идентичных вопросов, но не нашел реального ответа :-(

Почему границы и отступы не вычитаются из высоты?

К счастью, возвращаемые значения boundryBottomWidth и PaddingBottom были преобразованы в пиксели (включая, к сожалению, строку «px»), но разве в стандарте не сказано, что должна быть возвращена полезная высота?


person McMurphy    schedule 15.07.2017    source источник
comment
Кстати, кто-то предложил дисплей: кроме встроенного. Я так пробовал и никаких изменений.   -  person McMurphy    schedule 15.07.2017
comment
Я не совсем понимаю вопрос, но похоже, что вы используете не тот инструмент. getComputedStyle возвращает только текущие назначенные правила, после синтаксического анализа и сериализации вы не можете получить из него высоту элемента (например, он может быть обернут масштабированным элементом). Чтобы получить высоту элемента, либо вызовите его метод getBoundingClientRect, или его свойства clientHeight или offsetHeight в зависимости от того, что вы хотите.   -  person Kaiido    schedule 15.07.2017
comment
@Kaiido clientHeight вычитает borderWidth, но по-прежнему включает отступы. OffsetHeight включает в себя оба :-( есть другие идеи?   -  person McMurphy    schedule 16.07.2017
comment
Потому что вам нужна высота без отступов и границ? Затем let s = getComputedStyle(element); let height = element.clientHeight - (parseFloat(s.paddingTop) + parseFloat(s.paddingBottom). Обратите внимание, что box-sizing будет влиять на то, как будут вычисляться свойства CSS height и width, но здесь вы не устанавливаете height : это не влияет на то, откуда эти методы будут выводить текущие значения.   -  person Kaiido    schedule 16.07.2017


Ответы (2)


когда вы устанавливаете box-sizing как border-box:

Свойства ширины и высоты включают содержимое, отступы и границы, но не поля

Поэтому, когда вы используете getComputedStyle для получения высоты элемента, конечно, она включает в себя высоту заполнения и границы.

вы можете взглянуть на свойство box-sizing и блочная модель CSS

person Julien    schedule 15.07.2017
comment
Я видел эти 2 ссылки. Но, должно быть, пропустил (и до сих пор не вижу) ваш цитируемый текст? В любом случае, как тогда получить высоту содержимого без рамки + отступ? - person McMurphy; 16.07.2017
comment
developer.mozilla.org/en-US/docs/Web/ CSS/box-sizing перейдите в Syntax =› Values ​​=› border-box , тогда вы сможете найти текст. если вы хотите получить высоту без границы и заполнения, проверьте это: stackoverflow.com/questions/25197184/ - person Julien; 16.07.2017
comment
О да, я видел это в отношении свойств Элемента. Я думал, что ваш текст относится к значениям высоты/ширины, возвращаемым из calculatedStyle. - person McMurphy; 16.07.2017

Чтобы получить высоту элемента, вы не используете getComputedStyle.

getComputedStyle следует использовать только для получения проанализированных значений, которые в настоящее время применяются из разных таблиц стилей. Другими словами, вы можете видеть его как живую таблицу стилей, ориентированную только на один элемент, со стандартизированными единицами измерения.

Но ни в коем случае его нельзя использовать для получения текущей высоты или ширины элемента. Слишком много факторов может повлиять на установленное значение, и элемент может даже иметь высоту без какого-либо набора правил CSS height.

Так что да... когда правило CSS height установлено в auto, вы получите вычисленное значение, которое может совпадать с реальной высотой элемента, но может и не совпадать.

Таким образом, чтобы получить отображаемую высоту элемента без рамки и отступов, нам нужно будет сделать некоторые вычисления самостоятельно.
Element#getBoundingClientRect() даст нам реальные отображаемые размеры нашего элемента, включая преобразования. .offsetHeight даст нам непреобразованную высоту, включая рамку, а .clientHeight даст нам непреобразованную высоту с отступом.

Это означает, что нам сначала нужно получить все вычисленные значения границ и отступов, затем получить текущий масштаб нашего элемента и, наконец, удалить масштабированные поля отступов и границ из значений, которые мы получаем с помощью getBoundingClientRect.

Вот пример, который нарисует новый прямоугольник div поверх ограничительной рамки элемента без отступов и рамок.

let marker;
scale.onclick = e => {
  element.classList.toggle('scaled');
  drawRect();
}
boxSizing.onclick = e => {
  element.classList.toggle('boxSized');
  drawRect();
}

function drawRect() {
  // remove previous marker if any
  if (marker && marker.parentNode) {
    marker.remove();
    marker = null;
  }

  // first get the border and padding values
  let computed = getComputedStyle(element);
  let borderLeft = parseFloat(computed.borderLeftWidth);
  let borderWidth = borderLeft + parseFloat(computed.borderRightWidth);
  let borderTop = parseFloat(computed.borderTopWidth);
  let borderHeight = borderTop + parseFloat(computed.borderBottomWidth);
  let paddingLeft = parseFloat(computed.paddingLeft);
  let paddingWidth = paddingLeft + parseFloat(computed.paddingRight)
  let paddingTop = parseFloat(computed.paddingTop);
  let paddingHeight = paddingTop + parseFloat(computed.paddingBottom);

  // get the current bounding rect, including the border-box
  let rect = element.getBoundingClientRect();
  // we need to get the current scale since the computed values don't know about it...
  let scale = 1 / (element.offsetHeight / rect.height);
  // the real displayed height and width without border nor padding
  let height = rect.height - ((borderHeight + paddingHeight) * scale);
  let width = rect.width - ((borderWidth + paddingWidth) * scale);

  // create our rectangle
  marker = document.createElement('div');
  marker.classList.add('marker');
  marker.style.height = height + 'px';
  marker.style.width = width + 'px';
  // we need to scale border + padding again
  marker.style.top = (rect.top + (borderTop + paddingTop) * scale) + 'px';
  marker.style.left = (rect.left + (borderLeft + paddingLeft) * scale) + 'px';
  document.body.append(marker);
}
#element {
  width: 250px;
  border: 0.5em solid green;
  padding: 0.5em;
  margin-top: 12px;
}

#element.scaled {
  transform: scale(2);
  transform-origin: top left;
}

#element.boxSized {
  box-sizing: border-box;
}

.marker {
  position: fixed;
  width: 3px;
  background: rgba(0, 0, 0, .3)
}
<label>scale
  <input id="scale" type="checkbox">
</label>
<label>box-sizing
  <input id="boxSizing" type="checkbox">
</label>
<div id="element">
  Hello
  <br> world
</div>

person Kaiido    schedule 16.07.2017
comment
@kalido Спасибо за подробный ответ. Я думаю, что это проще, чем это. Я только что обнаружил, что существует такая вещь, как FlexBox, которая даст вам лучшее представление о том, что я пытаюсь сделать. Это размер отверстия, а затем установите мой DIV, чтобы он соответствовал/затыкал его. (Когда телефон/устройство также переходит в альбомную/портретную ориентацию) Я думаю, что мне все еще нужно свернуть свою собственную, поскольку страница начинается со статического размера в окне просмотра устройства, но может быть добавлена ​​​​позже. - person McMurphy; 16.07.2017