ChatGPT解决这个技术问题 Extra ChatGPT

如何检索 HTML 元素的实际宽度和高度?

假设我有一个希望在浏览器显示(视口)居中的 <div>。为此,我需要计算 <div> 元素的宽度和高度。

我应该使用什么?请包含有关浏览器兼容性的信息。

请记住,通过任何方法获取元素的高度总是会产生性能影响,因为它会使浏览器重新计算页面中所有元素的位置(重排)。因此,避免做太多。查看 this list 了解哪些情况会触发重排。

A
Alan W. Smith

您应该使用 .offsetWidth.offsetHeight 属性。请注意,它们属于元素,而不是 .style

var width = document.getElementById('foo').offsetWidth;

.getBoundingClientRect() 函数在执行 CSS 转换后将元素的尺寸和位置作为浮点数返回。

> console.log(document.getElementById('foo').getBoundingClientRect())
DOMRect {
    bottom: 177,
    height: 54.7,
    left: 278.5,​
    right: 909.5,
    top: 122.3,
    width: 631,
    x: 278.5,
    y: 122.3,
}

谨防!如果您最近对元素进行了某些 DOM 修改,则 offsetHeight/offsetWidth 可以返回 0。修改元素后,您可能必须在 setTimeout 调用中调用此代码。
什么情况下返回0?
我无法确定 offsetWidth 在我的情况下返回 0 的原因,因为我最初没有编写代码,但在 onload 事件中我总是得到 0。
@JDandChips:如果元素为 display:none,则 offsetWidth 将为 0,而在此实例中计算的 width 可能仍具有正值。 visibility:hidden 不影响 offsetWidth
@Supuhstar 都有不同的含义。 offsetWidth 返回“整个”框,包括内容、内边距和边框;而 clientWidth 仅返回内容框的大小(因此,只要元素具有任何非零填充和/或边框,它将具有较小的值)。 (为清晰起见,修改了模组)
Z
Zach Lysobey

看看Element.getBoundingClientRect()

此方法将返回一个包含 widthheight 和一些其他有用值的对象:

{
    width: 960,
    height: 71,
    top: 603,
    bottom: 674,
    left: 360,
    right: 1320
}

例如:

var element = document.getElementById('foo');
var positionInfo = element.getBoundingClientRect();
var height = positionInfo.height;
var width = positionInfo.width;

我相信这不存在 .offsetWidth.offsetHeight 有时会返回 0 的问题(如 comments here 中所述)

另一个区别是 getBoundingClientRect() 可能返回小数像素,其中 .offsetWidth.offsetHeight 将四舍五入到最接近的整数。

IE8 注意getBoundingClientRect 不返回 IE8 及以下版本的高度和宽度。*

如果您必须支持 IE8,请使用 .offsetWidth.offsetHeight

var height = element.offsetHeight;
var width = element.offsetWidth;

值得注意的是,该方法返回的 Object 并不是真正的 normal 对象。它的属性不是 enumerable(例如,Object.keys 不能开箱即用。)

在此处了解更多信息:How best to convert a ClientRect / DomRect into a plain Object

参考:

.offsetHeight:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetHeight

.offsetWidth:https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/offsetWidth

.getBoundingClientRect():https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect


getboundingClientRect() 将返回通过 css 缩放的元素的实际宽度和高度,而 offsetHeightoffsetWidth 不会。
t
tvanfosson

注意:这个答案写于 2008 年。当时对大多数人来说最好的跨浏览器解决方案确实是使用 jQuery。我将答案留给后代,如果您使用的是 jQuery,这是一个很好的方法。如果您使用的是其他框架或纯 JavaScript,则可接受的答案可能是要走的路。

从 jQuery 1.2.6 开始,您可以使用核心 CSS functionsheightwidth(或 outerHeightouterWidth,视情况而定)之一。

var height = $("#myDiv").height();
var width = $("#myDiv").width();

var docHeight = $(document).height();
var docWidth = $(document).width();

G
Graham

以防万一它对任何人有用,我用相同的 css 放置了一个文本框、按钮和 div:

width:200px;
height:20px;
border:solid 1px #000;
padding:2px;

<input id="t" type="text" />
<input id="b" type="button" />
<div   id="d"></div>

我在 chrome、firefox 和 ie-edge 中尝试过,我尝试使用 jquery 和不使用,我尝试使用和不使用 box-sizing:border-box。始终与 <!DOCTYPE html>

