Rewriting the Workshop
published:
categories: organisation
At this point I could start to make rewriting my website an annual tradition. There have been a number of little details that have been rubbing me the wrong way for almost a year now; the biggest one was the navigation bar on sub-sites like the Grid Framework product site. There were also accessibility issues relating to the lack of a proper HTML document outline and the use of JavaScript.
The sub-site navigation bar
Until now I had simply been using the same standard navigation bar that is also on top of every page. This worked, but it was pretty ugly because even though one bar was clearly subordinate both looked the same. The sub-site bar needs to be smaller and less prominent.
The solution was to roll my own code for my own sub-site navigation bar. The
bar itself is simply a plain <ul>
and I am using the CSS flexbox module to
style it. Here is what the HTML looks like:
<nav class="sub-site-nav">
<h1>Sub-site navigation bar</h1>
<ul>
<li><a href="#">Title</a></li>
<li><a href="#">Item 1</a></li>
<li><a href="#">Item 2</a></li>
<li><a href="#">Item 3</a></li>
<li><a href="#">Item 4</a></li>
</ul>
</nav>
That's it, we only specify that our <nav>
is a sub-site navigation bar and
let the CSS style the elements accordingly. You will also notice that the title
is part of the list as well; I will use CSS to style the title differently, but
some people prefer to make the title a separate element from the list. I made
it part of the list because despite the visual distinction it is all one
navigation bar and the title should be counted when enumerating the list.
With the content set in place we can start applying the style to it. Since we
have wrapped everything inside a .sub-site-nav
item we style only its child
elements. First let's hide the heading, it's only used for the document
outline.
.sub-site-nav > h1 {
display: none;
}
Now comes the interesting part: the list. I am using the CSS flexbox module to style the site, it's a fairly new feature that allows us to pass specifications in CSS on how to distribute elements and let the browser figure out the optimum instead of computing values by hand. To this end we have to declare the list to be a flex container
.sub-site-nav > ul {
display: flex;
flex-wrap: wrap;
justify-content: flex-end;
}
The last property justify-content: flex-end
will push all elements to the
right while preserving their order (non-flexbox hacks would always reverse the
order). We are almost done, but in order to make the navigation look good we
have to make the title stand out from the other list items. Since the title is
the first child of the list we can use the first-child
pseudo-class:
.sub-site-nav > ul > li:first-child {
margin-right: auto;
}
This will push the first element as far to the left as possible. All that is
now left is styling the list elements themselves so they look good. I also
styled the nav
itself to give it a border line at the bottom to stand out
from the rest of the page. Thanks to flexbox it has been dead-simple to evenly
distribute the items in a few lines of CSS instead of heaving to resort to
awkward helper-classes or empty <div>
elements.
Document outline
The document outline is what made me rewrite all the templates almost from
scratch. The old outline was all flat, so I had to introduce sectioning
elements where I had <div>
elements before and use semantic HTML where ever
possible. In order to make it possible to identify those sections I also had to
add headings everywhere and hide them via CSS, as shown above. The workshop
should now become more accessible once more client software starts supporting
the outline algorithm. Go ahead and try it out, open this page in the HTML5
Outliner and see the result.
A new blog navigator
The sidebar for the blogs has also been changed from the ground up. The old one was too bulky and had a fancy "accordion" feature: clicking a year would un-collapse a list of sub-entries. That way you could click a year, then a month, and you would see all articles for that month right in the side bar. It was pretty fancy, but not very useful and utterly unusable without JavaScript, so I threw it out.
The new navigator is all static: clicking a year will take you to the archive of that year instead. You can see all articles from that year in the body of the page, and in the navigator a sub-list of months will appear under that year. Clicking a month will take you to the archive of that month, narrowing the body of the page down to only those articles.
Effectively the new navigator has exactly the same features as the old one, except it is static now. This means you will have to load a new page, but since there is no JavaScript to execute this will be very fast. The new navigator is also more accessible because it only lists the relevant items instead of having an archive of the entire blog at all times.
Finally, on small screen sizes the navigator is moved down beneath the articles and all the lists are hidden. They would take up too much screen space, instead the reader can click the titles or the archives and get taken there. This is accomplished using flexbox again. Here is the HTML first:
<section class="blog-body">
<h1>Blog</h1>
<main>
<section>
All the articles go here
</section>
</main>
<nav>
<h1>Blog navigation</h1>
<nav>
<h1><a href="#">Archives</a></h1>
<ul>
...
</ul>
</nav>
<nav>
<h1><a href="#">Categories</a></h1>
<ul>
...
</ul>
</nav>
<nav>
<h1><a href="#">Tags</a></h1>
<ul>
...
</ul>
</nav>
</nav>
</section>
/* The blog body contains the navigator and the articles list */
.blog-body {
display: flex;
}
.blog-body > nav {
order: -1; /* Move the navigator left from the article */
}
This will put the article(s) and the navigator horizontally next to each other
and move the navigator visually before the article by changing the order
property. For smaller devices we use a media query to change the flex direction
to a colum, which will put the navigator on top of the articles. We change the
order to move the navigator down and hide the lists.
@media(max-width: 768px) {
/* Re-arrange the articles and navigator vertically */
.blog-body {
flex-direction: column;
}
/* The navigator comes after the articles now. */
.blog-body > nav {
order: 0;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
}
/* Hide the navigator lists, they are too large */
.blog-body > nav > nav ul {
display: none;
}
}
Hamburger menu without JavaScript
Every site should provide its full functionality without requiring JavaScript. It might not be as pretty, but it has to fully work. The standard navigation bar example from Bootstrap requires JavaScript for the toggle, but it turns out that it can also be accomplished without. The following trick comes from the blog of Viral Patel, so all credit goes to him.
Here is the HTML:
<nav class="navbar navbar-default">
<div class="container">
<input type="checkbox" id="navbar-toggle-cbox">
<div class="navbar-header">
<label for="navbar-toggle-cbox" class="navbar-toggle collapsed"
data-toggle="collapse" data-target="#navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</label>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
</ul>
</div>
</div>
</nav>
The differences are the existence of a new <input type="checkbox">
element
and changing the <button>
to a <label>
. This by itself won't do anything,
we need a few lines of CSS as well:
#navbar-toggle-cbox {
display:none
}
#navbar-toggle-cbox:checked ~ .collapse {
display: block;
}
First we hide the checkbox from sight, then we use its state to toggle the
display of the .collapse
. If JavaScript is available the new hamburger menu
will work just like before, but if JavaScript is unavailable the collapsed
items will still pop up. It won't be as pretty because there will be no smooth
animation, but it will be usable.
I consider this a hack because it introduces an extra HTML item, but as long as there is no built-in solution in HTML or CSS every approach is more or less a hack.