获取组件的实际宽度和高度

时间:2013-09-19 09:50:41

标签: javascript jquery html css dom

我们在JavaScript中面临一个相当可怕的问题,我们似乎都没有能力解决这个问题:

我们如何获得DOM元素的宽度和高度,包括子元素,整个盒子模型等,而不会在页面上显示组件?

请记住:我正在寻找建议。即使没有完全回答问题(或者不完全符合指定参数)的答案也可能,而且可能会有所帮助。

主要目标:我通过Javascript将HTML元素添加到页面中 - 来自数据库的大小和样式的HTML元素。问题是他们行为不端,通常是不好的对齐,由于填充/边距不同,一个元素比另一个元素大,所以我需要检查它们的实际大小来解决这些问题。

最终的应用程序将成为一个,正如BigMacAttack在评论中所描述的那样,“紧密结合的第三方HTML控件拼接”几乎可以在现场进行。它需要看起来像完全成熟的桌面应用程序,HTML似乎充满激情地讨厌这个想法。不是我责备它。

无论如何,这是一些示例代码:

JavaScript的:

function exampleElement(caption, content) {
    this.caption = caption;
    this.content = content;
    this.rootElement = document.createElement("div");
}

exampleElement.prototype.constructElement = function() {
    var otherElement = document.createElement("p");
    this.rootElement.className = "exampleElement";
    this.rootElement.textContent = this.caption; 
    otherElement.className = "exampleP";
    otherElement.textContent = this.content;
    this.rootElement.appendChild(otherElement);
    /*I need to know size of the otherElement here*/
    /*here goes code adding stuff into rootElement*/
};

window.onload = function() {
    var ex = new exampleElement("Hello", "Here's text");
    ex.constructElement();
    document.body.appendChild(ex.rootElement);
};

CSS:

.exampleElement {
    padding: 5px;
    margin: 6px;
}

.exampleElement .exampleP {
    padding: 20px;
    margin: 6px;
}

A fiddle

现在,我们需要页面动态地响应窗口的大小和单个组件的内容,这就是为什么在显示对象之前能够获得对象大小的重要性。同样重要的是,对象的创建明确分为三个阶段:

  • 通过新的

  • 创作
  • 构建DOM树(constructElement)

  • 添加到文档中(直接插入正文或另一个DOM树)

在施工阶段我们了解各个元素的大小非常重要。

到目前为止,我们已经尝试通过jQuery,DOM宽度和高度属性来测量它,但是这些都不能直接在页面上显示DOM对象。我尝试过的另一种方法是将几个函数添加到document.body中,获取宽度和高度,然后立即删除它 - 但是,由于我们的CSS文件非常具体,除非插入整个rootElement,否则这是不可靠的由于我们的组件变得相当复杂,所以性能和内存都很糟糕。

我认为完全删除.CSS文件并直接通过JS定义样式的方法至少可以解决部分困境,但必须有更好的方法。

开始赏金以获得更多想法和建议。只是拍摄人物,即使答案不完全在问题的范围内(你将如何做/等等) - 我试图实现的目标是让我生成的JS控件正确地组合在一起。

7 个答案:

答案 0 :(得分:10)

如果您需要最初隐藏手风琴,滑块等需要边界框信息才能正常工作的组件,您会经常遇到此问题。

一个简单的技巧是添加隐藏相关内容可见性的css,并确保它不会闪烁或导致您的布局受到干扰。

它可以是简单的事情:

{   visibility:hidden;
    position:absolute;
    left: -9999px;
}

然后在准备好显示组件时将位置设置回静态或相对,并将可见性恢复为可见。

小提琴在这里,但没有多少:http://jsfiddle.net/gwwar/ZqQtz/1/

答案 1 :(得分:4)

使用javascript获取框模型DOM节点的渲染宽度和高度,而无需将其实际添加到要显示的DOM中。

为了证明这一点,让我们来看看如何在浏览器内部计算DOM节点的渲染高度和宽度。我将引用WebKit如何处理它,因为它是最常用的布局引擎。

在解析文档并将DOM节点添加到“DOM树”时,会为需要显示的DOM节点创建Renderers。这就是“渲染树”的构建方式。

以下是Dave Hyatt在官方WebKit博客上发表的题为"WebCore Rendering I – The Basics"的文章的摘录:

  

“渲染器是通过DOM上称为附件的进程创建的。   在解析文档并添加DOM节点时,会调用一个方法   在DOM节点上调用attach来创建渲染器。

     

void attach()

     

