最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

width() and height() for modern browsers without jQuery - Stack Overflow

programmeradmin7浏览0评论

I am trying to implement a simple fold/unforld effect for elastic div's, i.e. when actual dimensions of an element are not set through CSS and thus are not trivially determinable. So I need equivalents of jQuery's width() and height() for arbitrary elements; the methods should return something that would be assignable to *.style.width/height to achieve the fold/unfold effect. The methods can be setters as well, though not necessarily as it's trivial anyway (or is it not?)

Compatibility: IE8+ and the adequate gang of 3: Firefox, Chrome, Safari. S.O. doesn't have an answer for this other than "use jQuery" which I don't want to do at the moment. The thing is I don't need to support such archaic browsers as IE6/7 and Netscape. I want my code to be just simple, maiden JavaScript for modern browsers. Dropping IE8 for IE9 is an option, too.

I think the answer may be useful to many web developers. Thanks!

Edit: I understand of course, analyzing jQuery (and dropping archaic quirks) is a good option, but I thought someone has done this already and could share with us.

I am trying to implement a simple fold/unforld effect for elastic div's, i.e. when actual dimensions of an element are not set through CSS and thus are not trivially determinable. So I need equivalents of jQuery's width() and height() for arbitrary elements; the methods should return something that would be assignable to *.style.width/height to achieve the fold/unfold effect. The methods can be setters as well, though not necessarily as it's trivial anyway (or is it not?)

Compatibility: IE8+ and the adequate gang of 3: Firefox, Chrome, Safari. S.O. doesn't have an answer for this other than "use jQuery" which I don't want to do at the moment. The thing is I don't need to support such archaic browsers as IE6/7 and Netscape. I want my code to be just simple, maiden JavaScript for modern browsers. Dropping IE8 for IE9 is an option, too.

I think the answer may be useful to many web developers. Thanks!

Edit: I understand of course, analyzing jQuery (and dropping archaic quirks) is a good option, but I thought someone has done this already and could share with us.

Share Improve this question edited Oct 17, 2010 at 20:21 mojuba asked Oct 17, 2010 at 20:07 mojubamojuba 12.2k9 gold badges54 silver badges76 bronze badges 3
  • One could always look at the jQuery (or another toolkit/library of your choice) source to determine the approach, and then rule out (or rule in) the different quirks needed in different environments. – user166390 Commented Oct 17, 2010 at 20:11
  • pst, that's always an option of course, but I thought someone with reasonable knowledge of just these 4 browsers, or someone who's done that before would give an answer straight away. And understanding jQuery may or may not be as easy. – mojuba Commented Oct 17, 2010 at 20:17
  • I think solving the hight()/width() problem is not going to be as time consuming as making the animation look good, which jquery does for you. – tster Commented Oct 17, 2010 at 20:18
Add a ment  | 

4 Answers 4

Reset to default 5

Here is an answer to my own question I came up with today after playing with IE8, FF, Chrome and Safari.

Let's say we want to fold and unfold a div element vertically (so we'll be talking only about the height for simplicity) with minimal possible JavaScript and no jQuery. Could be an inline error message box that you want to show and hide nicely on the page. The message box itself is elastic and you don't know its actual dimensions. There are two general problems to be solved here:

Problem #1: offsetHeight, clientHeight and scrollHeight properties are notoriously inconsistent across browsers. You can't rely on them especially when margin/padding/border are set to something other than 0 and when the CSS height is something other than default (i.e. when actually folding/unfolding the element). There is getComputedStyle(), but it's available only on sane browsers and not in IE. OTOH, IE's currentStyle property doesn't return puted values as you might expect (e.g. you may see "auto" as the height value). It turns out, with no margin/padding/border offsetHeight is reliable and patible on all modern browsers.

Problem #2: the only way (that I know of) to animate your div element is to change style.height, which, however, doesn't include padding and border, and thus you can't animate the box down to 0 or start your animation from 0 for elements with non-zero padding and border. (On top of that, IE doesn't accept 0px as style.height, so the minimal size would be 1px anyway).

The solution to both problems is to wrap your box around with another div with default style, i.e. padding/margin/border all set to 0, which is the default style for a new div. The box you want to fold and unfold should be inside and it shouldn't have a margin setting, only padding and border if desired. This way, you will be able to (1) reliably determine the height of your elastic inner box via offsetHeight, and (2) animate the height of the outer box to and from 1 pixel.

So, let's say we want to animate this:

<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>

The box is invisible in the beginning. The "window-close" class is a small box on the right with a cross which is used to hide the box when clicked. Calling showErrMsg() with empty string folds the message box (see below).

My JavaScript code to animate this error message box is as follows (I'm also animating opacity which is omitted here for simplicity):

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);
}

You can call showErrMsg() and the code will take care of the rest. You will have to define the window-close class as something that mimics a GUI close-window button. And of course the "errmsg" class as a box with distinct background color, border and possibly font face as well.

I think the most practical approach here would be to analyze the jQuery source and build your functions from there.

element.offsetHeight,element.offsetWidth work pretty much the same across browsers, return integers

element.clientWidth,element.clientHeight return integers, but have some x-browser differences (padding,border width)

The browsers currentStyle or puted style return strings, and they may be in pixels, ems, percents- hard to manipulate x-browser.

You can use window.getComputedStyle available in the modern browsers you support.
It returns a collection of all real style properties applied to an element.

Here is a description: https://developer.mozilla/en/DOM:window.getComputedStyle

发布评论

评论列表(0)

  1. 暂无评论