about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Hoffman-Andrews <github@hoffman-andrews.com>2022-01-06 19:48:24 -0500
committerJacob Hoffman-Andrews <github@hoffman-andrews.com>2022-01-18 10:43:14 -0800
commit6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c (patch)
treeb6dd1a95f8f47373a9b919dbc64dc368324631b1
parent7bc7be860f99f4a40d45b0f74e2d01b02e072357 (diff)
downloadrust-6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c.tar.gz
rust-6a5f8b1aef1417d7dc85b5d0a229d2db1930eb7c.zip
Simplify and unify rustdoc sidebar styles
This switches to just use size, weight, and spacing to distinguish
headings in the sidebar. We no longer use boxes, horizontal bars, or
centering to distinguish headings. This makes it much easier to
understand the hierarchy of headings, and reduces visual noise.

I also refactored how the mobile topbar works. Previously, we tried to
shift around elements from the sidebar to make the topbar. Now, the
topbar gets its own elements, which can be styled on their own. This
makes styling and reasoning about those elements simpler.

Because the heading font sizes are bigger, increase the sidebar width
slightly.

As a very minor change, removed version from the "All types" page. It's
now only on the crate page.
-rw-r--r--src/librustdoc/html/render/context.rs12
-rw-r--r--src/librustdoc/html/render/mod.rs31
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css304
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css27
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css27
-rw-r--r--src/librustdoc/html/static/css/themes/light.css27
-rw-r--r--src/librustdoc/html/static/js/main.js60
-rw-r--r--src/librustdoc/html/static/js/source-script.js2
-rw-r--r--src/librustdoc/templates/page.html14
-rw-r--r--src/test/rustdoc-gui/anchors.goml2
-rw-r--r--src/test/rustdoc-gui/code-blocks-overflow.goml2
-rw-r--r--src/test/rustdoc-gui/docblock-table-overflow.goml4
-rw-r--r--src/test/rustdoc-gui/headings.goml2
-rw-r--r--src/test/rustdoc-gui/item-info-width.goml2
-rw-r--r--src/test/rustdoc-gui/search-result-display.goml2
-rw-r--r--src/test/rustdoc-gui/sidebar-mobile.goml23
-rw-r--r--src/test/rustdoc-gui/sidebar-source-code.goml4
-rw-r--r--src/test/rustdoc-gui/sidebar.goml16
-rw-r--r--src/test/rustdoc-gui/type-declation-overflow.goml11
-rw-r--r--src/test/rustdoc/cap-lints.rs2
-rw-r--r--src/test/rustdoc/crate-version-escape.rs3
-rw-r--r--src/test/rustdoc/crate-version.rs2
-rw-r--r--src/test/rustdoc/titles.rs7
-rw-r--r--src/test/rustdoc/typedef.rs2
24 files changed, 228 insertions, 360 deletions
diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs
index 865e14f694d..2455d56bd2b 100644
--- a/src/librustdoc/html/render/context.rs
+++ b/src/librustdoc/html/render/context.rs
@@ -554,16 +554,8 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
             extra_scripts: &[],
             static_extra_scripts: &[],
         };
