diff --git a/browser/base/content/browser.css b/browser/base/content/browser.css
index c251625b955..f45ef977ff3 100644
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -122,7 +122,6 @@ tabbrowser {
visibility: hidden;
}
-.tab-close-button,
.tab-background {
/* Explicitly set the visibility to override the value (collapsed)
* we inherit from #TabsToolbar[collapsed] upon opening a browser window. */
@@ -131,15 +130,26 @@ tabbrowser {
transition: visibility 0ms 25ms;
}
-.tab-close-button:not([fadein]):not([pinned]),
.tab-background:not([fadein]):not([pinned]) {
visibility: hidden;
/* Closing tabs are hidden without a delay. */
transition-delay: 0ms;
}
+.tab-close-button[fadein],
+.tab-label[fadein] {
+ transition: opacity 70ms;
+}
+
+.tab-close-button[fullyopen]:not([fadeinlabel]),
+.tab-label[fullyopen]:not([fadeinlabel]) {
+ visibility: hidden;
+ opacity: .6;
+}
+
.tab-throbber:not([fadein]):not([pinned]),
-.tab-label:not([fadein]):not([pinned]),
+.tab-label:not([fullyopen]):not([pinned]),
+.tab-close-button:not([fullyopen]):not([pinned]),
.tab-icon-image:not([fadein]):not([pinned]) {
display: none;
}
diff --git a/browser/base/content/tabbrowser.xml b/browser/base/content/tabbrowser.xml
index 7e8d24241b5..2bc3174ec9e 100644
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1862,6 +1862,7 @@
this._blurTab(aTab);
aTab.style.maxWidth = ""; // ensure that fade-out transition happens
aTab.removeAttribute("fadein");
+ aTab._fullyOpen = false;
if (this.tabs.length - this._removingTabs.length == 1) {
// The second tab just got closed and we will end up with a single
@@ -3043,6 +3044,7 @@
this.mCurrentTab.linkedPanel = uniqueId;
this.mCurrentTab._tPos = 0;
this.mCurrentTab._fullyOpen = true;
+ this.mCurrentTab.setAttribute("fadeinlabel", "true");
this.mCurrentTab.linkedBrowser = this.mCurrentBrowser;
// set up the shared autoscroll popup
@@ -4063,6 +4065,8 @@
if (tab.parentNode != this)
return;
tab._fullyOpen = true;
+ tab.scrollTop; // force a layout flush as part of the fadeinlabel transition
+ tab.setAttribute("fadeinlabel", "true");
this.adjustTabstrip();
@@ -4702,11 +4706,11 @@
role="presentation"/>
@@ -4760,6 +4764,18 @@
0
+
+
+ return this.getAttribute("fullyopen") == "true";
+
+
+ if (val) {
+ this.setAttribute("fullyopen", "true");
+ } else {
+ this.removeAttribute("fullyopen");
+ }
+
+
false
null
false
diff --git a/browser/base/content/test/general/browser_tabopen_reflows.js b/browser/base/content/test/general/browser_tabopen_reflows.js
index aeaf168019e..2985409b3f6 100644
--- a/browser/base/content/test/general/browser_tabopen_reflows.js
+++ b/browser/base/content/test/general/browser_tabopen_reflows.js
@@ -8,6 +8,10 @@ XPCOMUtils.defineLazyGetter(this, "docShell", () => {
});
const EXPECTED_REFLOWS = [
+ // tabbrowser._handleNewTab() flushes layout to start the label+close button fade-in
+ "_handleNewTab@chrome://browser/content/tabbrowser.xml|" +
+ "onxbltransitionend@chrome://browser/content/tabbrowser.xml|",
+
// tabbrowser.adjustTabstrip() call after tabopen animation has finished
"adjustTabstrip@chrome://browser/content/tabbrowser.xml|" +
"_handleNewTab@chrome://browser/content/tabbrowser.xml|" +