attach方法计算DOM节点的样式信息。如果   显示元素的CSS属性设置为none或节点是否为   显示元素的后代:无设置,然后没有渲染器   将被创建。“

因此,为了提高效率,浏览器甚至不会为显示设置为无的元素计算样式信息。因此,无法通过javascript访问该信息。但是,如果显示属性设置为none,则会发生以下情况:

  

“在附件中,DOM查询CSS以获取样式信息   一个元素。结果信息存储在名为a的对象中   RenderStyle ...可以从RenderObject访问RenderStyle   使用style()方法...主要的主力子类之一   RenderObject是RenderBox。该子类表示对象   服从CSS盒子模型。这些包括任何有边框的对象,   填充,边距,宽度和高度。“

因此,如果您的用例允许您直接从浏览器通过C / C ++检索框模型渲染高度和宽度,并通过其他方式将其传递给您的javascript代码,那么您可以查询高度/宽度方法每个DOM元素的RenderBox子类。这基本上是WebKit开发人员工具获取此信息的方式。

答案 2 :(得分:1)

你可以尝试这个jQuery插件:https://github.com/dreamerslab/jquery.actual

答案 3 :(得分:1)

因为您要求相关答案......

如果您的DOM元素不是按其内容动态调整大小,我会建议以下工作流程。

虽然它可以使你的DOM结构更加臃肿,但通常最好使用“容器”对象。这些对象不具有边框,填充或边距,以保持其DOM维度可预测。然后你可以强迫孩子在它的容器范围内舒展。

您的容器对象将用于查询特定的大小和位置,因为没有额外的属性来解释大小失真。

http://jsfiddle.net/aywS6/

<强> CSS

#container {
    position: absolute;
    margin:0px;
    padding:0px;
    width: 300px;
    height: 100px;
    background: #aaa;
    border: 0 none;
}

#subject {
    position: absolute;
    top: 0px;
    bottom: 0px;
    left: 0px;
    right: 0px;
    padding: 10px 20px;
    background: #aaf;
}

<强> HTML

<div id="container">
    <div id="subject">
        contents...
    </div>
</div>

答案 4 :(得分:1)

这里的问题是在页面上添加此元素之前无法获取元素大小。

在你的方法“constructElement”中,你将元素添加到根元素,但只是在onload上添加到页面。 您的属性“rootElement”没有设置大小属性。

如果要操纵这些属性,请重新考虑对象/方法的结构。

查看我的update of your fiddle

$(function ()
{
    var ex = new exampleElement("Hello", "Here's text");
    ex.constructElement();
    document.body.appendChild(ex.rootElement);

    $("<span/>")
        .text(" => Width is " + $("div").width() + ", and Height is " + $("div").height())
        .appendTo($("div p"));
});

答案 5 :(得分:0)

不知道这是否有帮助,但既然你要求任何答案 :)这就是我所拥有的。

我有一个类似的问题,我希望有一个很好的jQuery效果,根据它的内部内容将HTML容器调整为“自动”高度和宽度。这个想法仍然类似于一些人已经在这里提到的:你在屏幕外的某个地方有一个容器,你把你的东西放在那里,改变尺寸并删除它。所以这是我找到的函数here

jQuery.fn.animateAuto = function(prop, speed, callback) {
    var elem, height, width;
    return this.each(function(i, el) {
        el = jQuery(el), elem = el.clone().css({
            "height" : "auto",
            "width" : "auto"
        }).appendTo("body");
        height = elem.css("height"), width = elem.css("width"), elem.remove();

        if (prop === "height")
            el.animate({
                "height" : height
            }, speed, callback);
        else if (prop === "width")
            el.animate({
                "width" : width
            }, speed, callback);
        else if (prop === "both")
            el.animate({
                "width" : width,
                "height" : height
            }, speed, callback);
    });
};

这段代码比您需要的多一点,但您可能感兴趣的部分是:

elem = el.clone().css({
                "height" : "auto",
                "width" : "auto"
}).appendTo("body");
height = elem.css("height")
width = elem.css("width")

希望这有帮助

答案 6 :(得分:0)

如果主要问题是在将其放到屏幕上之前无法获得大小,我建议创建一个允许div隐藏在页面背景下的类。这应该跨浏览器。

.exampleHidden{
    position: absolute;
    z-index: -1;
}

如果将页面的z-index的主背景设置为0,然后将隐藏的类附加到新元素,则会将其置于背景下。假设它不大于​​你的背景,它现在应该被隐藏,以允许你通过删除.exampleHidden类来实际将它带回前台之前测量和设置高度和宽度。