CSS Sidebar Menu
Preface
Menu Code Location
Etc, etc. I mean, look at it now! The Miscellaneous menu item is highlighted with gold because this page has the misc tag!
If you do not care, you can put the menu code in the Global World Navigation Custom Content section. Just be sure the CSS selectors you use are the appropriate ones, depending on where you put the menu code. Global World Navigation Sidebar Custom Content section
Base-line CSS
Ok finally into some code stuff. I'm going to start with the base-line CSS. World Anvil has it where you have to click a button to expand their sidebar thing. I didn't want that so I changed it..user-css-presentation .world-navigation-palette-trigger { display: none; }Just set that element to not display. That's it, the button's gone. Important!: This next CSS is a little different depending if you put the menu code in the Global World Navigation Sidebar Custom Content section or the Global Footer section.
Global Navigation Sidebar CSS
.user-css-presentation #world-navigation-sidebar { display: block!important; position: fixed; left: 0; top: 55px; margin: 0; padding: 12px 0 0 0; width: 64px; min-width: 0; max-height: 100%; overflow-x: hidden; }Be sure the CSS base selector is .user-css-presentation and the div ID selector is #world-navigation-sidebar! This is specific to putting the menu code in the Global World Navigation Sidebar Custom Content section. Now it's not best practice to use the !important flag, but there was no other way to set the display mode to block. Anyway, now that we've got it always showing, we can style it. Here's where you can do what you want, but I'll go over the basics for the positioning and whatnot.
Global Footer CSS
.user-css .sidebar { display: block; position: fixed; left: 0; top: 55px; margin: 0; padding: 12px 0 0 0; width: 64px; height: 100%; z-index: 1500; overflow-x: hidden; }Be sure the CSS base selector is .user-css and the div CLASS selector .sidebar! This is specific to putting the menu code in the Global Footer section.
.user-css .sidebar:hover { width: 250px; transition: all 0.2s ease-in-out; }All I do it set the width for the :hover state, and that's it. I also add the transition property for the smoothness.
Compensating for the World Editor Bar
I want to make a note on how to compensate for the World Edit bar. I mentioned the World Anvil bar and to not mess with it, so I set the top variable to 55px. If you have sage, you can disable this banner and set the top to 0. However, for authors of a world, you will have this "World Editor" bar. You could disable this if you want, but I find it useful. So with some CSS magic, you can have your normal CSS for normies who don't see the bar, and specific CSS for when the bar is there. CSS.user-css-presentation:has(.world-editor-bar) .sidebar { top: 53px; }The CSS :has() selector checks to see if an element has a child with whatever thing you put in. In this case, .sidebar is selected if .user-css-presentation currently has the child div .world-editor-bar. If it does, then it sets the top of the sidebar to 53px, which is the height of the World Editor bar.
(Since I have Sage and disabled the World Anvil bar, my sidebar's normal top is 0 and not 55px like I mentioned before. Set the variable here to compensate for the World Anvil bar and the World Editor bar.)
The Menu Code
Base level menu items, with no submenus
[url:https://www.worldanvil.com/w/dragonguard][container:menu-item][section:fas fa-fw fa-lg fa-house] [/section] [p]Homepage[/p][/container][/url]Unfortunetly you can't line break between the URL tags; it won't work so you've got to slap it on all one line. I want the container of the menu item to also be the link, so I wrap the menu item container in the URL. Otherwise the text will be the only thing that's the link, and there will be a little empty space if the text is shorter than the width of the menu. This always annoys me, so wrap the container in the URL tags.
You also can't use the tagging system here, so you have to use the actual link.
Remeber to update the links in your menu, if there are any changes to your URLs! The section tags with the fas stuff in it is for the FontAwesome icon. In this case, this was my homepage button, so it uses a house.
You've got to add a space between the section tags for some reason, if you're just using it to display a FontAwesome icon. I don't know why, you just do. I wrap the menu item's name "Homepage" in a p tag so I can select it with CSS later.
.user-css .sidebar .menu-item,
.user-css .sidebar .submenu-item {
padding-left: 16px;
text-align: left;
align-content: center;
height: 44px;
}
.user-css .sidebar a:hover .menu-item,
.user-css .sidebar a:hover .submenu-item,
.user-css .sidebar .menu-dropout:hover .menu-item {
color: var(--bluesky)
text-decoration: none;
background-color: var(--midnight)
}
Both menu items and submenu items actually get the same CSS.
.user-css .sidebar .menu-item p { display: inline-block; height: 44px; font-size: 0px; align-content: center; vertical-align: middle; margin-bottom: 0; padding-left: 10px; transition: all 0.2s ease-in-out; } .user-css .sidebar:hover .menu-item p { font-size: 20px; transition: all 0.2s ease-in-out; }There's actually a decent amount of CSS just for the text that shows up. Most of it is positioning.
Menu items with submenu dropout
[container:menu-dropout] [url:https://www.worldanvil.com/w/dragonguard/a/locations][container:menu-item menu-locations][section:fas fa-fw fa-lg fa-location-dot] [/section] [p]Locations[/p][/container][/url] [container:submenu] [url:https://www.worldanvil.com/w/dragonguard/a/geographical-locations][container:submenu-item][section:fas fa-fw fa-lg fa-mountains] [/section] [p]Geographic[/p][/container][/url] [url:https://www.worldanvil.com/w/dragonguard/a/landmarks][container:submenu-item][section:fas fa-fw fa-lg fa-monument] [/section] [p]Landmarks[/p][/container][/url] [/container] [/container]This still uses the base menu item code, but slightly different. First off, I wrap the whole thing in a container named menu-dropout. The first menu item is the base, so that's normal. Then below that, I make another container that wraps any submenu items, named submenu. Then any submenu items have a different CSS class name of submenu-item, just in case if I want to do something slightly different with them. CSS
.user-css .sidebar .submenu {
visibility: hidden;
position: fixed;
width: 0;
left: 249px;
margin-top: -44px;
font-size: 0;
background: var(--darkcloud
transition: all 0.2s ease-in-out;
}
.user-css .sidebar .menu-dropout:hover .submenu {
visibility: visible;
width: 250px;
font-size: inherit;
transition: all 0.2s ease-in-out;
}
The visibility property here will hide and show the dropout submenu. We don't do this with the text on the base menu because it messes with the positioning of stuff. This is just for the submenu container, not an element within it, like the menu text.
Here are the other parts, if you want spacers and the Table of Contents in the sidebar too.
Menu Spacers
There are two kinds of spacers I use in the sidebar. One is padded, and the other is full width. Let's start with the padded one first.Padded Spacer
[container:menu-item menu-spacer][section:blank][hr][/section][/container]Yup, that's it. We still use the menu-item CSS class so it has similar sizing and whatnot, but it has an extra class too. The blank section probably isn't necessary, I put it there just in case I needed to do extra stuff. I wrap the HR tag in a container so I can specifically edit the HR that's only in the menu, and not any that are on the pages themselves. CSS
.user-css .sidebar .menu-item.menu-spacer {
width: 100%;
padding: 0 12px;
transition: width 0.2s ease-in-out;
}
.user-css .sidebar .menu-item.menu-spacer:hover {
background: none;
}
This actually has a width of 100% (so it grows with the sidebar when it's expanded), but the padding on the sides make it inset. Then, in the second section, I remove the background color. Since the code has the menu-item CSS class for the same universal styling, it also does the hover effect from the base menu item. I don't want the background changing color when you hover over this, this is just a spacer and not an actual menu link.
Now the way I setup the menu code in the World Settings is with line breaks in between each menu item / url tags. Unfortunately World Anvil will insert its own thing here when you do that, so to get rid of it while keeping the code readable, I just hide the element. Otherwise the menu items will be like.. doubled spaced. You have to use the !important flag here, which is not the best practice but it was the only way to hide the element. I don't necessarily recommend this, I just had to do it because I wanted the code to be easier to read. If you don't add line breaks and separate the menu items in the code, you won't need this.
.user-css .sidebar .line-spacer { display: none!important; }
Full Width Spacer
I also have a full width spacer for the TOC section. It's more of a top border really, but I just used the same pre-defined HR spacer I had before, with a slightly different CSS. It was easier.[container:menu-item menu-spacer-full][section:blank][hr][/section][/container]Yeah the same code as the other spacer, but with the menu-spacer-full CSS class instead. CSS
.user-css .sidebar .menu-item.menu-spacer-full { padding: 22px 0 0 0; height: 0; position: relative; z-index: 10; }The CSS for the full width spacer is different than the inset one.
Tag Based Menu Highlighting
One of the specific features I wanted to have was the menu items highlighting based on the current page's tags. I finally figured it out, so here's how I did it.You also need to setup a Tagging System for your article pages. The base sidebar CSS is slightly different for this than if you put the menu code in the Global World Navigation Sidebar Custom Content section.
.user-css .sidebar { display: block; position: fixed; left: 0; top: 55px; margin: 0; padding: 12px 0 0 0; width: 64px; height: 100%; z-index: 1500; overflow-x: hidden; }The main differences here vs the other way is:
.user-css.page[class*=tag-character] .sidebar a .menu-characters, .user-css.page[class*=tag-location] .sidebar a .menu-locations, .user-css [class*=world-meta] .sidebar a .menu-world-meta { background: var(--b50) color: var(--lightgold) }In this case I only showed three menu items. If you have more, just add them to the end and edit accordingly.
Full CSS Code
.user-css.page[class*=tag-character] .sidebar a .menu-characters, .user-css.page[class*=tag-location] .sidebar a .menu-locations, .user-css.page[class*=tag-fauna] .sidebar a .menu-fauna, .user-css.page[class*=tag-flora] .sidebar a .menu-flora, .user-css.page[class*=tag-item] .sidebar a .menu-objects, .user-css.page[class*=tag-prose] .sidebar a .menu-proses, .user-css.page[class*=tag-indices] .sidebar a .menu-glossary, .user-css.page[class*=tag-misc] .sidebar a .menu-misc, .user-css.page[class*=tag-wa-event] .sidebar a .menu-events, .user-css [class*=world-meta] .sidebar a .menu-world-meta { background: var(--b50) color: var(--lightgold) }
Full CSS Code
.user-css .sidebar a:hover, .user-css .sidebar a:hover .menu-item, .user-css .sidebar a:hover .submenu-item, .user-css .sidebar .menu-dropout:hover .menu-item, .user-css.page[class*=tag-character] .sidebar a:hover .menu-characters, .user-css.page[class*=tag-location] .sidebar a:hover .menu-locations, .user-css.page[class*=tag-fauna] .sidebar a:hover .menu-fauna, .user-css.page[class*=tag-flora] .sidebar a:hover .menu-flora, .user-css.page[class*=tag-item] .sidebar a:hover .menu-objects, .user-css.page[class*=tag-prose] .sidebar a:hover .menu-prose, .user-css.page[class*=tag-indices] .sidebar a:hover .menu-glossary, .user-css.page[class*=tag-misc] .sidebar a:hover .menu-misc, .user-css.page[class*=tag-wa-event] .sidebar a:hover .menu-events { background: var(--midnight) color: var(--bluesky) text-decoration: none; }
Table of Contents in the Sidebar
So I've seen some other World Anvil sites and noticed a few have the table of contents in the sidebar. However, these other sites that have the TOC in the navigation bar, do not have a collapsable sidebar. A few had a hidden pullout menu on the other size, but none had everything in on place. So I figured out how to do it and added it to my site.[container:sidebar-toc] [container:sidebar-toc-title-box] [container:sidebar-toc-title] [section:fas fa-fw fa-lg fa-bars-staggered] [/section][p]Table of Contents[/p] [/container] [/container] [container:sidebar-toc-separater] [/container] [container:sidebar-scroll-to] [url:#full-layout][section:fas fa-fw fa-arrow-up-to-line] [/section] Scroll to top[/url][br] [url:#comments][section:fas fa-fw fa-comments] [/section] Comments[/url] [hr] [/container] [articletoc] [/container]The whole TOC section is wrapped in a container. Then the title is wrapped in it's own box (for CSS styling). The text for the TOC title box is after that, but there's also the FontAwesome icon. Using CSS, the icon will be hidden when the sidebar is expanded, but visible when it's collapsed. After the title box stuff comes the actual TOC stuff. Well kind of. First there's a TOC separater, just for CSS purposes and is how I made the stylized angled slant to the title box. After that there is are Scroll to Top and Comments links, this will always be there even when there are no TOC contents. Then there's a horizontal line, and finally the articletoc tag. This articletoc tag (not to be confused with the world codex or just toc) will grab the headers from any article page and put them in the TOC. CSS time. There are a lot of "empty" containers for CSS stuff. CSS - Title Box
.user-css .sidebar .sidebar-toc-title-box { padding: 15px 0; text-align: center; background: linear-gradient(85deg, var(--b60) 0%, var(--midnight) 15% transition: all 0.2s ease-in-out; }
.user-css .sidebar .sidebar-toc-separater {
width: 0;
height: 0;
border-left: 0;
border-bottom: 0;
margin-top: 0;
transition: all 0.2s ease-in-out;
}
.user-css .sidebar:hover .sidebar-toc-separater {
width: 0;
height: 0;
margin-top: -10px;
border-left: 250px solid transparent;
border-bottom: 10px solid var(--stormcloud
transition: all 0.2s ease-in-out;
}
A lot of this is just zeroing out stuff, just to be sure, and for the collapsed sidebar. The main part of this is on the sidebar on hover state.
Swapping Icon and Title Text
Bunch of CSS for hiding the icon when the sidebar is expanded, but showing it when the sidebar is collapsed, and then the opposite for the title text. Like most of the other stuff, a lot of this is just freaking positioning it. Anyway.. CSS - Title Text
/ * Closed * /
.user-css .sidebar .sidebar-toc-title p {
display: inline-block;
margin: 0;
font-size: 0;
transition: all 0.2s ease-in-out;
}
/ * Open * /
.user-css .sidebar:hover .sidebar-toc-title p {
margin-left: 5px;
font-size: 23px;
transition: all 0.2s ease-in-out;
}
Because the icon and text are on the same line, we have to set their display to inline-block so they're.. inline.
/ * Closed * /
.user-css .sidebar .sidebar-toc-title .fas {
transition: all 0.2s ease-in-out;
}
/ * Open * /
.user-css .sidebar:hover .sidebar-toc-title .fas {
font-size: 0;
transition: all 0.2s ease-in-out;
}
This is a little weird because I'm not actually setting the font size here. The first block is when the sidebar is closed and I do a smooth transition for the font size, which it defaults to inheriting what the FontAwesome CSS is (the icon CSS classes were fa-fw and fa-lg). This is why I don't specifically set it myself, because I do not know what actual size it is.Anyway, while the sidebar is expanded, the icon gets hidden in the second section, with the font size of 0. Ok wow all that just for the TOC Title Box. There's still the actual TOC stuff to get through. oof.
TOC Section
I'll repost the relevant code for this section. This is for everything under that TOC Title Box, so pretty much the actual TOC stuff. Relavent Code - Recap[container:sidebar-scroll-to] [url:#full-layout][section:fas fa-fw fa-arrow-up-to-line] [/section] Scroll to top[/url][br] [url:#comments][section:fas fa-fw fa-comments] [/section] Comments[/url] [hr] [/container] [articletoc]So here I add a permanent Scroll to Top and Comments link just above the articletoc itself. This is for convenience, and I've seen it on a few other sites as well. All it is are two plain links that link to an anchor at the top of the page (#full-layout), and the other one links to an anchor if the comments section exists (#comments). They both have a FontAwesome icon as well. After that is a horizontal line, and then finally, the freaking article's TOC contents itself.
CSS time. CSS
/ * Closed * /
.user-css .sidebar .sidebar-scroll-to {
margin: 0;
font-size: 0;
transition: all 0.2s ease-in-out;
}
/ * Open * /
.user-css .sidebar:hover .sidebar-scroll-to {
margin: 5px 15px;
font-size: 14px;
transition: all 0.2s ease-in-out;
}
The anchor links of course get hidden too, when the sidebar is collapsed. Again, for the 69th time, using the font size trick. Also adjusting the margins and setting them to 0 when it's hidden because it would otherwise mess with the positioning of stuff.
There's also some general styling for this part too, that I didn't include. All I do is add some left padding to the links, so they're offset a bit, and style the horizontal line.
Now for the moment you've been waiting for! The Krabby Patty Secret Formula is — wait, no, wrong thing.
Ah yes, the TOC thing and its CSS. Bet you can't guess how I did it. Go on guess. CSS - part 1
.user-css .sidebar .articletoc {
border: none;
font-size: 0;
margin: 5px 15px;
padding: 0;
padding-bottom: 6em;
width: -webkit-fill-available;
transition: all 0.2s ease-in-out;
}
.user-css .sidebar:hover .articletoc {
font-size: 16px;
transition: all 0.2s ease-in-out;
}
That's right!Default font size of 0, then actually set it on the sidebar on hover state!
I also remove the border, because I didn't want that garbage. Everything else is just positional stuff. I also change the link's color and add an underline (it's actually a bottom border) when you hover over it (shown below).
I do this because of the Accessibility button that shows up at the bottom. This will ensure there is enough space to scroll and see the very last item in the Table of Contents, no matter how long it is.
.user-css .sidebar .articletoc .article-toc-link { padding: 0; margin: 0; border: 0; } .user-css .sidebar:hover .articletoc .article-toc-link { padding-bottom: 3px; margin-bottom: 3px; } .user-css .sidebar .articletoc .article-toc-link:hover { color: var(--bluesky) border-bottom: 1px solid var(--bluesky) }If you have many headings, such as on an Index page, the padding and margins of the items will be enough to still mess up the sidebar. So set everything on the TOC link to zero, then on the on hover state of the sidebar, set the TOC link's bottom padding and margin to 3px. This is what it was initially. The last block is just for the on hover state for the TOC item itself; setting the border to what it was before, instead of just it's color.
I love this, Thank you for this... I wish I could get it to work, and maybe I have been staring at it for too long and need to step away and take a break. But I love it all the same and really hope I can get it working. There something not adding up with the code put in the global footer on my end me thinks.