-        let sidebar = if let Some(ref version) = self.shared.cache.crate_version {
-            format!(
-                "<h2 class=\"location\">Crate {}</h2>\
-                     <div class=\"block version\">\
-                         <p>Version {}</p>\
-                     </div>\
-                     <a id=\"all-types\" href=\"index.html\"><p>Back to index</p></a>",
-                crate_name,
-                Escape(version),
-            )
+        let sidebar = if self.shared.cache.crate_version.is_some() {
+            format!("<h2 class=\"location\">Crate {}</h2>", crate_name)
         } else {
             String::new()
         };
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index a79b3e8ed08..29a793f3110 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -1744,13 +1744,6 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
             buffer,
             "<h2 class=\"location\"><a href=\"#\">{}{}</a></h2>",
             match *it.kind {
-                clean::StructItem(..) => "Struct ",
-                clean::TraitItem(..) => "Trait ",
-                clean::PrimitiveItem(..) => "Primitive Type ",
-                clean::UnionItem(..) => "Union ",
-                clean::EnumItem(..) => "Enum ",
-                clean::TypedefItem(..) => "Type Definition ",
-                clean::ForeignTypeItem => "Foreign Type ",
                 clean::ModuleItem(..) =>
                     if it.is_crate() {
                         "Crate "
@@ -1763,26 +1756,14 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
         );
     }
 
+    buffer.write_str("<div class=\"sidebar-elems\">");
     if it.is_crate() {
+        write!(buffer, "<div class=\"block\"><ul>");
         if let Some(ref version) = cx.cache().crate_version {
-            write!(
-                buffer,
-                "<div class=\"block version\">\
-                     <div class=\"narrow-helper\"></div>\
-                     <p>Version {}</p>\
-                 </div>",
-                Escape(version),
-            );
+            write!(buffer, "<li class=\"version\">Version {}</li>", Escape(version));
         }
-    }
-
-    buffer.write_str("<div class=\"sidebar-elems\">");
-    if it.is_crate() {
-        write!(
-            buffer,
-            "<a id=\"all-types\" href=\"all.html\"><p>See all {}'s items</p></a>",
-            it.name.as_ref().expect("crates always have a name"),
-        );
+        write!(buffer, "<li><a id=\"all-types\" href=\"all.html\">All Items</a></li>");
+        buffer.write_str("</div></ul>");
     }
 
     match *it.kind {
@@ -1806,7 +1787,7 @@ fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer) {
     // to navigate the documentation (though slightly inefficiently).
 
     if !it.is_mod() {
-        buffer.write_str("<h2 class=\"location\">Other items in<br>");
+        buffer.write_str("<h2 class=\"location\">In ");
         for (i, name) in cx.current.iter().take(parentlen).enumerate() {
             if i > 0 {
                 buffer.write_str("::<wbr>");
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index bfdce74de67..dbc068ce6b1 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -169,8 +169,7 @@ h1.fqn {
 	section hierarchies. */
 h2,
 .top-doc h3,
-.top-doc h4,
-.sidebar .others h3 {
+.top-doc h4 {
 	border-bottom: 1px solid;
 }
 h3.code-header {
@@ -206,7 +205,11 @@ div.impl-items > div {
 }
 
 h1, h2, h3, h4, h5, h6,
-.sidebar, a.source, .search-input, .search-results .result-name,
+.sidebar,
+.mobile-topbar,
+a.source,
+.search-input,
+.search-results .result-name,
 .content table td:first-child > a,
 .item-left > a,
 .out-of-band,
@@ -261,6 +264,11 @@ textarea {
 	margin: 0;
 }
 
+button {
+	/* Buttons on Safari have different default padding than other platforms. Make them the same. */
+	padding: 1px 6px;
+}
+
 /* end tweaks for normalize.css 8 */
 
 .rustdoc {
@@ -359,15 +367,25 @@ nav.sub {
 }
 
 .sidebar {
-	width: 200px;
+	font-size: 0.9rem;
+	width: 250px;
+	min-width: 200px;
 	overflow-y: scroll;
 	position: sticky;
-	min-width: 200px;
 	height: 100vh;
 	top: 0;
 	left: 0;
 }
 
+.sidebar-elems,
+.sidebar > .location {
+	padding-left: 24px;
+}
+
+.sidebar .location {
+	overflow-wrap: anywhere;
+}
+
 .rustdoc.source .sidebar {
 	width: 50px;
 	min-width: 0px;
@@ -396,6 +414,10 @@ nav.sub {
 	visibility: visible;
 }
 
+#all-types {
+	margin-top: 1em;
+}
+
 /* Improve the scrollbar display on firefox */
 * {
 	scrollbar-width: initial;
@@ -415,48 +437,28 @@ nav.sub {
 	-webkit-box-shadow: inset 0;
 }
 
-.sidebar .block > ul > li {
-	margin-right: -10px;
-}
-
 /* Everything else */
 
 .hidden {
 	display: none !important;
 }
 
-.logo-container {
+.sidebar .logo-container {
 	display: flex;
 	margin-top: 10px;
 	margin-bottom: 10px;
 	justify-content: center;
 }
 
+.version {
+	overflow-wrap: break-word;
+}
+
 .logo-container > img {
 	height: 100px;
 	width: 100px;
 }
 
-.sidebar .location {
-	border: 1px solid;
-	font-size: 1.0625rem;
-	margin: 30px 10px 20px 10px;
-	text-align: center;
-	word-wrap: break-word;
-	font-weight: inherit;
-	padding: 0;
-}
-
-.sidebar .version {
-	font-size: 0.9375rem;
-	text-align: center;
-	border-bottom: 1px solid;
-	overflow-wrap: break-word;
-	overflow-wrap: anywhere;
-	word-wrap: break-word; /* deprecated */
-	word-break: break-word; /* Chrome, non-standard */
-}
-
 .location:empty {
 	border: none;
 }
@@ -470,48 +472,45 @@ nav.sub {
 
 .block {
 	padding: 0;
-	margin-bottom: 14px;
-}
-.block h2, .block h3 {
-	text-align: center;
 }
 .block ul, .block li {
-	margin: 0 10px;
 	padding: 0;
 	list-style: none;
 }
 
 .block a {
 	display: block;
+	padding: 0.3em;
+	margin-left: -0.3em;
+
 	text-overflow: ellipsis;
 	overflow: hidden;
-	line-height: 15px;
-	padding: 7px 5px;
-	font-size: 0.875rem;
-	font-weight: 300;
-	transition: border 500ms ease-out;
 }
 
-.sidebar-title {
-	border-top: 1px solid;
-	border-bottom: 1px solid;
-	text-align: center;
-	font-size: 1.0625rem;
-	margin-bottom: 5px;
-	font-weight: inherit;
+.sidebar h2 {
+	border-bottom: none;
+	font-weight: 500;
 	padding: 0;
+	margin: 0;
+	margin-top: 1rem;
+	margin-bottom: 1rem;
 }
 
-.sidebar-links {
-	margin-bottom: 15px;
+.sidebar h3 {
+	font-size: 1.1rem;
+	font-weight: 500;
+	padding: 0;
+	margin: 0;
+	margin-top: 0.5rem;
+	margin-bottom: 0.25rem;
 }
 
-.sidebar-links > a {
-	padding-left: 10px;
-	width: 100%;
+.sidebar-links,
+.block {
+	margin-bottom: 2em;
 }
 
-.sidebar-menu {
+.mobile-topbar {
 	display: none;
 }
 
@@ -784,13 +783,12 @@ nav.sub {
 	margin-top: 0;
 }
 
-nav:not(.sidebar) {
+nav.sub {
 	flex-grow: 1;
-	border-bottom: 1px solid;
 	padding-bottom: 10px;
 	margin-bottom: 25px;
 }
-.source nav:not(.sidebar).sub {
+.source nav.sub {
 	margin-left: 32px;
 }
 nav.main {
@@ -1395,18 +1393,6 @@ pre.rust {
 	margin-left: 5px;
 }
 
-#all-types {
-	text-align: center;
-	border: 1px solid;
-	margin: 0 10px;
-	margin-bottom: 10px;
-	display: block;
-	border-radius: 7px;
-}
-#all-types > p {
-	margin: 5px 0;
-}
-
 #sidebar-toggle {
 	position: sticky;
 	top: 0;
@@ -1752,8 +1738,12 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 }
 
 @media (max-width: 700px) {
-	body {
+	.rustdoc {
 		padding-top: 0px;
+		/* Sidebar should overlay main content, rather than pushing main content to the right.
+		   Turn off `display: flex` on the body element. */
+		display: block;
+		scroll-margin-top: 45px;
 	}
 
 	main {
@@ -1761,134 +1751,110 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		padding-top: 0px;
 	}
 
-	/* Space is at a premium on mobile, so remove the theme-picker icon. */
-	#theme-picker {
-		display: none;
-		width: 0;
-	}
-
 	.rustdoc {
 		flex-direction: column;
 	}
 
-	.rustdoc:not(.source) > .sidebar {
-		width: 100%;
-		height: 45px;
-		min-height: 40px;
-		max-height: 45px;
-		margin: 0;
-		padding: 0 15px;
-		position: static;
-		z-index: 11;
-		overflow-y: hidden;
+	/* Hide the logo and item name from the sidebar. Those are displayed
+	   in the mobile-topbar instead. */
+	.sidebar .sidebar-logo,
+	.sidebar .location {
+		display: none;
 	}
 
-	.rustdoc.source > .sidebar {
+	.sidebar-elems {
+		margin-top: 1em;
+	}
+
+	.sidebar {
 		position: fixed;
-		top: 0;
-		left: 0;
+		top: 45px;
+		/* Hide the sidebar offscreen while not in use. Doing this instead of display: none means
+		   the sidebar stays visible for screen readers, which is useful for navigation. */
+		left: -1000px;
+		margin-left: 0;
+		background-color: rgba(0,0,0,0);
 		margin: 0;
+		padding: 0;
+		padding-left: 15px;
 		z-index: 11;
-		width: 0;
 	}
 
-	.sidebar.mobile {
-		position: sticky !important;
+	/* The source view uses a different design for the sidebar toggle, and doesn't have a topbar,
+	   so don't bump down the main content or the sidebar. */
+	.source main,
+	.source .sidebar {
 		top: 0;
+		padding: 0;
+	}
+
+	.sidebar.shown,
+	.sidebar.expanded,
+	.sidebar:focus-within {
 		left: 0;
-		width: 100%;
-		margin-left: 0;
-		background-color: rgba(0,0,0,0);
 	}
 
-	.sidebar > .location {
-		float: right;
-		margin: 0px;
-		margin-top: 2px;
-		padding: 3px 10px 1px 10px;
-		min-height: 39px;
-		background: inherit;
-		text-align: left;
-		font-size: 1.5rem;
+	.rustdoc.source > .sidebar {
+		position: fixed;
+		margin: 0;
+		z-index: 11;
+		width: 0;
 	}
 
-	.sidebar .location:empty {
-		padding: 0;
+	.mobile-topbar .location {
+		border: none;
+		margin: 0;
+		margin-left: auto;
+		padding: 0.3em;
+		padding-right: 0.6em;
+		text-overflow: ellipsis;
+		overflow-x: hidden;
 	}
 
-	.rustdoc:not(.source) .sidebar .logo-container {
-		width: 35px;
-		height: 35px;
-		margin-top: 5px;
-		margin-bottom: 5px;
-		float: left;
-		margin-left: 50px;
+	.mobile-topbar .logo-container {
+		max-height: 45px;
 	}
 
-	.sidebar .logo-container > img {
+	.mobile-topbar .logo-container > img {
 		max-width: 35px;
 		max-height: 35px;
+		margin-left: 20px;
+		margin-top: 5px;
+		margin-bottom: 5px;
 	}
 
-	.sidebar-menu {
-		position: fixed;
+	.mobile-topbar {
+		display: flex;
+		flex-direction: row;
+		position: sticky;
 		z-index: 10;
 		font-size: 2rem;
 		cursor: pointer;
-		width: 45px;
+		height: 45px;
+		width: 100%;
 		left: 0;
 		top: 0;
-		text-align: center;
-		display: block;
-		border-bottom: 1px solid;
-		border-right: 1px solid;
-		height: 45px;
 	}
 
-	.rustdoc.source > .sidebar > .sidebar-menu {
+	.source .mobile-topbar {
 		display: none;
 	}
 
-	/* We do NOT hide this element so that alternative device readers still have this information
-	   available. */
-	.sidebar-elems {
-		position: fixed;
-		z-index: 1;
-		top: 45px;
-		bottom: 0;
-		width: 246px;
-		/* We move the sidebar to the left by its own width so it doesn't appear. */
-		left: -246px;
-		overflow-y: auto;
-		border-right: 1px solid;
-	}
-
-	.sidebar > .block.version {
-		overflow: hidden;
-		border-bottom: none;
-		margin-bottom: 0;
-		height: 100%;
-		padding-left: 12px;
-	}
-	.sidebar > .block.version > div.narrow-helper {
-		float: left;
-		width: 1px;
-		height: 100%;
-	}
-	.sidebar > .block.version > p {
-		/* hide Version text if too narrow */
-		margin: 0;
-		min-width: 55px;
-		/* vertically center */
-		display: flex;
-		align-items: center;
-		height: 100%;
+	.sidebar-menu-toggle {
+		width: 45px;
+		border: none;
 	}
 
 	.source nav:not(.sidebar).sub {
 		margin-left: 32px;
 	}
 
+	/* Space is at a premium on mobile, so remove the theme-picker icon. */
+	#theme-picker {
+		display: none;
+		width: 0;
+	}
+
 	.content {
 		margin-left: 0px;
 	}
@@ -1925,28 +1891,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		height: 50px;
 	}
 
-	.show-it, .sidebar-elems:focus-within {
-		z-index:  2;
-		left: 0;
-	}
-
-	.show-it > .block.items {
-		margin: 8px 0;
-	}
-
-	.show-it > .block.items > ul {
-		margin: 0;
-	}
-
-	.show-it > .block.items > ul > li {
-		text-align: center;
-		margin: 2px 0;
-	}
-
-	.show-it > .block.items > ul > li > a {
-		font-size: 1.3125rem;
-	}
-
 	/* Because of ios, we need to actually have a full height sidebar title so the
 	 * actual sidebar can show up. But then we need to make it transparent so we don't
 	 * hide content. The filler just allows to create the background for the sidebar
@@ -1967,10 +1911,6 @@ details.rustdoc-toggle[open] > summary.hideme::after {
 		left: -11px;
 	}
 
-	#all-types {
-		margin: 10px;
-	}
-
 	.sidebar.expanded #sidebar-toggle {
 		font-size: 1.5rem;
 	}
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 885fe7c09a9..82a2be67ceb 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -57,7 +57,7 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #191f26;
 }
 
-.sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: #14191f;
 }
 
@@ -100,12 +100,6 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #14191f;
 }
 
-.sidebar .location {
-	border-color: #000;
-	background-color: #0f1419;
-	color: #fff;
-}
-
 .sidebar-elems .location {
 	color: #ff7733;
 }
@@ -114,15 +108,6 @@ pre, .rustdoc.source .example-wrap {
 	color: #fff;
 }
 
-.sidebar .version {
-	border-bottom-color: #424c57;
-}
-
-.sidebar-title {
-	border-top-color: #5c6773;
-	border-bottom-color: #5c6773;
-}
-
 .block a:hover {
 	background: transparent;
 	color: #ffb44c;
@@ -228,7 +213,8 @@ a.anchor,
 .small-section-header a,
 #source-sidebar a,
 pre.rust a,
-.sidebar a,
+.sidebar h2 a,
+.sidebar h3 a,
 .in-band a {
 	color: #c5c5c5;
 }
@@ -581,13 +567,6 @@ kbd {
 	}
 }
 
-#all-types {
-	background-color: #14191f;
-}
-#all-types:hover {
-	background-color: rgba(70, 70, 70, 0.33);
-}
-
 .search-results .result-name span.alias {
 	color: #c5c5c5;
 }
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 71af7797832..761bf50dd36 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -28,7 +28,7 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #2A2A2A;
 }
 
-.sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: #505050;
 }
 
@@ -69,21 +69,6 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #565656;
 }
 
-.sidebar .location {
-	border-color: #fff;
-	background: #575757;
-	color: #DDD;
-}
-
-.sidebar .version {
-	border-bottom-color: #DDD;
-}
-
-.sidebar-title {
-	border-top-color: #777;
-	border-bottom-color: #777;
-}
-
 .block a:hover {
 	background: #444;
 }
@@ -186,7 +171,8 @@ a.anchor,
 .small-section-header a,
 #source-sidebar a,
 pre.rust a,
-.sidebar a,
+.sidebar h2 a,
+.sidebar h3 a,
 .in-band a {
 	color: #ddd;
 }
@@ -453,13 +439,6 @@ kbd {
 	}
 }
 
-#all-types {
-	background-color: #505050;
-}
-#all-types:hover {
-	background-color: #606060;
-}
-
 .search-results .result-name span.alias {
 	color: #fff;
 }
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index e462fd16237..7cca7d4004b 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -30,7 +30,7 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #F5F5F5;
 }
 
-.sidebar {
+.sidebar, .mobile-topbar, .sidebar-menu-toggle {
 	background-color: #F5F5F5;
 }
 
@@ -69,21 +69,6 @@ pre, .rustdoc.source .example-wrap {
 	background-color: #f1f1f1;
 }
 
-.sidebar .location {
-	border-color: #000;
-	background-color: #fff;
-	color: #333;
-}
-
-.sidebar .version {
-	border-bottom-color: #DDD;
-}
-
-.sidebar-title {
-	border-top-color: #777;
-	border-bottom-color: #777;
-}
-
 .block a:hover {
 	background: #F5F5F5;
 }
@@ -183,7 +168,8 @@ a.anchor,
 .small-section-header a,
 #source-sidebar a,
 pre.rust a,
-.sidebar a,
+.sidebar h2 a,
+.sidebar h3 a,
 .in-band a {
 	color: #000;
 }
@@ -440,13 +426,6 @@ kbd {
 	}
 }
 
-#all-types {
-	background-color: #fff;
-}
-#all-types:hover {
-	background-color: #f9f9f9;
-}
-
 .search-results .result-name span.alias {
 	color: #000;
 }
diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js
index e7d1eedd358..161b95d9993 100644
--- a/src/librustdoc/html/static/js/main.js
+++ b/src/librustdoc/html/static/js/main.js
@@ -67,6 +67,13 @@ function resourcePath(basename, extension) {
             ty: sidebarVars.attributes["data-ty"].value,
             relpath: sidebarVars.attributes["data-relpath"].value,
         };
+        // FIXME: It would be nicer to generate this text content directly in HTML,
+        // but with the current code it's hard to get the right information in the right place.
+        var mobileLocationTitle = document.querySelector(".mobile-topbar h2.location");
+        var locationTitle = document.querySelector(".sidebar h2.location");
+        if (mobileLocationTitle && locationTitle) {
+            mobileLocationTitle.innerText = locationTitle.innerText;
+        }
     }
 }());
 
@@ -309,37 +316,6 @@ function hideThemeButtonState() {
         return null;
     }
 
-    function showSidebar() {
-        var elems = document.getElementsByClassName("sidebar-elems")[0];
-        if (elems) {
-            addClass(elems, "show-it");
-        }
-        var sidebar = document.getElementsByClassName("sidebar")[0];
-        if (sidebar) {
-            addClass(sidebar, "mobile");
-            var filler = document.getElementById("sidebar-filler");
-            if (!filler) {
-                var div = document.createElement("div");
-                div.id = "sidebar-filler";
-                sidebar.appendChild(div);
-            }
-        }
-    }
-
-    function hideSidebar() {
-        var elems = document.getElementsByClassName("sidebar-elems")[0];
-        if (elems) {
-            removeClass(elems, "show-it");
-        }
-        var sidebar = document.getElementsByClassName("sidebar")[0];
-        removeClass(sidebar, "mobile");
-        var filler = document.getElementById("sidebar-filler");
-        if (filler) {
-            filler.remove();
-        }
-        document.getElementsByTagName("body")[0].style.marginTop = "";
-    }
-
     var toggleAllDocsId = "toggle-all-docs";
     var main = document.getElementById(MAIN_ID);
     var savedHash = "";
@@ -374,7 +350,8 @@ function hideThemeButtonState() {
 
     function onHashChange(ev) {
         // If we're in mobile mode, we should hide the sidebar in any case.
-        hideSidebar();
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        removeClass(sidebar, "shown");
         handleHashes(ev);
     }
 
@@ -866,6 +843,11 @@ function hideThemeButtonState() {
         });
     }());
 
+    function hideSidebar() {
+        var sidebar = document.getElementsByClassName("sidebar")[0];
+        removeClass(sidebar, "shown");
+    }
+
     function handleClick(id, f) {
         var elem = document.getElementById(id);
         if (elem) {
@@ -906,16 +888,16 @@ function hideThemeButtonState() {
         };
     });
 
-    var sidebar_menu = document.getElementsByClassName("sidebar-menu")[0];
-    if (sidebar_menu) {
-        sidebar_menu.onclick = function() {
+    var sidebar_menu_toggle = document.getElementsByClassName("sidebar-menu-toggle")[0];
+    if (sidebar_menu_toggle) {
+        sidebar_menu_toggle.addEventListener("click", function() {
             var sidebar = document.getElementsByClassName("sidebar")[0];
-            if (hasClass(sidebar, "mobile")) {
-                hideSidebar();
+            if (!hasClass(sidebar, "shown")) {
+                addClass(sidebar, "shown");
             } else {
-                showSidebar();
+                removeClass(sidebar, "shown");
             }
-        };
+        });
     }
 
     var buildHelperPopup = function() {
diff --git a/src/librustdoc/html/static/js/source-script.js b/src/librustdoc/html/static/js/source-script.js
index 81dc0b2fb1e..498f60e9f25 100644
--- a/src/librustdoc/html/static/js/source-script.js
+++ b/src/librustdoc/html/static/js/source-script.js
@@ -139,7 +139,7 @@ function createSourceSidebar() {
                                       currentFile, hasFoundFile);
     });
 
-    container.insertBefore(sidebar, document.querySelector(".sidebar-logo").nextSibling);
+    container.appendChild(sidebar);
     // Focus on the current file in the source files sidebar.
     var selected_elem = sidebar.getElementsByClassName("selected")[0];
     if (typeof selected_elem !== "undefined") {
diff --git a/src/librustdoc/templates/page.html b/src/librustdoc/templates/page.html
index 1ef001ec2b7..1322b854b7f 100644
--- a/src/librustdoc/templates/page.html
+++ b/src/librustdoc/templates/page.html
@@ -72,8 +72,20 @@
     </div> {#- -#}
     <![endif]--> {#- -#}
     {{- layout.external_html.before_content|safe -}}
+    <nav class="mobile-topbar"> {#- -#}
+        <button class="sidebar-menu-toggle">&#9776;</button> {#- -#}
+        <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
+            <div class="logo-container"> {#- -#}
+            {%- if !layout.logo.is_empty() -%}
+                <img src="{{layout.logo}}" alt="logo"> {#- -#}
+            {%- else -%}
+                <img class="rust-logo" src="{{static_root_path|safe}}rust-logo{{page.resource_suffix}}.svg" alt="logo"> {#- -#}
+            {%- endif -%}
+            </div>
+        </a> {#- -#}
+        <h2 class="location"></h2>
+    </nav>
     <nav class="sidebar"> {#- -#}
-        <div class="sidebar-menu" role="button">&#9776;</div> {#- -#}
         <a class="sidebar-logo" href="{{page.root_path|safe}}{{krate_with_trailing_slash|safe}}index.html"> {#- -#}
             <div class="logo-container"> {#- -#}
                 {%- if !layout.logo.is_empty()  %}
diff --git a/src/test/rustdoc-gui/anchors.goml b/src/test/rustdoc-gui/anchors.goml
index e6758287d8c..2d48d21dc1b 100644
--- a/src/test/rustdoc-gui/anchors.goml
+++ b/src/test/rustdoc-gui/anchors.goml
@@ -20,7 +20,7 @@ assert-css: (".srclink", {"text-decoration": "underline solid rgb(56, 115, 173)"
 
 assert-css: ("#top-doc-prose-title", {"color": "rgb(0, 0, 0)"})
 
-assert-css: (".sidebar a", {"color": "rgb(0, 0, 0)"})
+assert-css: (".sidebar a", {"color": "rgb(56, 115, 173)"})
 assert-css: (".in-band a", {"color": "rgb(0, 0, 0)"})
 
 // We move the cursor over the "Implementations" title so the anchor is displayed.
diff --git a/src/test/rustdoc-gui/code-blocks-overflow.goml b/src/test/rustdoc-gui/code-blocks-overflow.goml
index ee4dad444e9..f93f3f0aefc 100644
--- a/src/test/rustdoc-gui/code-blocks-overflow.goml
+++ b/src/test/rustdoc-gui/code-blocks-overflow.goml
@@ -5,4 +5,4 @@ size: (1080, 600)
 assert-count: (".docblock > .example-wrap", 2)
 assert: ".docblock > .example-wrap > .language-txt"
 assert: ".docblock > .example-wrap > .rust-example-rendered"
-assert-css: (".docblock > .example-wrap > pre", {"width": "796px", "overflow-x": "auto"}, ALL)
+assert-css: (".docblock > .example-wrap > pre", {"width": "785.25px", "overflow-x": "auto"}, ALL)
diff --git a/src/test/rustdoc-gui/docblock-table-overflow.goml b/src/test/rustdoc-gui/docblock-table-overflow.goml
index 1b3006155d8..a9af88189a6 100644
--- a/src/test/rustdoc-gui/docblock-table-overflow.goml
+++ b/src/test/rustdoc-gui/docblock-table-overflow.goml
@@ -4,7 +4,7 @@ goto: file://|DOC_PATH|/lib2/long_table/struct.Foo.html
 size: (1100, 800)
 // Logically, the ".docblock" and the "<p>" should have the same scroll width.
 compare-elements-property: (".top-doc .docblock", ".top-doc .docblock > p", ["scrollWidth"])
-assert-property: (".top-doc .docblock", {"scrollWidth": "816"})
+assert-property: (".top-doc .docblock", {"scrollWidth": "801"})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: (".top-doc .docblock table", {"scrollWidth": "1573"})
 
@@ -16,6 +16,6 @@ compare-elements-property: (
     "#implementations + details .docblock > p",
     ["scrollWidth"],
 )
-assert-property: ("#implementations + details .docblock", {"scrollWidth": "816"})
+assert-property: ("#implementations + details .docblock", {"scrollWidth": "801"})
 // However, since there is overflow in the <table>, its scroll width is bigger.
 assert-property: ("#implementations + details .docblock table", {"scrollWidth": "1573"})
diff --git a/src/test/rustdoc-gui/headings.goml b/src/test/rustdoc-gui/headings.goml
index 34fadd84ae8..34ff2de3a9b 100644
--- a/src/test/rustdoc-gui/headings.goml
+++ b/src/test/rustdoc-gui/headings.goml
@@ -110,7 +110,7 @@ assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"font-size": "15.2px"
 assert-css: ("h6#sub-sub-heading-for-enum-impl-item-doc", {"border-bottom-width": "0px"})
 
 assert-text: (".sidebar .others h3", "Modules")
-assert-css: (".sidebar .others h3", {"border-bottom-width": "1px"}, ALL)
+assert-css: (".sidebar .others h3", {"border-bottom-width": "0px"}, ALL)
 
 goto: file://|DOC_PATH|/test_docs/union.HeavilyDocumentedUnion.html
 
diff --git a/src/test/rustdoc-gui/item-info-width.goml b/src/test/rustdoc-gui/item-info-width.goml
index cdc00d34114..acb30141ce5 100644
--- a/src/test/rustdoc-gui/item-info-width.goml
+++ b/src/test/rustdoc-gui/item-info-width.goml
@@ -3,5 +3,5 @@ goto: file://|DOC_PATH|/lib2/struct.Foo.html
 // We set a fixed size so there is no chance of "random" resize.
 size: (1100, 800)
 // We check that ".item-info" is bigger than its content.
-assert-css: (".item-info", {"width": "807px"})
+assert-css: (".item-info", {"width": "757px"})
 assert-css: (".item-info .stab", {"width": "341px"})
diff --git a/src/test/rustdoc-gui/search-result-display.goml b/src/test/rustdoc-gui/search-result-display.goml
index ea94e5640fb..3162a067d21 100644
--- a/src/test/rustdoc-gui/search-result-display.goml
+++ b/src/test/rustdoc-gui/search-result-display.goml
@@ -5,7 +5,7 @@ write: (".search-input", "test")
 wait-for: "#titles"
 // The width is returned by "getComputedStyle" which returns the exact number instead of the
 // CSS rule which is "50%"...
-assert-css: (".search-results div.desc", {"width": "320px"})
+assert-css: (".search-results div.desc", {"width": "295px"})
 size: (600, 100)
 // As counter-intuitive as it may seem, in this width, the width is "100%", which is why
 // when computed it's larger.
diff --git a/src/test/rustdoc-gui/sidebar-mobile.goml b/src/test/rustdoc-gui/sidebar-mobile.goml
index eecd584bca9..547eb3fd1b3 100644
--- a/src/test/rustdoc-gui/sidebar-mobile.goml
+++ b/src/test/rustdoc-gui/sidebar-mobile.goml
@@ -4,25 +4,28 @@
 goto: file://|DOC_PATH|/test_docs/struct.Foo.html
 // Switching to "mobile view" by reducing the width to 600px.
 size: (600, 600)
-assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 // Opening the sidebar menu.
-click: ".sidebar-menu"
-assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"display": "block", "left": "0px"})
 // Closing the sidebar menu.
-click: ".sidebar-menu"
-assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 // Force the sidebar open by focusing a link inside it.
 // This makes it easier for keyboard users to get to it.
 focus: ".sidebar-title a"
-assert-css: (".sidebar-elems", {"display": "block", "left": "0px"})
+assert-css: (".sidebar", {"display": "block", "left": "0px"})
 // When we tab out of the sidebar, close it.
 focus: ".search-input"
-assert-css: (".sidebar-elems", {"display": "block", "left": "-246px"})
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
 
 // Open the sidebar menu.
-click: ".sidebar-menu"
-assert-css: (".sidebar-elems", {"left": "0px"})
+click: ".sidebar-menu-toggle"
+assert-css: (".sidebar", {"left": "0px"})
 
 // Click elsewhere.
 click: "body"
-assert-css: (".sidebar-elems", {"left": "-246px"})
+assert-css: (".sidebar", {"display": "block", "left": "-1000px"})
+
+// Check that the topbar is visible
+assert-property: (".mobile-topbar", {"clientHeight": "45"})
diff --git a/src/test/rustdoc-gui/sidebar-source-code.goml b/src/test/rustdoc-gui/sidebar-source-code.goml
index 98f4fdf4233..1c5eb9239ba 100644
--- a/src/test/rustdoc-gui/sidebar-source-code.goml
+++ b/src/test/rustdoc-gui/sidebar-source-code.goml
@@ -10,6 +10,7 @@ click: (10, 10)
 // We wait for the sidebar to be expanded (there is a 0.5s animation).
 wait-for: 600
 assert-css: ("nav.sidebar.expanded", {"width": "300px"})
+assert-css: ("nav.sidebar.expanded a", {"font-size": "14.4px"})
 // We collapse the sidebar.
 click: (10, 10)
 // We wait for the sidebar to be collapsed (there is a 0.5s animation).
@@ -30,3 +31,6 @@ click: (10, 10)
 // We ensure that the class has been removed.
 assert-false: "nav.sidebar.expanded"
 assert: "nav.sidebar"
+
+// Check that the topbar is not visible
+assert-property: (".mobile-topbar", {"offsetParent": "null"})
diff --git a/src/test/rustdoc-gui/sidebar.goml b/src/test/rustdoc-gui/sidebar.goml
index 9289244f6f8..a1175525858 100644
--- a/src/test/rustdoc-gui/sidebar.goml
+++ b/src/test/rustdoc-gui/sidebar.goml
@@ -1,8 +1,14 @@
 goto: file://|DOC_PATH|/test_docs/index.html
+show-text: true
+local-storage: {"rustdoc-theme": "light"}
+// We reload the page so the local storage settings are being used.
+reload:
+
 assert-text: (".sidebar > .location", "Crate test_docs")
 // In modules, we only have one "location" element.
 assert-count: (".sidebar .location", 1)
-assert-text: (".sidebar-elems > #all-types", "See all test_docs's items")
+assert-text: ("#all-types", "All Items")
+assert-css: ("#all-types", {"color": "rgb(56, 115, 173)"})
 // We check that we have the crates list and that the "current" on is "test_docs".
 assert-text: (".sidebar-elems .crate > ul > li > a.current", "test_docs")
 // And we're also supposed to have the list of items in the current module.
@@ -24,13 +30,14 @@ assert-count: (".sidebar .location", 2)
 assert-false: ".sidebar-elems > .crate"
 
 click: ".sidebar-links a"
-assert-property: ("html", {"scrollTop": "389"})
+assert-property-false: ("html", {"scrollTop": "0"})
 
-click: ".sidebar h2.location"
+click: ".sidebar h2.location a"
 assert-property: ("html", {"scrollTop": "0"})
 
 // We now go back to the crate page to click on the "lib2" crate link.
 goto: file://|DOC_PATH|/test_docs/index.html
+assert-css: (".sidebar-elems .crate > ul > li:first-child > a", {"color": "rgb(56, 115, 173)"})
 click: ".sidebar-elems .crate > ul > li:first-child > a"
 
 // PAGE: lib2/index.html
@@ -51,8 +58,7 @@ click: "#functions + .item-table .item-left > a"
 // In items containing no items (like functions or constants) and in modules, we have one
 // "location" elements.
 assert-count: (".sidebar .location", 1)
-// There is a "<br>" tag between "in" and "lib2", but it doesn't count as a space.
-assert-text: (".sidebar .sidebar-elems .location", "Other items inlib2")
+assert-text: (".sidebar .sidebar-elems .location", "In lib2")
 // We check that we don't have the crate list.
 assert-false: ".sidebar-elems > .crate"
 
diff --git a/src/test/rustdoc-gui/type-declation-overflow.goml b/src/test/rustdoc-gui/type-declation-overflow.goml
index bb24d0ce792..21874f786f1 100644
--- a/src/test/rustdoc-gui/type-declation-overflow.goml
+++ b/src/test/rustdoc-gui/type-declation-overflow.goml
@@ -11,7 +11,7 @@ assert-property: (".item-decl pre", {"scrollWidth": "1324"})
 goto: file://|DOC_PATH|/lib2/too_long/type.ReallyLongTypeNameLongLongLong.html
 assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "840"})
+assert-property: ("#main-content", {"scrollWidth": "825"})
 // And now checking that it has scrollable content.
 assert-property: (".item-decl pre", {"scrollWidth": "1103"})
 
@@ -20,6 +20,13 @@ assert-property: (".item-decl pre", {"scrollWidth": "1103"})
 goto: file://|DOC_PATH|/lib2/too_long/constant.ReallyLongTypeNameLongLongLongConstBecauseWhyNotAConstRightGigaGigaSupraLong.html
 assert-property: ("body", {"scrollWidth": "1100"})
 // We now check that the section width hasn't grown because of it.
-assert-property: ("#main-content", {"scrollWidth": "840"})
+assert-property: ("#main-content", {"scrollWidth": "825"})
 // And now checking that it has scrollable content.
 assert-property: (".item-decl pre", {"scrollWidth": "950"})
+
+// On mobile:
+size: (600, 600)
+goto: file://|DOC_PATH|/lib2/too_long/struct.SuperIncrediblyLongLongLongLongLongLongLongGigaGigaGigaMegaLongLongLongStructName.html
+assert-property: (".mobile-topbar .location", {"scrollWidth": "504"})
+assert-property: (".mobile-topbar .location", {"clientWidth": "504"})
+assert-css: (".mobile-topbar .location", {"overflow-x": "hidden"})
diff --git a/src/test/rustdoc/cap-lints.rs b/src/test/rustdoc/cap-lints.rs
index 15910e1e900..08a35339680 100644
--- a/src/test/rustdoc/cap-lints.rs
+++ b/src/test/rustdoc/cap-lints.rs
@@ -3,7 +3,7 @@
 // therefore should not concern itself with the lints.
 #[deny(warnings)]
 
-// @has cap_lints/struct.Foo.html //* 'Struct Foo'
+// @has cap_lints/struct.Foo.html //* 'Foo'
 pub struct Foo {
     field: i32,
 }
diff --git a/src/test/rustdoc/crate-version-escape.rs b/src/test/rustdoc/crate-version-escape.rs
index 2f91eea339b..8413709f15e 100644
--- a/src/test/rustdoc/crate-version-escape.rs
+++ b/src/test/rustdoc/crate-version-escape.rs
@@ -2,5 +2,4 @@
 
 #![crate_name = "foo"]
 
-// @has 'foo/index.html' '//div[@class="block version"]/p' 'Version <script>alert("hi")</script>'
-// @has 'foo/all.html' '//div[@class="block version"]/p' 'Version <script>alert("hi")</script>'
+// @has 'foo/index.html' '//li[@class="version"]' 'Version <script>alert("hi")</script>'
diff --git a/src/test/rustdoc/crate-version.rs b/src/test/rustdoc/crate-version.rs
index 893af5c6133..2592c98530f 100644
--- a/src/test/rustdoc/crate-version.rs
+++ b/src/test/rustdoc/crate-version.rs
@@ -1,3 +1,3 @@
 // compile-flags: --crate-version=1.3.37
 
-// @has 'crate_version/index.html' '//div[@class="block version"]/p' 'Version 1.3.37'
+// @has 'crate_version/index.html' '//*[@class="version"]' 'Version 1.3.37'
diff --git a/src/test/rustdoc/titles.rs b/src/test/rustdoc/titles.rs
index 016ec7bfaa3..69e8b856b0a 100644
--- a/src/test/rustdoc/titles.rs
+++ b/src/test/rustdoc/titles.rs
@@ -1,10 +1,11 @@
 #![crate_name = "foo"]
-
 #![feature(rustdoc_internals)]
 
 // @matches 'foo/index.html' '//h1' 'Crate foo'
+// @matches 'foo/index.html' '//h2[@class="location"]' 'Crate foo'
 
 // @matches 'foo/foo_mod/index.html' '//h1' 'Module foo::foo_mod'
+// @matches 'foo/foo_mod/index.html' '//h2[@class="location"]' 'Module foo_mod'
 pub mod foo_mod {
     pub struct __Thing {}
 }
@@ -18,15 +19,19 @@ extern "C" {
 pub fn foo_fn() {}
 
 // @matches 'foo/trait.FooTrait.html' '//h1' 'Trait foo::FooTrait'
+// @matches 'foo/trait.FooTrait.html' '//h2[@class="location"]' 'FooTrait'
 pub trait FooTrait {}
 
 // @matches 'foo/struct.FooStruct.html' '//h1' 'Struct foo::FooStruct'
+// @matches 'foo/struct.FooStruct.html' '//h2[@class="location"]' 'FooStruct'
 pub struct FooStruct;
 
 // @matches 'foo/enum.FooEnum.html' '//h1' 'Enum foo::FooEnum'
+// @matches 'foo/enum.FooEnum.html' '//h2[@class="location"]' 'FooEnum'
 pub enum FooEnum {}
 
 // @matches 'foo/type.FooType.html' '//h1' 'Type Definition foo::FooType'
+// @matches 'foo/type.FooType.html' '//h2[@class="location"]' 'FooType'
 pub type FooType = FooStruct;
 
 // @matches 'foo/macro.foo_macro.html' '//h1' 'Macro foo::foo_macro'
diff --git a/src/test/rustdoc/typedef.rs b/src/test/rustdoc/typedef.rs
index 1fb28ee9970..4ecd62cded2 100644
--- a/src/test/rustdoc/typedef.rs
+++ b/src/test/rustdoc/typedef.rs
@@ -12,7 +12,7 @@ impl MyStruct {
 // @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyAlias'
 // @has - '//*[@class="impl has-srclink"]//h3[@class="code-header in-band"]' 'impl MyTrait for MyAlias'
 // @has - 'Alias docstring'
-// @has - '//*[@class="sidebar"]//*[@class="location"]' 'Type Definition MyAlias'
+// @has - '//*[@class="sidebar"]//*[@class="location"]' 'MyAlias'
 // @has - '//*[@class="sidebar"]//a[@href="#implementations"]' 'Methods'
 // @has - '//*[@class="sidebar"]//a[@href="#trait-implementations"]' 'Trait Implementations'
 /// Alias docstring