Adjust top_offset when top margin of a element collapses with its first child

This commit is contained in:
Ilyong Cho 2013-08-28 15:34:14 +09:00
parent 3bddaee785
commit 7a2bbf6257

View file

@ -315,12 +315,22 @@ impl BlockFlowData {
let mut collapsible = Au(0); let mut collapsible = Au(0);
let mut collapsing = 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() { for &box in self.box.iter() {
do box.with_model |model| { do box.with_model |model| {
if !self.is_root && model.border.top == Au(0) && model.padding.top == Au(0) { if !self.is_root && model.border.top == Au(0) && model.padding.top == Au(0) {
collapsible = model.margin.top; 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() { for kid in self.common.child_iter() {
@ -328,19 +338,26 @@ impl BlockFlowData {
BlockFlow(ref info) => { BlockFlow(ref info) => {
for &box in info.box.iter() { for &box in info.box.iter() {
do box.with_model |model| { 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
// 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.
// top margin if the parent has no top boder, no top padding. if first_inflow && top_margin_collapsible {
model.margin.top // If top-margin of parent is less than top-margin of its first child,
} else { // the parent box goes down until its top is aligned with the child.
// The bottom margin of an in-flow block-level element collapses if margin_top < model.margin.top {
// with the top margin of its next in-flow block-level sibling. // TODO: The position of child floats should be updated and this
geometry::min(model.margin.top, collapsible) // 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; collapsible = model.margin.bottom;
} }
} }
first_collapsing = false; first_inflow = false;
} }
// Margins between a floated box and any other box do not collapse. // 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; 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. // if the parent has no bottom boder, no bottom padding.
for &box in self.box.iter() { collapsing = if bottom_margin_collapsible {
collapsing = do box.with_model |model| { if margin_bottom < collapsible {
if !self.is_root && model.border.bottom == Au(0) && model.padding.bottom == Au(0) { margin_bottom = collapsible;
collapsible }
} else { collapsible
Au(0) } 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 { let mut height = if self.is_root {
Au::max(ctx.screen_size.size.height, cur_y) Au::max(ctx.screen_size.size.height, cur_y)
@ -383,6 +405,9 @@ impl BlockFlowData {
self.box.map(|&box| { self.box.map(|&box| {
do box.with_mut_base |base| { do box.with_mut_base |base| {
//The associated box is the border box of this flow //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; base.position.origin.y = clearance + base.model.margin.top;
noncontent_height = base.model.padding.top + base.model.padding.bottom + noncontent_height = base.model.padding.top + base.model.padding.bottom +