diff --git a/core/src/main/resources/spark/ui/static/webui.css b/core/src/main/resources/spark/ui/static/webui.css
index c1ad4dbb17e776dd65635446bd83869b34bb8d1b..f7537bb7661919e20f66298273471d1629feb0a3 100644
--- a/core/src/main/resources/spark/ui/static/webui.css
+++ b/core/src/main/resources/spark/ui/static/webui.css
@@ -39,3 +39,11 @@
   padding-top: 10px;
   padding-bottom: 10px;
 }
+
+.progress-cell {
+  width: 134px;
+  border-right: 0;
+  padding: 0;
+  padding-top: 7px;
+  padding-left: 4px;
+}
diff --git a/core/src/main/scala/spark/ui/jobs/IndexPage.scala b/core/src/main/scala/spark/ui/jobs/IndexPage.scala
index 27c017d7eeceb40504cc0212507f7c3c37378bba..cd04542faab07cd0240bda81a3bd4b345c9f5161 100644
--- a/core/src/main/scala/spark/ui/jobs/IndexPage.scala
+++ b/core/src/main/scala/spark/ui/jobs/IndexPage.scala
@@ -24,9 +24,27 @@ private[spark] class IndexPage(parent: JobProgressUI) {
     val completedStages = listener.completedStages.reverse.toSeq
     val failedStages = listener.failedStages.reverse.toSeq
 
-    val activeStageTable: NodeSeq = listingTable(stageHeaders, stageRow, activeStages)
-    val completedStageTable = listingTable(stageHeaders, stageRow, completedStages)
-    val failedStageTable: NodeSeq = listingTable(stageHeaders, stageRow, failedStages)
+    /** Special table which merges two header cells. */
+    def stageTable[T](makeRow: T => Seq[Node], rows: Seq[T]): Seq[Node] = {
+      <table class="table table-bordered table-striped table-condensed sortable">
+        <thead>
+          <th>Stage Id</th>
+          <th>Origin</th>
+          <th>Submitted</th>
+          <td>Duration</td>
+          <td colspan="2">Tasks: Complete/Total</td>
+          <td>Shuffle Activity</td>
+          <td>Stored RDD</td>
+        </thead>
+        <tbody>
+          {rows.map(r => makeRow(r))}
+        </tbody>
+      </table>
+    }
+
+    val activeStageTable: NodeSeq = stageTable(stageRow, activeStages)
+    val completedStageTable = stageTable(stageRow, completedStages)
+    val failedStageTable: NodeSeq = stageTable(stageRow, failedStages)
 
     val content = <h2>Active Stages</h2> ++ activeStageTable ++
                   <h2>Completed Stages</h2>  ++ completedStageTable ++
@@ -77,8 +95,8 @@ private[spark] class IndexPage(parent: JobProgressUI) {
       <td>{submissionTime}</td>
       <td>{getElapsedTime(s.submissionTime,
              s.completionTime.getOrElse(System.currentTimeMillis()))}</td>
-      <td>{makeProgressBar(completedTasks, totalTasks)}</td>
-      <td>{completedTasks} / {totalTasks}
+      <td class="progress-cell">{makeProgressBar(completedTasks, totalTasks)}</td>
+      <td style="border-left: 0; text-align: center;">{completedTasks} / {totalTasks}
         {listener.stageToTasksFailed.getOrElse(s.id, 0) match {
         case f if f > 0 => "(%s failed)".format(f)
         case _ =>