diff --git a/components/layout/block.rs b/components/layout/block.rs
index 2b7f17729df7..1c7925feb0ec 100644
--- a/components/layout/block.rs
+++ b/components/layout/block.rs
@@ -1666,33 +1666,40 @@ impl BlockFlow {
// Now compute the real value.
self.propagate_and_compute_used_inline_size(shared_context);
- // Now for some speculation.
- match self.formatting_context_type() {
- FormattingContextType::Block => {
- // We can't actually compute the inline-size of this block now, because floats
- // might affect it. Speculate that its inline-size is equal to the inline-size
- // computed above minus the inline-size of the previous left and/or right floats.
- //
- // (If `max-width` is set, then don't perform this speculation. We guess that the
- // page set `max-width` in order to avoid hitting floats. The search box on Google
- // SERPs falls into this category.)
- if self.fragment.style.max_inline_size() == LengthOrPercentageOrNone::None {
- let speculated_left_float_size =
- max(Au(0),
- self.base.speculated_float_placement_in.left -
- self.fragment.margin.inline_start);
- let speculated_right_float_size =
- max(Au(0),
- self.base.speculated_float_placement_in.right -
- self.fragment.margin.inline_end);
- self.fragment.border_box.size.inline =
- self.fragment.border_box.size.inline -
- speculated_left_float_size -
- speculated_right_float_size;
- }
- }
- FormattingContextType::None | FormattingContextType::Other => {}
+ self.guess_inline_size_for_block_formatting_context_if_necessary()
+ }
+
+ fn guess_inline_size_for_block_formatting_context_if_necessary(&mut self) {
+ // We don't need to guess anything unless this is a block formatting context.
+ if self.formatting_context_type() != FormattingContextType::Block {
+ return
+ }
+
+ // If `max-width` is set, then don't perform this speculation. We guess that the
+ // page set `max-width` in order to avoid hitting floats. The search box on Google
+ // SERPs falls into this category.
+ if self.fragment.style.max_inline_size() != LengthOrPercentageOrNone::None {
+ return
}
+
+ // At this point, we know we can't precisely compute the inline-size of this block now,
+ // because floats might affect it. Speculate that its inline-size is equal to the
+ // inline-size computed above minus the inline-size of the previous left and/or right
+ // floats.
+ let speculated_left_float_size = if self.fragment.margin.inline_start >= Au(0) &&
+ self.base.speculated_float_placement_in.left > self.fragment.margin.inline_start {
+ self.base.speculated_float_placement_in.left - self.fragment.margin.inline_start
+ } else {
+ Au(0)
+ };
+ let speculated_right_float_size = if self.fragment.margin.inline_end >= Au(0) &&
+ self.base.speculated_float_placement_in.right > self.fragment.margin.inline_end {
+ self.base.speculated_float_placement_in.right - self.fragment.margin.inline_end
+ } else {
+ Au(0)
+ };
+ self.fragment.border_box.size.inline = self.fragment.border_box.size.inline -
+ speculated_left_float_size - speculated_right_float_size
}
fn definitely_has_zero_block_size(&self) -> bool {
diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json
index ec188e4011fc..dc9d239eac0d 100644
--- a/tests/wpt/mozilla/meta/MANIFEST.json
+++ b/tests/wpt/mozilla/meta/MANIFEST.json
@@ -652,6 +652,18 @@
"url": "/_mozilla/css/block_formatting_context_max_width_a.html"
}
],
+ "css/block_formatting_context_negative_margins_a.html": [
+ {
+ "path": "css/block_formatting_context_negative_margins_a.html",
+ "references": [
+ [
+ "/_mozilla/css/block_formatting_context_negative_margins_ref.html",
+ "=="
+ ]
+ ],
+ "url": "/_mozilla/css/block_formatting_context_negative_margins_a.html"
+ }
+ ],
"css/block_formatting_context_overflow_a.html": [
{
"path": "css/block_formatting_context_overflow_a.html",
@@ -10058,6 +10070,18 @@
"url": "/_mozilla/css/block_formatting_context_max_width_a.html"
}
],
+ "css/block_formatting_context_negative_margins_a.html": [
+ {
+ "path": "css/block_formatting_context_negative_margins_a.html",
+ "references": [
+ [
+ "/_mozilla/css/block_formatting_context_negative_margins_ref.html",
+ "=="
+ ]
+ ],
+ "url": "/_mozilla/css/block_formatting_context_negative_margins_a.html"
+ }
+ ],
"css/block_formatting_context_overflow_a.html": [
{
"path": "css/block_formatting_context_overflow_a.html",
diff --git a/tests/wpt/mozilla/tests/css/block_formatting_context_negative_margins_a.html b/tests/wpt/mozilla/tests/css/block_formatting_context_negative_margins_a.html
new file mode 100644
index 000000000000..41bc3ccabb58
--- /dev/null
+++ b/tests/wpt/mozilla/tests/css/block_formatting_context_negative_margins_a.html
@@ -0,0 +1,69 @@
+
+
+
+
+
+ Servo test case: wrong block width with negative margins and overflow
+
+
+
+
+
+
+
Servo test case: wrong block width with negative margins and overflow
+
+
+
With width: auto
+
The following blocks have negative margins on the sides. They
+ should end up being as large as the red container, with their left and
+right borders should overlap the container’s border.
+
In Servo Nightly 0.0.1-e3d946b (2016-09-16), when the value of overflow is not visible, the rendered width is wrong (as if a box-sizing: border-box; width: 100%; had been applied).
+
+
+
+
+
+
+
+
+
With box-sizing: border-box; width: 100%
+
If we do use box-sizing: border-box; width: 100%;, for the overflow: visible block we get the expected rendering, but for the other values the width is wrong once again.
Servo test case: wrong block width with negative margins and overflow
+
+
+
With width: auto
+
The following blocks have negative margins on the sides. They
+ should end up being as large as the red container, with their left and
+right borders should overlap the container’s border.
+
In Servo Nightly 0.0.1-e3d946b (2016-09-16), when the value of overflow is not visible, the rendered width is wrong (as if a box-sizing: border-box; width: 100%; had been applied).
+
+
+
+
+
+
+
+
+
With box-sizing: border-box; width: 100%
+
If we do use box-sizing: border-box; width: 100%;, for the overflow: visible block we get the expected rendering, but for the other values the width is wrong once again.