结果:

                                                               Firefox       Chrome        IE-Edge    
                                                              with   w/o    with   w/o    with   w/o     box-sizing

$("#t").width()                                               194    200    194    200    194    200
$("#b").width()                                               194    194    194    194    194    194
$("#d").width()                                               194    200    194    200    194    200

$("#t").outerWidth()                                          200    206    200    206    200    206
$("#b").outerWidth()                                          200    200    200    200    200    200
$("#d").outerWidth()                                          200    206    200    206    200    206

$("#t").innerWidth()                                          198    204    198    204    198    204
$("#b").innerWidth()                                          198    198    198    198    198    198
$("#d").innerWidth()                                          198    204    198    204    198    204

$("#t").css('width')                                          200px  200px  200px  200px  200px  200px
$("#b").css('width')                                          200px  200px  200px  200px  200px  200px
$("#d").css('width')                                          200px  200px  200px  200px  200px  200px

$("#t").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#b").css('border-left-width')                              1px    1px    1px    1px    1px    1px
$("#d").css('border-left-width')                              1px    1px    1px    1px    1px    1px

$("#t").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#b").css('padding-left')                                   2px    2px    2px    2px    2px    2px
$("#d").css('padding-left')                                   2px    2px    2px    2px    2px    2px

document.getElementById("t").getBoundingClientRect().width    200    206    200    206    200    206
document.getElementById("b").getBoundingClientRect().width    200    200    200    200    200    200
document.getElementById("d").getBoundingClientRect().width    200    206    200    206    200    206

document.getElementById("t").offsetWidth                      200    206    200    206    200    206
document.getElementById("b").offsetWidth                      200    200    200    200    200    200
document.getElementById("d").offsetWidth                      200    206    200    206    200    206

只是要清楚......这些浏览器中的任何一个都做不同的事情吗?我找不到任何差异......另外,我还没有投票,但这并没有真正直接回答这个问题,尽管它可以很容易地编辑这样做。
不是为了回答这个问题——它已经被回答了。只是一些有用的信息,是的,所有主要的最新版本浏览器都同意这些值 - 这是一件好事。
嗯......如果你的意图不是回答这个问题,那么这并不真正属于这里(作为“答案”)。我会考虑将其放入一些外部资源(可能是 GitHub 要点或博客文章)中,并将其链接到对原始问题或答案之一的评论中。
@ZachLysobey 每条规则都有例外——这是一件很酷、很有用的东西。
H
HarlemSquirrel

根据MDN: Determining the dimensions of elements

offsetWidthoffsetHeight 返回“元素占用的总空间量,包括可见内容的宽度、滚动条(如果有)、填充和边框”

clientWidthclientHeight 返回“实际显示的内容占用了多少空间,包括填充但不包括边框、边距或滚动条”

scrollWidthscrollHeight 返回“内容的实际大小,无论当前有多少可见”

所以这取决于测量的内容是否预计会超出当前的可视区域。


K
Kornel

您只需要为 IE7 和更早版本计算它(并且仅当您的内容没有固定大小时)。我建议使用 HTML 条件注释来限制对不支持 CSS2 的旧 IE 的攻击。对于所有其他浏览器,请使用:

<style type="text/css">
    html,body {display:table; height:100%;width:100%;margin:0;padding:0;}
    body {display:table-cell; vertical-align:middle;}
    div {display:table; margin:0 auto; background:red;}
</style>
<body><div>test<br>test</div></body>

这是完美的解决方案。它将任何大小的 <div> 居中,并将其收缩包装到其内容的大小。


L
Lekens

修改元素样式很容易,但读取值有点棘手。

JavaScript 无法读取来自 css(internal/external) 的任何元素样式属性 (elem.style),除非您使用 javascript 中的内置方法调用 getComputedStyle。

getComputedStyle(元素[,伪])

元素:要为其读取值的元素。伪:如果需要,一个伪元素,例如 ::before。空字符串或无参数表示元素本身。

结果是一个具有样式属性的对象,例如 elem.style,但现在涉及所有 css 类。

例如,这里的样式看不到边距:

<head>
  <style> body { color: red; margin: 5px } </style>
</head>
<body>

  <script>
    let computedStyle = getComputedStyle(document.body);

    // now we can read the margin and the color from it

    alert( computedStyle.marginTop ); // 5px
    alert( computedStyle.color ); // rgb(255, 0, 0)
  </script>

</body>

因此修改了您的 javaScript 代码以包含您希望获取它的宽度/高度或其他属性的元素的 getComputedStyle

