没有jQuery的现代浏览器的width()和height()

时间:2010-10-17 20:07:08

标签: height width element javascript

我试图为弹性div实现一个简单的fold / unforld效果,即当元素的实际尺寸不是通过CSS设置时,因此不能轻易确定。所以我需要jQuery的width()和height()等价于任意元素;方法应返回可分配给* .style.width / height的内容,以实现折叠/展开效果。这些方法也可以是设置者,但不一定是因为它无关紧要(或者不是吗?)

兼容性:IE8 +和3个适当的帮派:Firefox,Chrome,Safari。所以。除了“使用jQuery”之外没有其他答案,我现在不想做。问题是我不需要支持像IE6 / 7和Netscape这样的古老浏览器。我希望我的代码只是简单的,适用于现代浏览器的首页JavaScript。删除IE8 for IE9也是一种选择。

我认为答案可能对许多Web开发人员有用。谢谢!

编辑:我当然理解,分析jQuery(以及放弃古老的怪癖)是一个不错的选择,但我认为有人已经这样做并且可以与我们分享。

4 个答案:

答案 0 :(得分:5)

以下是我在玩IE8,FF,Chrome和Safari后今天提出的问题的答案。

假设我们想要垂直折叠和展开div元素(因此我们只是简单地谈论高度),尽可能少的JavaScript和没有jQuery。可以是要在页面上显示和隐藏的内联错误消息框。消息框本身是弹性的,您不知道它的实际尺寸。这里有两个一般问题需要解决:

问题#1:offsetHeight,clientHeight和scrollHeight属性在浏览器中出了名的不一致。您不能依赖它们,特别是当边距/填充/边框设置为0以外的值并且CSS高度不是默认值时(即实际折叠/展开元素时)。有getComputedStyle(),但只能在理智的浏览器上使用,而不能在IE浏览器中使用。 OTOH,IE的currentStyle属性不会像您预期的那样返回计算值(例如,您可能会将“auto”视为高度值)。事实证明,没有边距/填充/边框偏移高度可靠且兼容所有现代浏览器。

问题#2:设置div元素动画的唯一方法(我知道)是更改style.height,但是不包括填充和边框,因此您无法为该框设置动画为0或从0开始动画,对于具有非零填充和边框的元素。 (最重要的是,IE不接受0px作为style.height,所以最小尺寸无论如何都是1px。)

这两个问题的解决方案是用另一个具有默认样式的div包装你的盒子,即padding / margin / border都设置为0,这是新div的默认样式。您要折叠和展开的框应该在里面,它不应该有边距设置,如果需要,只有填充和边框。通过这种方式,您将能够(1)通过offsetHeight可靠地确定弹性内盒的高度,以及(2)将外盒的高度设置为1像素的动画。

所以,让我们说我们想要动画这个:

<div id="errmsg" style="display:none">
    <div class="errmsg">
        <div class="window-close" onClick="javascript:showErrMsg('', this.parentNode.parentNode)"></div>
        <div id="errmsg.text"></div>
    </div>
</div>

该框在开头是不可见的。 “窗口关闭”类是右侧的一个小框,带有十字,用于在单击时隐藏框。用空字符串调用showErrMsg()会折叠消息框(见下文)。

我为此错误消息框设置动画的JavaScript代码如下(我也是动画不透明度,为简单起见,此处省略):

var ANIMATE_STEPS = 10;
var ANIMATE_DELAY = 20;


function _obj(obj, parent)
{
    if (typeof obj == 'string')
        obj = (parent ? parent : document).getElementById(obj);
    return obj;
}

function _setStyleHeight(obj, h)
{
    _obj(obj).style.height = Math.round(h) + 'px';
}

function _animateVertFold(obj, cur, by, lim)
{
    obj = _obj(obj);
    cur += by;
    if (by < 0 && cur <= 1)
    {
        obj.style.display = 'none';
        _setStyleHeight(obj, 1); // IE doesn't accept 0
    }
    else if (by > 0 && cur >= lim)
    {
        _setStyleHeight(obj, lim);
    }
    else
    {
        _setStyleHeight(obj, cur);
        setTimeout('_animateVertFold(\'' + obj.id + '\', ' +
            cur + ', ' + by + ', ' + lim + ')', ANIMATE_DELAY);
    }
}

function _expandElem(obj)
{
    obj = _obj(obj);
    if (obj.style.display == 'none')
    {
        obj.style.overflow = 'hidden';
        _setStyleHeight(obj, 1);
        obj.style.display = 'block';
        var innerDiv = obj.getElementsByTagName('div')[0]; // better way?
        var h = innerDiv.offsetHeight;
        if (h > 0)
            _animateVertFold(obj, obj.offsetHeight, h /  ANIMATE_STEPS, h);
    }
}

function _shrinkElem(obj)
{
    obj = _obj(obj);
    if (!obj.style.display || obj.style.display != 'none')
    {
        obj.style.display = 'block';
        obj.style.overflow = 'hidden';
        var h = obj.offsetHeight;
        _animateVertFold(obj, h, - h /  ANIMATE_STEPS, h);
    }
}


function showErrMsg(msg, id)
{
    id || (id = '_errmsg');
    obj = _obj(id);
    if (msg != '')
    {
        _obj(id + '.text').innerHTML = msg;
        _expandElem(obj);
    }
    else
        _shrinkElem(obj);
}

您可以调用showErrMsg(),代码将处理其余部分。您必须将窗口关闭类定义为模仿GUI关闭窗口按钮的东西。当然,“errmsg”类作为一个具有不同背景颜色,边框和可能的字体的框。

答案 1 :(得分:4)

我认为这里最实用的方法是分析jQuery源代码并从那里构建你的函数。

答案 2 :(得分:4)

element.offsetHeight,element.offsetWidth 跨浏览器工作几乎相同,返回整数

element.clientWidth,element.clientHeight返回整数,但是 有一些x浏览器差异(填充,边框宽度)

浏览器currentStyle或计算样式返回字符串, 它们可能是像素,ems,百分比 - 很难操纵x浏览器。

答案 3 :(得分:3)

您可以使用您支持的现代浏览器中提供的window.getComputedStyle 它返回应用于元素的所有真实样式属性的集合。

以下是说明:https://developer.mozilla.org/en/DOM:window.getComputedStyle