5

假设我们有一个未知的容器 div,widthheight小于身体的完整尺寸。

此容器 div 包含未知数量的 div。容器中的所有 div 都有不同的大小,除此之外,它们具有与以下 3 种类型之一相同的 CSS:

  • 类型 1:所有 div 都向左浮动。
  • 类型 2:所有 div 都向右浮动。
  • 类型 3:所有 div 的绝对位置未知,甚至可以放置在远离屏幕的位置。

类型 1 和 2 的 div 有边距,也可能有填充。类型 3 的 div 可能有,也可能没有,也可能两者都有。

鉴于容器中 div 的类型未知 - 最终目标是在原始容器内添加一个辅助容器,该容器大到足以容纳视口中的所有 div(带有溢出:滚动)。计算它最便宜的方法是什么?

需要记住的一些事项:

  1. div可能有也可能没有(作为一个整体)有box-sizing: border-box. 这将影响它们的边框、边距和填充的呈现方式,并且也应予以考虑。

  2. 在类型 1 和 2(浮动 div)的情况下,div 意味着水平堆叠 - 即容器应该增长以适应它们的总宽度。应该考虑到这一点。

  3. 例如,最右边 div 的右边距应该被计算在内,并且应该增加容器的宽度。这同样适用于顶部、底部和最左侧的 div。

  4. 不需要 IE8 及以下版本。

  5. 请仅使用原版 Javascript。没有像 jQuery 之类的框架。

谢谢!

一些可视化: 类型 1(和 2)div 类型 3 div

4

1 回答 1

1

您可能必须自己进行性能测试以查看哪种方法最快,但无论如何这里是一种非常快速的方法。(jsfiddle

function getOuterBoxDimensions() {
    var original = document.getElementById('original'),
        divs = original.getElementsByTagName('div'),
        left = 0,
        right = original.offsetWidth,
        top = 0,
        bottom = original.offsetHeight;
    for (var i = 0, div; div = divs[i++];) {
        if (div.offsetTop < top) {
            top = div.offsetTop;
        }
        if (div.offsetTop + div.offsetHeight > bottom) {
            bottom = div.offsetTop + div.offsetHeight;
        }
        if (div.offsetLeft < left) {
            left = div.offsetLeft;
        }
        if (div.offsetLeft + div.offsetWidth > right) {
            right = div.offsetLeft + div.offsetWidth;
        }
    }
    return {
        top: top,
        left: left,
        bottom: bottom,
        right: right
    };
    // Note that dimensions are relative to the original div top left
}

据我所知,无论是否box-sizing: border-box设置,offsetLeft、offsetWidth 等都会返回正确的尺寸。如果您在内部 div 中有 div,那么事情会变得有点复杂 - 您只想检查作为原始子节点的 div。

编辑:这是一个扩展版本,它适当地考虑了边距并扩展了新容器以容纳单行中的所有浮动 div(请参阅评论中的讨论)。http://jsfiddle.net/m7N2J/10/

function getOuterBoxDimensions() {
    var original = document.getElementById('original'),
        divs = original.getElementsByTagName('div'),
        left = 0,
        right = original.offsetWidth,
        top = 0,
        bottom = original.offsetHeight,
        d = document.defaultView,
        style, marginTop, marginBottom, marginLeft, marginRight, float, floatWidth = 0;
    for (var i = 0, div; div = divs[i++];) {
        if (style = div.currentStyle) {
            // May be possible to exclude this if IE7/8 not needed
            marginTop = parseFloat(style.marginTop);
            marginBottom = parseFloat(style.marginBottom);
            marginLeft = parseFloat(style.marginLeft);
            marginRight = parseFloat(style.marginRight);
            float = style.float;
        }
        else {
            style = d.getComputedStyle(div, null);
            marginTop = parseFloat(style.getPropertyValue('margin-top'));
            marginBottom = parseFloat(style.getPropertyValue('margin-bottom'));
            marginLeft = parseFloat(style.getPropertyValue('margin-left'));
            marginRight = parseFloat(style.getPropertyValue('margin-right'));
            float = style.getPropertyValue('float');
        }
        if (float == 'left' || float == 'right') {
            floatWidth += div.offsetWidth + marginLeft + marginRight;
            if (div.offsetHeight + marginBottom > bottom) {
                bottom = div.offsetHeight + marginBottom;
            }
        }
        else {
            if (div.offsetTop - marginTop < top) {
                top = div.offsetTop - marginTop;
            }
            if (div.offsetTop + div.offsetHeight + marginBottom > bottom) {
                bottom = div.offsetTop + div.offsetHeight + marginBottom;
            }
            if (div.offsetLeft < left - marginLeft) {
                left = div.offsetLeft - marginLeft;
            }
            if (div.offsetLeft + div.offsetWidth + marginRight > right) {
                right = div.offsetLeft + div.offsetWidth + marginRight;
            }
        }
    }
    if (right < left + floatWidth) {
        right = left + floatWidth;
    }
    return {
        top: top,
        left: left,
        bottom: bottom,
        right: right
    };
    // Note that dimensions are relative to the original div
}
于 2012-12-24T10:20:38.500 回答