window.onload = function() {

    var test = document.getElementById("test");
    test.addEventListener("click", select);


    function select(e) {                                  
        var elementID = e.target.id;
        var element = document.getElementById(elementID);
        let computedStyle = getComputedStyle(element);
        var width = computedStyle.width;
        console.log(element);
        console.log(width);
    }

}

计算和解析值

CSS中有两个概念:

计算的样式值是应用所有 CSS 规则和 CSS 继承后的值,作为 CSS 级联的结果。它可能看起来像 height:1em 或 font-size:125%。已解决的样式值是最终应用于元素的样式值。像 1em 或 125% 这样的值是相对的。浏览器采用计算值并使所有单位固定和绝对,例如:height:20px 或 font-size:16px。对于几何属性,解析值可能有一个浮点数,例如 width:50.5px。

很久以前 getComputedStyle 被创建用于获取计算值,但结果证明解析值更方便,并且标准改变了。所以现在 getComputedStyle 实际上返回了属性的解析值。

请注意:

getComputedStyle 需要完整的属性名称

您应该始终询问您想要的确切属性,例如 paddingLeft 或高度或宽度。否则不能保证正确的结果。例如,如果有属性 paddingLeft/paddingTop,那么我们应该为 getComputedStyle(elem).padding 得到什么?什么都没有,或者可能是已知填充的“生成”值?这里没有标准规则。

还有其他不一致的地方。例如,一些浏览器 (Chrome) 在下面的文档中显示 10px,而其中一些 (Firefox) 则不显示:

<style>
  body {
    margin: 30px;
    height: 900px;
  }
</style>
<script>
  let style = getComputedStyle(document.body);
  alert(style.margin); // empty string in Firefox
</script>

了解更多信息https://javascript.info/styles-and-classes


q
questzen

element.offsetWidth 和 element.offsetHeight 应该按照上一篇文章中的建议进行。

但是,如果您只想使内容居中,则有更好的方法。假设您使用 xhtml 严格的 DOCTYPE。将 margin:0,auto 属性和所需宽度(以 px 为单位)设置为 body 标签。内容与页面中心对齐。


我认为他也想垂直居中,这对 CSS 来说是一个正确的痛苦,除非你能满足一些特定的标准(例如已知大小的内容)
s
sanecin

...似乎CSS有助于将div放在中心...

<style>
 .monitor {
 position:fixed;/* ... absolute possible if on :root */
 top:0;bottom:0;right:0;left:0;
 visibility:hidden;
 }
 .wrapper {
 width:200px;/* this is size range */
 height:100px;
 position:absolute;
 left:50%;top:50%;
 visibility:hidden;
 }

 .content {
 position:absolute;
 width: 100%;height:100%;
 left:-50%;top:-50%;
 visibility:visible;
 }

</style>

 <div class="monitor">
  <div class="wrapper">
   <div class="content">

 ... so you hav div 200px*100px on center ...

  </div>
 </div>
</div>

S
Sergio

您也可以使用以下代码:

var divID = document.getElementById("divid");

var h = divID.style.pixelHeight;

嗯,在 Chrome 和 IE9 中工作,在 Firefox 中似乎不起作用。它仅适用于某些文档类型吗?
pixelHeight 是 Internet Explorer 的一项发明,不应再使用stackoverflow.com/q/17405066/2194590
K
Kamil Kiełczewski

柔性

如果您想在屏幕中心的 <div> 中显示某种弹出消息 - 那么您不需要阅读 <div> 的大小,但您可以使用 flex

.box { 宽度:50px;高度:20px;背景:红色; } .container { 显示:弹性;证明内容:中心;对齐项目:居中;高度:100vh;宽度:100vw;位置:固定; /* 如果 div 下没有内容,则删除它(并记住将 body margins 设置为 0)*/ }

我的 div


V
Venryx

我为此创建了一个实用函数,具有很高的灵活性:

export type Size = {width: number, height: number};
export enum GetSize_Method {
    /** Includes: content, padding. Excludes: border, margin, scroll-bar (if it has one), "position:absolute" descendants. */
    ClientSize = "ClientSize",
    /** Includes: content, padding, border, margin, scroll-bar (if it has one). Excludes: "position:absolute" descendants. */
    OffsetSize = "OffsetSize",
    /** Includes: content, padding, border, margin, scroll-bar (if it has one), "position:absolute" descendants. Excludes: none. */
    ScrollSize = "ScrollSize",
    /** Same as ScrollSize, except that it's calculated after the element's css transforms are applied. */
    BoundingClientRect = "BoundingClientRect",
    /** Lets you specify the exact list of components you want to include in the size calculation. */
    Custom = "Custom",
}
export type SizeComp = "content" | "padding" | "border" | "margin" | "scrollBar" | "posAbsDescendants";

