The most expensive way to find the farthest DIV?

Let's say we have a container div of unknown width and height , which is smaller than the full dimensions of the body.

This div container contains an unknown number of divs. All divs in the container have different sizes , and besides them they have the same CSS as one of these three types:

  • Type 1: all div files move to the left.
  • Type 2: all divs floated to the right.
  • Type 3: all divs have unknown absolute positions and can even be placed far from the screen.

Type 1 and 2 divs have margins and can be indented. Type 3 divs can have either one or the other.

Given that the type of div in the container is unknown, the ultimate goal is to add a secondary container inside the original, large enough to fit all the divs in the viewport (with overflow: scrolling). What is the least expensive way to calculate this?

Some things to keep in mind:

  • divs may or may not (generally) have box-sizing: border-box . This will affect how their borders, margins and indents are displayed and should also be taken into account.

  • In the case of types 1 and 2 (floating divs), divs are designed for horizontal stacking - that is, the container should grow in accordance with their total width. This should be considered.

  • For example, the right margin on the rightmost div should be considered and should increase the width of the container. The same applies to the top, bottom, and left divs.

  • IE8 and below is not required.

  • Please use only vanilla Javascript . There are no frameworks like jQuery etc.

Thanks!

Some visualizations: Type 1 (and 2) divsType 3 divs

+4
source share
1 answer

You may need to conduct a performance test yourself to find out which method is the fastest, but in any case it is a pretty quick way. ( 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 } 

As far as I know, offsetLeft, offsetWidth, etc. will return the correct sizes whether box-sizing: border-box or not. If you have a div inside the inner divs, then everything will be a little more complicated - you will need to check only those divs that are the childNodes of the original.

EDIT: Here is an extended version that takes fields into account properly and expands a new container to accommodate all floating divs on one line (see discussion in the comments). 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 } 
+1
source

All Articles