找到最远的DIV的最便宜的方式?

pil*_*lau 5 html javascript css position dimensions

比方说,我们有未知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. 请仅使用vanilla Javascript.没有像jQuery等框架.

谢谢!

一些可视化: 输入1(和2)div 输入3个div

Stu*_*art 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
}
Run Code Online (Sandbox Code Playgroud)

据我所知,offsetLeft、offsetWidth 等无论是否box-sizing: border-box设置都会返回正确的尺寸。如果内部 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
}
Run Code Online (Sandbox Code Playgroud)