diff --git a/core/src/main/resources/org/apache/spark/ui/static/webui.css b/core/src/main/resources/org/apache/spark/ui/static/webui.css
index 595e80ab5e3ad106b0a442d20841e1be5fbd9e52..b157f3e0a407d4a5a5f1205fddf8d39149f9c318 100644
--- a/core/src/main/resources/org/apache/spark/ui/static/webui.css
+++ b/core/src/main/resources/org/apache/spark/ui/static/webui.css
@@ -155,7 +155,7 @@ pre {
   display: none;
 }
 
-span.expand-additional-metrics, span.expand-dag-viz {
+span.expand-additional-metrics, span.expand-dag-viz, span.collapse-table {
   cursor: pointer;
 }
 
@@ -163,7 +163,7 @@ span.additional-metric-title {
   cursor: pointer;
 }
 
-.additional-metrics.collapsed {
+.additional-metrics.collapsed, .collapsible-table.collapsed {
   display: none;
 }
 
diff --git a/core/src/main/resources/org/apache/spark/ui/static/webui.js b/core/src/main/resources/org/apache/spark/ui/static/webui.js
new file mode 100644
index 0000000000000000000000000000000000000000..e37307aa1f70597af6b0ac3908215cdb0791a383
--- /dev/null
+++ b/core/src/main/resources/org/apache/spark/ui/static/webui.js
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+function collapseTablePageLoad(name, table){
+  if (window.localStorage.getItem(name) == "true") {
+    // Set it to false so that the click function can revert it
+    window.localStorage.setItem(name, "false");
+    collapseTable(name, table);
+  }
+}
+
+function collapseTable(thisName, table){
+    var status = window.localStorage.getItem(thisName) == "true";
+    status = !status;
+
+    thisClass = '.' + thisName
+
+    // Expand the list of additional metrics.
+    var tableDiv = $(thisClass).parent().find('.' + table);
+    $(tableDiv).toggleClass('collapsed');
+
+    // Switch the class of the arrow from open to closed.
+    $(thisClass).find('.collapse-table-arrow').toggleClass('arrow-open');
+    $(thisClass).find('.collapse-table-arrow').toggleClass('arrow-closed');
+
+    window.localStorage.setItem(thisName, "" + status);
+}
+
+// Add a call to collapseTablePageLoad() on each collapsible table
+// to remember if it's collapsed on each page reload
+$(function() {
+  collapseTablePageLoad('collapse-aggregated-metrics','aggregated-metrics');
+});
\ No newline at end of file
diff --git a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
index 4e2fe5e0e5beb20945896bd33e7e22f16fae1a97..740f5e5f7fe39796a91e256e27ffd92430005fe2 100644
--- a/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
+++ b/core/src/main/scala/org/apache/spark/ui/UIUtils.scala
@@ -169,6 +169,7 @@ private[spark] object UIUtils extends Logging {
     <script src={prependBaseUri("/static/additional-metrics.js")}></script>
     <script src={prependBaseUri("/static/timeline-view.js")}></script>
     <script src={prependBaseUri("/static/log-view.js")}></script>
+    <script src={prependBaseUri("/static/webui.js")}></script>
   }
 
   def vizHeaderNodes: Seq[Node] = {
diff --git a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
index d986a55959b82386d980784f2de7539cdc4d2e2c..a5e2a2068949d73809068e7c8adadcd33dbd298e 100644
--- a/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
+++ b/core/src/main/scala/org/apache/spark/ui/jobs/StagePage.scala
@@ -564,6 +564,18 @@ private[ui] class StagePage(parent: StagesTab) extends WebUIPage("stage") {
       val maybeAccumulableTable: Seq[Node] =
         if (hasAccumulators) { <h4>Accumulators</h4> ++ accumulableTable } else Seq()
 
+      val aggMetrics =
+        <span class="collapse-aggregated-metrics collapse-table"
+              onClick="collapseTable('collapse-aggregated-metrics','aggregated-metrics')">
+          <h4>
+            <span class="collapse-table-arrow arrow-open"></span>
+            <a>Aggregated Metrics by Executor</a>
+          </h4>
+        </span>
+        <div class="aggregated-metrics collapsible-table">
+          {executorTable.toNodeSeq}
+        </div>
+
       val content =
         summary ++
         dagViz ++
@@ -572,9 +584,9 @@ private[ui] class StagePage(parent: StagesTab) extends WebUIPage("stage") {
           // Only show the tasks in the table
           stageData.taskData.values.toSeq.filter(t => taskIdsInPage.contains(t.taskInfo.taskId)),
           currentTime) ++
-        <h4>Summary Metrics for {numCompleted} Completed Tasks</h4> ++
+        <h4>Summary Metrics for <a href="#tasks-section">{numCompleted} Completed Tasks</a></h4> ++
         <div>{summaryTable.getOrElse("No tasks have reported metrics yet.")}</div> ++
-        <h4>Aggregated Metrics by Executor</h4> ++ executorTable.toNodeSeq ++
+        aggMetrics ++
         maybeAccumulableTable ++
         <h4 id="tasks-section">Tasks</h4> ++ taskTableHTML ++ jsForScrollingDownToTaskTable
       UIUtils.headerSparkPage(stageHeader, content, parent, showVisualization = true)