Further nightCasper theme development; reading progress bar added. CSS/Handlebars.js discussion.
nightCasper Development - Progress Bar
In previous devLog posts, I have chronicled some of my design decisions while building out nightCasper. Today's devLog continues that theme and focuses on a question posed by a user in the Ghost forums, which I was glad to be able to help him with:
I wanted to elaborate a little more on why he was running into this issue and why my HTML/CSS recommendations fixed it.
The Problem
Let's first begin by looking at his initial insertion point for the progress bar:
{{!< default}}
{{!-- The tag above means: insert everything in this file
into the {body} of the default.hbs template --}}
<header class="site-header">
{{> site-header}}
</header>
{{!-- Everything inside the #post tags pulls data from the post --}}
{{#post}}
<main id="site-main" class="site-main outer">
<div class="inner">
By inserting his progress bar after line 7 in post.hbs, he is inserting his progress bar into the header element, right after the site header. The site header is populated by the Handlebars partial:
<div class="outer site-nav-main">
<div class="inner">
{{> "site-nav"}}
</div>
</div>
This means that by inserting the progress bar after site header, he has also inserted it outside of site-header and therefore his final result ultimately renders to something like this:
When you see div containers set up like this, it's usually for a reason (i.e. there's CSS styling applied) and it's best to continue with that style. Therefore, we should also wrap that progress bar in a div:
<div id="bottomHeader">
<progress class="reading-progress-bar"></progress>
</div>
Additionally, I would like for this new progress bar div container to stay grouped with the overall site header (and within the overall container div it provides). If we add it to post.hbs, as van attempted to do, it's too late, as the site header has already been provided by the site-header.hbs partial and we would end up with something like this:
<header class="site-header">
<div class="outer site-nav-main">
<div class="inner">
{{> "site-nav"}}
</div>
</div>
<div id="bottomHeader">
<progress class="reading-progress-bar"></progress>
</div>
</header>
The Fix
We're close, but we're still not completely there yet. I would like for the bottomHeader div to be contained within the "outer site-nav-main" div class. I.e. I would like lines 7-9 above to dwell between lines 5 and 6:
<header class="site-header">
<div class="outer site-nav-main">
<div class="inner">
{{> "site-nav"}}
</div>
<div id="bottomHeader">
<progress class="reading-progress-bar"></progress>
</div>
</div>
</header>
The way to accomplish this is to simply add our bottomHeader div + progress element to the site-header.hbs. This introduces a slight problem as the site-header is a partial would display on every other Handlebar template that called it, such as in the index. While I would like for you to scroll through all of my posts on the homepage, I certainly don't expect every user to, and therefore I think a progress bar would be meaningless there. Thankfully, this can be handled nicely with Handlebars with the addition of a simple if statement to check the context. If it's a post context, we'll display our progress bar:
That just leaves us with the styling to handle:
#bottomHeader {
height:2px;
position: relative;
top:0px;
left: -5vw;
}
progress.reading-progress-bar {
appearance: none;
position: absolute;
width: 100vw;
height: 2px;
}
For the bottomHeader, since we now have our progress bar wrapped in a div, we can use position: relative; to allow us to not only add the progress bar (really the bottomHeader div it's contained in) after the regular navigation bar. It also lets us use the helper property, left, to move the div to the left. (This is needed because of the margin Ghost's Casper has specified and so it allows us to blow through that margin). We then use absolute position for the progress bar styling so that it is positioned relative to its parent, the div bottomHeader. (Counterintuitively, position: absolute; an element is positioned relative to its parent, as opposed to position: relative; where it is positioned relative to itself.)