Bug 1010675 - Stop allowing button contents to overflow into the CSS padding and border (although still allow them to overflow into our internal focuspadding when the min-content width says the contents don't fit). r=dholbert
☠☠ backed out by 5be9842d5121 ☠ ☠
authorL. David Baron <dbaron@dbaron.org>
Fri, 20 Mar 2015 06:47:29 -0700
changeset 263588 c2724e2f9de9c64a3e811fcfcce75c07ac50eaff
parent 263587 67fa35a8f1a1c835a3a1b58c17e1b546c79aa9a3
child 263589 e246f0d09dbec63784667f55076df124a4904c25
push id4718
push userraliiev@mozilla.com
push dateMon, 11 May 2015 18:39:53 +0000
treeherdermozilla-beta@c20c4ef55f08 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert
bugs1010675, 491180
milestone39.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1010675 - Stop allowing button contents to overflow into the CSS padding and border (although still allow them to overflow into our internal focuspadding when the min-content width says the contents don't fit). r=dholbert Note that this replaces the code that allows eroding the space with new code that reduces the focusPadding value. (Also, we previously didn't count the focusPadding towards what could be eroded, which meant we wouldn't quite get to the edge of the padding and border, because we weren't counting the extra for the focusPadding.) The existing reftests that I'm changing from == to != are ones that were specifically testing issues related to erosion of padding. The change to 491180-{1,2}-ref.html is because we now *do* erode the focusPadding, which is 3px in the horizontal dimensions (see the button::-moz-focus-inner styles in forms.css), and that was the only nonzero style on the button in 491180-{1,2}.html.
layout/forms/nsHTMLButtonControlFrame.cpp
layout/reftests/bugs/491180-1-ref.html
layout/reftests/bugs/491180-2-ref.html
layout/reftests/bugs/reftest.list
layout/reftests/forms/button/reftest.list
layout/reftests/forms/button/width-auto-size-em-ltr-ref.html
layout/reftests/forms/button/width-auto-size-em-ltr.html
layout/reftests/forms/button/width-auto-size-em-rtl-ref.html
layout/reftests/forms/button/width-auto-size-em-rtl.html
layout/reftests/forms/button/width-auto-size-ltr-ref.html
layout/reftests/forms/button/width-auto-size-ltr.html
layout/reftests/forms/button/width-auto-size-rtl-ref.html
layout/reftests/forms/button/width-auto-size-rtl.html
layout/reftests/forms/button/width-erode-all-focuspadding-ltr-ref.html
layout/reftests/forms/button/width-erode-all-focuspadding-ltr.html
layout/reftests/forms/button/width-erode-all-focuspadding-rtl-ref.html
layout/reftests/forms/button/width-erode-all-focuspadding-rtl.html
layout/reftests/forms/button/width-erode-overflow-focuspadding-ltr-ref.html
layout/reftests/forms/button/width-erode-overflow-focuspadding-ltr.html
layout/reftests/forms/button/width-erode-overflow-focuspadding-rtl-ref.html
layout/reftests/forms/button/width-erode-overflow-focuspadding-rtl.html
layout/reftests/forms/button/width-erode-part-focuspadding-ltr-ref.html
layout/reftests/forms/button/width-erode-part-focuspadding-ltr.html
layout/reftests/forms/button/width-erode-part-focuspadding-rtl-ref.html
layout/reftests/forms/button/width-erode-part-focuspadding-rtl.html
layout/reftests/forms/button/width-exact-fit-ltr.html
layout/reftests/forms/button/width-exact-fit-rtl.html
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -263,46 +263,50 @@ nsHTMLButtonControlFrame::ReflowButtonCo
                                                nsIFrame* aFirstKid)
 {
   WritingMode wm = GetWritingMode();
   LogicalSize availSize = aButtonReflowState.ComputedSize(wm);
   availSize.BSize(wm) = NS_INTRINSICSIZE;
 
   // Buttons have some bonus renderer-determined border/padding,
   // which occupies part of the button's content-box area:
-  const LogicalMargin focusPadding =
+  LogicalMargin focusPadding =
     LogicalMargin(wm, mRenderer.GetAddedButtonBorderAndPadding());
 
+  // See whether out availSize's inline-size is big enough.  If it's
+  // smaller than our intrinsic min iSize, that means that the kid
+  // wouldn't really fit.  In that case, we overflow into our internal
+  // focuspadding (which other browsers don't have) so that there's a
+  // little more space for it.
+  // Note that GetMinISize includes the focusPadding.
+  nscoord IOverflow = GetMinISize(aButtonReflowState.rendContext) -
+                      aButtonReflowState.ComputedISize();
+  nscoord IFocusPadding = focusPadding.IStartEnd(wm);
+  nscoord focusPaddingReduction = std::min(IFocusPadding,
+                                           std::max(IOverflow, 0));
+  if (focusPaddingReduction > 0) {
+    nscoord startReduction = focusPadding.IStart(wm);
+    if (focusPaddingReduction != IFocusPadding) {
+      startReduction = NSToCoordRound(startReduction *
+                                      (float(focusPaddingReduction) /
+                                       float(IFocusPadding)));
+    }
+    focusPadding.IStart(wm) -= startReduction;
+    focusPadding.IEnd(wm) -= focusPaddingReduction - startReduction;
+  }
+
   // shorthand for a value we need to use in a bunch of places
   const LogicalMargin& clbp = aButtonReflowState.ComputedLogicalBorderPadding();
 
   // Indent the child inside us by the focus border. We must do this separate
   // from the regular border.
   availSize.ISize(wm) -= focusPadding.IStartEnd(wm);
 
-  // See whether out availSize's inline-size is big enough.  If it's smaller than
-  // our intrinsic min iSize, that means that the kid wouldn't really fit; for a
-  // better look in such cases we adjust the available iSize and our inline-start
-  // offset to allow the kid to spill start-wards into our padding.
   LogicalPoint childPos(wm);
   childPos.I(wm) = focusPadding.IStart(wm) + clbp.IStart(wm);
-  nscoord extraISize = GetMinISize(aButtonReflowState.rendContext) -
-    aButtonReflowState.ComputedISize();
-  if (extraISize > 0) {
-    nscoord extraIStart = extraISize / 2;
-    nscoord extraIEnd = extraISize - extraIStart;
-    NS_ASSERTION(extraIEnd >=0, "How'd that happen?");
-
-    // Do not allow the extras to be bigger than the relevant padding
-    const LogicalMargin& padding = aButtonReflowState.ComputedLogicalPadding();
-    extraIStart = std::min(extraIStart, padding.IStart(wm));
-    extraIEnd = std::min(extraIEnd, padding.IEnd(wm));
-    childPos.I(wm) -= extraIStart;
-    availSize.ISize(wm) = availSize.ISize(wm) + extraIStart + extraIEnd;
-  }
   availSize.ISize(wm) = std::max(availSize.ISize(wm), 0);
 
   // Give child a clone of the button's reflow state, with height/width reduced
   // by focusPadding, so that descendants with height:100% don't protrude.
   nsHTMLReflowState adjustedButtonReflowState =
     CloneReflowStateWithReducedContentBox(aButtonReflowState,
                                           focusPadding.GetPhysicalMargin(wm));
 
--- a/layout/reftests/bugs/491180-1-ref.html
+++ b/layout/reftests/bugs/491180-1-ref.html
@@ -1,5 +1,5 @@
 <!DOCTYPE html>
 <html>
-  <div style="padding: 0; margin: 0; border: none; background: transparent; -moz-appearance: none; width: 0; height: 0; font: inherit; padding: 1px 3px">
+  <div style="padding: 0; margin: 0; border: none; background: transparent; -moz-appearance: none; width: 0; height: 0; font: inherit; padding: 1px 0">
     Some text <div style="background: green; width: 100px; height: 100px"></div>
   </div>
--- a/layout/reftests/bugs/491180-2-ref.html
+++ b/layout/reftests/bugs/491180-2-ref.html
@@ -1,4 +1,4 @@
 <!DOCTYPE html>
 <html>
-  <div style="padding: 0; margin: 0; border: none; background: transparent; -moz-appearance: none; width: 14px; font: inherit; padding: 1px 3px; white-space: pre; overflow: hidden">Some text</div>
+  <div style="padding: 0; margin: 0; border: none; background: transparent; -moz-appearance: none; width: 20px; font: inherit; padding: 1px 0; white-space: pre; overflow: hidden">Some text</div>
   </div>
--- a/layout/reftests/bugs/reftest.list
+++ b/layout/reftests/bugs/reftest.list
@@ -147,18 +147,18 @@ random == 99850-1b.html 99850-1-ref.html
 == 169749-1.html 169749-1-ref.html
 == 172073-1.html 172073-1-ref.html
 == 175190-1.html 175190-1-ref.html
 == 179596-1a.html 179596-1a-ref.html
 == 179596-1b.html 179596-1b-ref.html
 == 179596-2.html 179596-2-ref.html
 == 179596-2.html 179596-2-ref2.html
 == 179596-2.html 179596-2-ref3.html
-== 180085-1.html 180085-1-ref.html
-== 180085-2.html 180085-2-ref.html
+!= 180085-1.html 180085-1-ref.html # fix for 180085 reverted in bug 1010675
+!= 180085-2.html 180085-2-ref.html # fix for 180085 reverted in bug 1010675
 == 185388-1.html 185388-1-ref.html
 == 186317-1.html 186317-1-ref.html
 == 192902-1.html 192902-ref.html
 skip-if(B2G||Mulet) == 192767-01.xul 192767-11.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == 192767-02.xul 192767-12.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == 192767-03.xul 192767-13.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == 192767-04.xul 192767-14.xul # Initial mulet triage: parity with B2G/B2G Desktop
 skip-if(B2G||Mulet) == 192767-05.xul 192767-15.xul # Initial mulet triage: parity with B2G/B2G Desktop
@@ -522,18 +522,18 @@ random-if(cocoaWidget) == 350506-1.html 
 == 355548-1.xml 355548-1-ref.xml
 == 355548-2.xml 355548-2-ref.xml
 == 355548-3.xml 355548-3-ref.xml
 == 355548-4.xml 355548-4-ref.xml
 == 355548-5.xml 355548-5-ref.xml
 == 356774-1.html 356774-1-ref.html
 == 356775-1.html 356775-1-ref.html
 == 359869-1.html 359869-1-ref.html
-skip-if(B2G||Mulet) == 359903-1.html 359903-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
-== 359903-2.html 359903-2-ref.html
+fails-if(OSX==1010) != 359903-1.html 359903-1-ref.html # erosion of padding removed in bug 1010675 # failure is bug 1145589
+!= 359903-2.html 359903-2-ref.html # erosion of padding removed in bug 1010675
 == 360065-1.html 360065-1-ref.html
 == 360746-1.html 360746-1-ref.html
 == 360757-1a.html 360757-1-ref.html
 == 360757-1b.html 360757-1-ref.html
 == 361091-1.html 361091-1-ref.html
 == 362594-1a.html 362594-1-quirks-ref.html
 == 362594-1b.html 362594-1-quirks-ref.html
 == 362594-1c.html 362594-1-standards-ref.html
--- a/layout/reftests/forms/button/reftest.list
+++ b/layout/reftests/forms/button/reftest.list
@@ -22,8 +22,21 @@ pref(browser.display.focus_ring_width,1)
 # different from ColorGray
 fails-if(Android||B2G||Mulet) == disabled-1.html disabled-1-ref.html # Initial mulet triage: parity with B2G/B2G Desktop
 == disabled-2.html disabled-2-ref.html
 
 != disabled-3.html disabled-3-notref.html
 != disabled-4.html disabled-4-notref.html
 != disabled-5.html disabled-5-notref.html
 != disabled-6.html disabled-6-notref.html
+
+== width-auto-size-em-ltr.html width-auto-size-em-ltr-ref.html
+== width-auto-size-ltr.html width-auto-size-ltr-ref.html
+== width-exact-fit-ltr.html width-auto-size-ltr-ref.html
+== width-erode-part-focuspadding-ltr.html width-erode-part-focuspadding-ltr-ref.html
+== width-erode-all-focuspadding-ltr.html width-erode-all-focuspadding-ltr-ref.html
+== width-erode-overflow-focuspadding-ltr.html width-erode-overflow-focuspadding-ltr-ref.html
+== width-auto-size-em-rtl.html width-auto-size-em-rtl-ref.html
+== width-auto-size-rtl.html width-auto-size-rtl-ref.html
+== width-exact-fit-rtl.html width-auto-size-rtl-ref.html
+== width-erode-part-focuspadding-rtl.html width-erode-part-focuspadding-rtl-ref.html
+== width-erode-all-focuspadding-rtl.html width-erode-all-focuspadding-rtl-ref.html
+== width-erode-overflow-focuspadding-rtl.html width-erode-overflow-focuspadding-rtl-ref.html
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-em-ltr-ref.html
@@ -0,0 +1,19 @@
+<!DOCTYPE HTML>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 2em; width: 5em; border: 2px solid blue;
+  margin: 1px 3px; /* for implicit focuspadding */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-em-ltr.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 1em;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 2em; width: 5em; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-em-rtl-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 2em; width: 5em; border: 2px solid blue;
+  margin: 1px 3px; /* for implicit focuspadding */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-em-rtl.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 1em;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 2em; width: 5em; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-ltr-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 3px; /* for implicit focuspadding */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-ltr.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 2em; width: 5em; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-rtl-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 3px; /* for implicit focuspadding */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-auto-size-rtl.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 2em; width: 5em; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-all-focuspadding-ltr-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 0px; /* for implicit focuspadding, fully eroded */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-all-focuspadding-ltr.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 62px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-all-focuspadding-rtl-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 0px; /* for implicit focuspadding, fully eroded */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-all-focuspadding-rtl.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 62px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-overflow-focuspadding-ltr-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px -2px 1px 0; /* for implicit focuspadding, fully eroded and overflowed */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-overflow-focuspadding-ltr.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 60px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-overflow-focuspadding-rtl-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 0 1px -2px; /* for implicit focuspadding, fully eroded and overflowed */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-overflow-focuspadding-rtl.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 60px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-part-focuspadding-ltr-ref.html
@@ -0,0 +1,20 @@
+<!DOCTYPE HTML>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 2px; /* for implicit focuspadding, partly eroded */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-part-focuspadding-ltr.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 66px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-part-focuspadding-rtl-ref.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+div.button {
+  display: inline-block;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+  margin: 1px 2px; /* for implicit focuspadding, partly eroded */
+}
+
+</style>
+
+<div class=button><span></span></div>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-erode-part-focuspadding-rtl.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 66px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-exact-fit-ltr.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 68px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/width-exact-fit-rtl.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML>
+<html dir=rtl>
+<style>
+
+button {
+  -moz-appearance: none;
+  background: yellow;
+  border: 2px solid fuchsia;
+  padding: 2px;
+  font-size: 10px;
+  width: 68px;
+  border-radius: 0; /* override mobile/android/themes/core/content.css */
+}
+
+span {
+  display: inline-block; vertical-align: middle;
+  height: 20px; width: 50px; border: 2px solid blue;
+}
+
+</style>
+
+<button><span></span></button>