From 7a2bbf62576f30fd0eb73d7c1ff33fe4fd520e41 Mon Sep 17 00:00:00 2001 From: Ilyong Cho Date: Wed, 28 Aug 2013 15:34:14 +0900 Subject: [PATCH] Adjust top_offset when top margin of a element collapses with its first child --- src/components/main/layout/block.rs | 67 ++++++++++++++++++++--------- 1 file changed, 46 insertions(+), 21 deletions(-) diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 13b2a675b2f..212441c8798 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -315,12 +315,22 @@ impl BlockFlowData { let mut collapsible = Au(0); let mut collapsing = Au(0); - let mut first_collapsing = true; + let mut margin_top = Au(0); + let mut margin_bottom = Au(0); + let mut top_margin_collapsible = false; + let mut bottom_margin_collapsible = false; + let mut first_inflow = true; for &box in self.box.iter() { do box.with_model |model| { if !self.is_root && model.border.top == Au(0) && model.padding.top == Au(0) { collapsible = model.margin.top; + top_margin_collapsible = true; } + if !self.is_root && model.border.bottom == Au(0) && model.padding.bottom == Au(0) { + bottom_margin_collapsible = true; + } + margin_top = model.margin.top; + margin_bottom = model.margin.bottom; } } for kid in self.common.child_iter() { @@ -328,19 +338,26 @@ impl BlockFlowData { BlockFlow(ref info) => { for &box in info.box.iter() { do box.with_model |model| { - collapsing = if first_collapsing && collapsible != Au(0) { - // The top margin collapses with its first in-flow block-level child's - // top margin if the parent has no top boder, no top padding. - model.margin.top - } else { - // The bottom margin of an in-flow block-level element collapses - // with the top margin of its next in-flow block-level sibling. - geometry::min(model.margin.top, collapsible) - }; + // The top margin collapses with its first in-flow block-level child's + // top margin if the parent has no top boder, no top padding. + if first_inflow && top_margin_collapsible { + // If top-margin of parent is less than top-margin of its first child, + // the parent box goes down until its top is aligned with the child. + if margin_top < model.margin.top { + // TODO: The position of child floats should be updated and this + // would influence clearance as well. See #725 + let extra_margin = model.margin.top - margin_top; + top_offset = top_offset + extra_margin; + margin_top = model.margin.top; + } + } + // The bottom margin of an in-flow block-level element collapses + // with the top margin of its next in-flow block-level sibling. + collapsing = geometry::min(model.margin.top, collapsible); collapsible = model.margin.bottom; } } - first_collapsing = false; + first_inflow = false; } // Margins between a floated box and any other box do not collapse. _ => { @@ -354,17 +371,22 @@ impl BlockFlowData { cur_y = cur_y + child_node.position.size.height; }; } - // The bottom margin collapses with its first in-flow block-level child's bottom margin + + // The bottom margin collapses with its last in-flow block-level child's bottom margin // if the parent has no bottom boder, no bottom padding. - for &box in self.box.iter() { - collapsing = do box.with_model |model| { - if !self.is_root && model.border.bottom == Au(0) && model.padding.bottom == Au(0) { - collapsible - } else { - Au(0) - } - }; - } + collapsing = if bottom_margin_collapsible { + if margin_bottom < collapsible { + margin_bottom = collapsible; + } + collapsible + } else { + Au(0) + }; + + // TODO: A box's own margins collapse if the 'min-height' property is zero, and it has neither + // top or bottom borders nor top or bottom padding, and it has a 'height' of either 0 or 'auto', + // and it does not contain a line box, and all of its in-flow children's margins (if any) collapse. + let mut height = if self.is_root { Au::max(ctx.screen_size.size.height, cur_y) @@ -383,6 +405,9 @@ impl BlockFlowData { self.box.map(|&box| { do box.with_mut_base |base| { //The associated box is the border box of this flow + base.model.margin.top = margin_top; + base.model.margin.bottom = margin_bottom; + base.position.origin.y = clearance + base.model.margin.top; noncontent_height = base.model.padding.top + base.model.padding.bottom +