 			private static func computeContainerFrame(frameNodes:[FrameNodeImpl]) -> CGRect {
 				var rect = CGRect(x: CGFloat.max, y: CGFloat.max, width: 0.0, height: 0.0)
 				for frameNode in frameNodes {
-					if frameNode.frame.origin.x < rect.origin.x {
-						rect.origin.x = frameNode.frame.origin.x
-					}
-					// sum the origin and the width to get total width
-					let frameWidth = frameNode.frame.origin.x + frameNode.frame.size.width
-					// if that exceeds the rect
-					if frameWidth > rect.origin.x + rect.size.width {
-						// subtract the rect origin from the total width so overall width of the container now matches the overall width of the frame
-						rect.size.width = frameWidth - rect.origin.x
-					}
-					
-					if frameNode.frame.origin.y < rect.origin.y {
-						rect.origin.y = frameNode.frame.origin.y
-					}
-
-					let frameHeight = frameNode.frame.origin.y + frameNode.frame.size.height
-					if frameHeight > rect.origin.y + rect.size.height {
-						rect.size.height = frameHeight - rect.origin.y
-					}
+					rect = expandRect(rect, toContainChild: frameNode.frame)
+				}
+				return rect
+			}
+			
+			private static func expandRect(parentRect: CGRect, toContainChild childRect: CGRect) -> CGRect {
+				var rect = parentRect
+				
+				if childRect.origin.x < rect.origin.x {
+					rect.origin.x = childRect.origin.x
+				}
+				// sum the origin and the width to get total width
+				let frameWidth = childRect.origin.x + childRect.size.width
+				// if that exceeds the rect
+				if frameWidth > rect.origin.x + rect.size.width {
+					// subtract the rect origin from the total width so overall width of the container now matches the overall width of the frame
+					rect.size.width = frameWidth - rect.origin.x
+				}
+				
+				if childRect.origin.y < rect.origin.y {
+					rect.origin.y = childRect.origin.y
+				}
+				
+				let frameHeight = childRect.origin.y + childRect.size.height
+				if frameHeight > rect.origin.y + rect.size.height {
+					rect.size.height = frameHeight - rect.origin.y
 				}
 				return rect
 			}

			// compute each section height
			for (sectionIndex, section) in sections.enumerate() {
				//TODO: support horizontal scroll direction
				//TODO: support interitem spacing
				let sectionInset = insetForSection(sectionIndex)
				let interitemSpacing = interitemSpacingForSection(sectionIndex)
				let lineSpacing = lineSpacingForSection(sectionIndex)
				// scale factor converts 1x1 grid into pixel frames.  Subtract 1 from width to ensure fit
				let summedIteritemSpacing = CGFloat(section.constrainedSideGridLength - 1) * interitemSpacing
				let unitPixelScaleFactor = (contentSize.width - sectionInset.left - sectionInset.right - summedIteritemSpacing) / CGFloat(section.constrainedSideGridLength)
				
				// get the header and footer sizes to use in frame calculations
				let headerSize = frameForSupplementaryViewOfKind(UICollectionElementKindSectionHeader, inSection:sectionIndex)?.size ?? CGSizeZero
				let footerSize = frameForSupplementaryViewOfKind(UICollectionElementKindSectionFooter, inSection:sectionIndex)?.size ?? CGSizeZero
				
				
				// section origin starts horizontally at the content and section insets and vertically at the vertical extent of contentSize + the height of the header + the section and content insets
				let sectionOrigin = CGPoint(x: sectionInset.left + contentInset.left, y:contentSize.height + sectionInset.top + contentInset.top + headerSize.height)
				
				// the frames coresponding to the cells, calculated from their grid frames
				var cellFrames: [MosaicLayoutFrameTree.SectionFrameNode.CellFrameNode] = []

				
				let frame: CGRect
				let cells: [CellFrameNode]
				let headerFrame: CGRect?
				let footerFrame: CGRect?
				init(cells: [CellFrameNode], headerFrame: CGRect? = nil, footerFrame: CGRect? = nil) {
					//TODO: change headerFrame and footerFrame to size only to remove amiibuity of how its used
					self.cells = cells
					
					// compute frame of all cells
					var rect = MosaicLayoutFrameTree.computeContainerFrame(cells.map({$0 as MosaicFrameNode}))
					
					if let header = headerFrame {
						// expand rect to include header
						rect = MosaicLayoutFrameTree.expandRect(rect, toContainChild: header)
						self.headerFrame = header
					} else {
						self.headerFrame = nil
					}
					
					if let footer = footerFrame {
						// expand rect to include footer
						rect = MosaicLayoutFrameTree.expandRect(rect, toContainChild: footer)
						self.footerFrame = footer
					} else {
						self.footerFrame = nil
					}
					
					self.frame = rect
				}
			}
