使用带边框的getComputedStyle应该返回高度sans边框和填充

时间:2017-07-15 12:57:24

标签: javascript css border-box getcomputedstyle

编辑3 /最终:计算风格问题/问题在下面解释,但为了后来其他人的利益,我的真正问题是通过Flex Boxes和Vx测量与边框一起解决的。恕我直言"显示:flex;"是许多问题的答案,尽管我努力让它做我想做的事,但是你不得不反对CSS!

编辑2:以下无疑需要重构,但如果你能告诉我,它确实是我所要求的,那就太棒了。我必须做的改变是将offsetTop中的clientTop添加到等式中: -

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.]*")));

原始问题: -

这肯定是重复的,但经过近一个小时的观察,我发现了许多类似/相同的问题,但没有真正的答案: - (

为什么没有从高度中扣除boundryWith和padding?

值得庆幸的是,boundryBottomWidth和PaddingBottom返回已经转换为像素(包括&#34; px&#34;字符串遗憾),但标准中是否表示应该返回可用的高度?

2 个答案:

答案 0 :(得分:0)

将box-sizing设置为border-box:

宽度和高度属性包括内容,填充和边框,但不包括边距

因此,当您使用getComputedStyle获取元素的高度时,当然它包含填充和边框的高度。

您可以查看box-sizing propertycss box model

答案 1 :(得分:0)

要获取元素的高度,请不要使用getComputedStyle

getComputedStyle仅应用于获取当前从不同样式表应用的已解析值。换句话说,您可以将其视为实时样式表,仅针对具有标准化单位的单个元素。

但绝不应该用它来获取元素的当前高度或宽度。太多因素可能会干扰设定值,并且元素甚至可以具有高度,而无需设置任何CSS height规则。

所以是的......当height CSS规则设置为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>