export function GetSize(el: HTMLElement, method = GetSize_Method.ClientSize, custom_sizeComps?: SizeComp[]) {
    let size: Size;
    if (method == GetSize_Method.ClientSize) {
        size = {width: el.clientWidth, height: el.clientHeight};
    } else if (method == GetSize_Method.OffsetSize) {
        size = {width: el.offsetWidth, height: el.offsetHeight};
    } else if (method == GetSize_Method.ScrollSize) {
        size = {width: el.scrollWidth, height: el.scrollHeight};
    } else if (method == GetSize_Method.BoundingClientRect) {
        const rect = el.getBoundingClientRect();
        size = {width: rect.width, height: rect.height};
    } else if (method == GetSize_Method.Custom) {
        const style = window.getComputedStyle(el, null);
        const styleProp = (name: string)=>parseFloat(style.getPropertyValue(name));

        const padding = {w: styleProp("padding-left") + styleProp("padding-right"), h: styleProp("padding-top") + styleProp("padding-bottom")};
        const base = {w: el.clientWidth - padding.w, h: el.clientHeight - padding.h};
        const border = {w: styleProp("border-left") + styleProp("border-right"), h: styleProp("border-top") + styleProp("border-bottom")};
        const margin = {w: styleProp("margin-left") + styleProp("margin-right"), h: styleProp("margin-top") + styleProp("margin-bottom")};
        const scrollBar = {w: (el.offsetWidth - el.clientWidth) - border.w - margin.w, h: (el.offsetHeight - el.clientHeight) - border.h - margin.h};
        const posAbsDescendants = {w: el.scrollWidth - el.offsetWidth, h: el.scrollHeight - el.offsetHeight};

        const sc = (name: SizeComp, valIfEnabled: number)=>custom_sizeComps.includes(name) ? valIfEnabled : 0;
        size = {
            width: sc("content", base.w) + sc("padding", padding.w) + sc("border", border.w)
                    + sc("margin", margin.w) + sc("scrollBar", scrollBar.w) + sc("posAbsDescendants", posAbsDescendants.w),
            height: sc("content", base.h) + sc("padding", padding.h) + sc("border", border.h)
                    + sc("margin", margin.h) + sc("scrollBar", scrollBar.h) + sc("posAbsDescendants", posAbsDescendants.h),
        };
    }
    return size;
}

用法:

const el = document.querySelector(".my-element");
console.log("Size:", GetSize(el, "ClientSize"));
console.log("Size:", GetSize(el, "Custom", ["content", "padding", "border"]));

f
fguillen

这是唯一对我有用的东西:

element.clientWidth -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-left")) -
parseFloat(window.getComputedStyle(element, null).getPropertyValue("padding-right"))

A
Arko

如果 offsetWidth 返回 0,则可以获取元素的样式宽度属性并在其中搜索数字。 “100 像素”-> 100

/\d*/.exec(MyElement.style.width)


A
Aleksey Mazurenko

这是确定特定 Dom 元素高度的 WKWebView 的代码(不适用于整个页面)

let html = "<body><span id=\"spanEl\" style=\"font-family: '\(taskFont.fontName)'; font-size: \(taskFont.pointSize - 4.0)pt; color: rgb(\(red), \(blue), \(green))\">\(textValue)</span></body>"
webView.navigationDelegate = self
webView.loadHTMLString(taskHTML, baseURL: nil)

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("document.getElementById(\"spanEl\").getBoundingClientRect().height;") { [weak self] (response, error) in
        if let nValue = response as? NSNumber {

        }
    }
}

需要明确的是,这是 iOS swift 代码,对吧?不是 JavaScript。我拒绝投反对票(b/c 这实际上可能非常有用),但请注意,这确实回答了这个问题,并且可能更适合另一个特定于 iOS 的问题。如果没有一个已经存在,也许考虑问一个并自我回答。
u
user1767599

使用宽度参数如下:

   style={{
      width: "80%",
      paddingLeft: 100,
      paddingRight: 200,
      paddingTop: 30,
      paddingBottom: 30,
      border: "3px solid lightGray",
    }}

看起来像是用于设置宽度的 JSX 属性?