5

未知のコンテナ div があり、本体の全寸法よりも小さいwidthとしましょう。height

このコンテナ 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

どの方法が最速かを確認するために、自分でパフォーマンステストを行う必要があるかもしれませんが、とにかくここでは非常に簡単な方法の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
}

私の知る限り、offsetLeft、offsetWidthなどは、box-sizing: border-box設定されているかどうかに関係なく、正しい寸法を返します。内部div内にdivがある場合、状況は少し複雑になります。元のdivのchildNodeである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 に答える