In this customization, we're doing our second upgrade to our Shopify blog pages. We’re adding a sidebar to our blog and articles. The sidebar works best if you add the badges first, so I do suggest checking out the previous video if you haven’t already.
Compatible Themes: This code should work on all free Shopify themes (Dawn, Refresh, Craft, Studio, Publisher, Crave, Origin, Taste, Colorblock, Sense, Ride, Spotlight).
Links:
Add Custom Blog Settings
Edit config file settings_schema.json
{
"name": "Blog Custom Sidebar",
"settings": [
{
"type": "header",
"content": "Blog Page Settings"
},
{
"type": "checkbox",
"id": "hide_blog_title",
"default": false,
"label": "Hide Blog Title"
},
{
"type": "checkbox",
"id": "show_blog_sidebar",
"default": false,
"label": "Show Blog Sidebar"
},
{
"type": "text",
"id": "filter_title",
"label": "Filter Title",
"default": "Categories"
},
{
"type": "select",
"id": "show_filters",
"options": [
{
"value": "none",
"label": "None"
},
{
"value": "tag_buttons",
"label": "Tag Buttons"
},
{
"value": "tag_checkbox",
"label": "Tag Checkboxes"
}
],
"default": "tag_buttons",
"label": "Show Tag Filters"
},
{
"type": "text",
"id": "blog_all_tag",
"label": "Tag text for all articles",
"default": "all"
},
{
"type": "checkbox",
"id": "show_latest_featured_article",
"default": false,
"label": "Show Latest Featured Article"
},
{
"type": "text",
"id": "featured_article_title",
"label": "Latest Featured Article Title",
"default": "Featured Article"
},
{
"type": "text",
"id": "featured_article_tags",
"label": "Latest Featured Article Tags",
"placeholder": "tag1,tag2,tag3",
"info": "Enter tags for featured sidebar article, separated by commas"
},
{
"type": "header",
"content": "Blog Article Settings"
},
{
"type": "checkbox",
"id": "show_article_sidebar",
"default": false,
"label": "Show Article Sidebar"
},
{
"type": "text",
"id": "sidebar_navigation_title",
"label": "Article Sidebar Title",
"default": "Quick Navigation"
},
{
"type": "header",
"content": "Sidebar Settings"
},
{
"type": "color_scheme",
"id": "blog_sidebar_color_scheme",
"label": "Blog Sidebar Color Scheme",
"default": "scheme-2"
}
]
},
Add Sidebar to Blog
Edit section main-blog.liquid
Add stylesheet to top of file
{{ 'component-sidebar-custom.css' | asset_url | stylesheet_tag }}
Add if statement to conditionally hide the blog title
{% unless settings.hide_blog_title %}
... existing h1 title code here ...
{% endunless %}
Add if statements to wrap existing blog section to conditionally change the blog html structure with the sidebar
{% if settings.show_blog_sidebar %}
<div class="content-container blog-page page-width">
<aside class="blog-sidebar">
{% render 'sidebar-content-blog' %}
</aside>
<main class="main-content">
{% endif %}
.... existing blog div here ....
{% if settings.show_blog_sidebar %}
</main>
</div>
{% endif %}
Add id="articles-container"
to the div with class blog-articles
<div id="articles-container" class="blog-articles {% if section.settings.layout == 'collage' %}blog-articles--collage{% endif %}">
Add data-tags to the div with class blog-articles__article
data-tags="{{ article.tags | map: 'handle' | join: ' ' }}"
Create new snippet sidebar-content-blog.liquid
{{ 'component-sidebar-custom.css' | asset_url | stylesheet_tag }}
<div class="blog-sidebar blog-page color-{{ settings.blog_sidebar_color_scheme }}">
{% if settings.show_filters != none %}
<h2>{{ settings.filter_title }}</h2>
{%- assign excluded_tags = settings.excluded_tags | split: ',' -%}
{%- assign cleaned_excluded_tags = '' -%}
{%- for tag in excluded_tags -%}
{%- assign cleaned_tag = tag | strip | downcase -%}
{%- assign cleaned_excluded_tags = cleaned_excluded_tags | append: cleaned_tag | append: ',' -%}
{%- endfor -%}
{%- assign final_excluded_tags = cleaned_excluded_tags | split: ',' -%}
{% if settings.show_filters == 'tag_buttons' %}
{% assign url_parts = request.path | split: '/' %}
{% assign current_tag_handle = url_parts[4] %} {% comment %} Adjust index based on your URL structure {% endcomment %}
<div class="tag-buttons">
<a href="{{ blog.url }}"
class="tag-badge badge color-{{ settings.blog_tag_color_scheme }}
{%- if settings.blog_tag_hover_effect == 'underline' -%} hover-underline
{%- elsif settings.blog_tag_hover_effect == 'bold' -%} hover-bold
{%- endif -%}
{% if current_tag_handle == nil or current_tag_handle == '' %}active{% endif %}">
{{ settings.blog_all_tag }}
</a>
{%- for tag in blog.all_tags -%}
{%- assign current_tag = tag | downcase -%}
{%- unless final_excluded_tags contains current_tag -%}
{%- assign tag_handle = tag | handle -%}
<a href="{{ blog.url }}/tagged/{{ tag_handle }}"
class="tag-badge badge color-{{ settings.blog_tag_color_scheme }}
{%- if settings.blog_tag_hover_effect == 'underline' -%} hover-underline
{%- elsif settings.blog_tag_hover_effect == 'bold' -%} hover-bold
{%- endif -%}
{% if tag_handle == current_tag_handle %}active{% endif %}">
{{ tag }}
</a>
{%- endunless -%}
{%- endfor -%}
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const tags = document.querySelectorAll('.tag-badge');
tags.forEach(tag => {
tag.addEventListener('click', function(event) {
tags.forEach(t => t.classList.remove('active'));
this.classList.add('active');
});
});
});
</script>
{% elsif settings.show_filters == 'tag_checkbox' %}
{{ 'component-checkbox-custom.css' | asset_url | stylesheet_tag }}
<div class="tag-filters">
<form id="tag-filter-form">
{%- for tag in blog.all_tags -%}
{%- assign current_tag = tag | downcase -%}
{%- unless final_excluded_tags contains current_tag -%}
<label class="custom-checkbox" for="tag-{{ tag | handle }}">
<input type="checkbox" id="tag-{{ tag | handle }}" class="custom-checkbox__input" name="tag" value="{{ tag | handle }}">
<span class="custom-checkbox__icon"></span>
{{ tag }}
</label>
{%- endunless -%}
{%- endfor -%}
</form>
</div>
<script>
document.getElementById('tag-filter-form').addEventListener('change', function() {
const checkboxes = document.querySelectorAll('#tag-filter-form input[type="checkbox"]:checked');
const selectedTags = Array.from(checkboxes).map(cb => cb.value);
const articles = document.querySelectorAll('#articles-container .article');
articles.forEach(article => {
const tags = article.getAttribute('data-tags').split(' ');
if (selectedTags.some(tag => tags.includes(tag)) || selectedTags.length === 0) {
article.style.display = '';
} else {
article.style.display = 'none';
}
});
});
</script>
{% endif %}
{% endif %}
{% if settings.show_latest_featured_article %}
<div class="featured-post">
{%- assign featured_tags = settings.featured_article_tags | split: ',' -%}
{%- assign latest_featured_article = nil -%}
{%- for article in blog.articles -%}
{%- for tag in featured_tags -%}
{%- assign cleaned_tag = tag | strip | downcase -%}
{%- if article.tags contains cleaned_tag -%}
{%- assign latest_featured_article = article -%}
{%- break -%}
{%- endif -%}
{%- endfor -%}
{%- if latest_featured_article != nil -%}
{%- break -%}
{%- endif -%}
{%- endfor -%}
{%- if latest_featured_article == nil -%}
{%- assign latest_featured_article = blog.articles.first -%}
{%- endif -%}
{%- if latest_featured_article -%}
<h2>{{ settings.featured_article_title }}</h2>
<div class="featured-article-card">
{%- render 'article-card',
article: latest_featured_article,
show_image: true,
show_date: true,
show_author: false,
show_excerpt: false
-%}
</div>
{%- endif -%}
</div>
{% endif %}
</div>
Add Custom Styling
Create new asset component-sidebar-custom.css
.content-container {
display: grid;
grid-template-columns: 1fr 3fr;
gap: 20px;
}
.main-content {
width: 100%; /* Full width */
min-width: 0;
}
.blog-sidebar {
padding: 10px;
position: -webkit-sticky;
position: sticky;
top: 30px; /* Adjust this value based on your header/nav height */
}
.article-page .blog-sidebar {
height: calc(100vh - 40px);
overflow-y: auto;
}
.blog-page .blog-sidebar {
height: auto;
overflow-y: visible;
}
.blog-sidebar .featured-article-card {
margin-bottom: 20px; /* space between cards */
}
.blog-sidebar .featured-post .article {
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
border-radius: 8px;
}
.tag-buttons {
display: flex;
flex-wrap: wrap;
margin-top: 10px; /* Adjust spacing above the tag list */
gap: 5px; /* Adjust the spacing between tags */
}
.badge.tag-badge {
text-decoration: none;
}
.badge.tag-badge.hover-underline:hover {
text-decoration: underline; /* Underline on hover */
}
.badge.tag-badge.hover-bold:hover {
font-weight: bold; /* Bold text on hover */
}
.card__badge .tag-badge {
margin-right: 5px;
}
.tag-buttons .tag-badge.active {
background-color: rgb(var(--color-foreground));
color: rgb(var(--color-background));
border: 1px solid rgb(var(--color-background));
}
.quick-links-sidebar {
background-color: rgb(var(--color-background));
padding: 10px;
white-space: normal;
overflow-wrap: break-word;
}
.quick-links-sidebar h2 {
margin-bottom: 10px;
color: rgb(var(--color-foreground));
}
.quick-links-sidebar ul {
list-style-type: none;
padding-left: 0; /* Ensure no default padding */
}
.quick-links-sidebar li {
margin-bottom: 15px;
font-weight: bold;
}
.quick-links-sidebar li a {
display: block;
color: rgb(var(--color-foreground));
text-decoration: none;
line-height: 1.2;
}
.quick-links-sidebar li.h2-link a {
padding-left: 0px; /* No padding for h2 links */
}
.quick-links-sidebar li.h3-link a {
font-size: 0.875em;
padding-left: 20px; /* Indent h3 links for hierarchy, applies to all content */
}
@media (min-width: 750px) {
.main-content .page-width {
padding: 0 1rem;
}
}
@media (max-width: 749px) {
.content-container {
display: block; /* Stack sidebar and main content vertically */
}
.blog-sidebar {
position: static; /* Remove sticky positioning */
width: 100%;
height: auto;
top: auto;
overflow-y: visible; /* No scrolling needed */
border: none;
}
.article-page .blog-sidebar {
height: auto;
overflow-y: visible;
}
.blog-page .featured-post {
display: none;
}
}
Create new asset component-checkbox-custom.css
.custom-checkbox {
cursor: pointer;
display: block;
align-items: center;
margin-bottom: 0px; /* Space between checkboxes */
}
#tag-filter-form .custom-checkbox__input {
display: none;
}
.custom-checkbox__icon {
width: 16px;
height: 16px;
border: 1px solid;
color: rgba(var(--color-foreground), 0.5);
margin-right: 5px;
display: inline-flex;
align-items: center;
transform: translateY(-2px);
justify-content: center;
background-color: transparent;
}
.custom-checkbox__input:checked + .custom-checkbox__icon {
background-color: rgb(var(--color-background));
}
.custom-checkbox__icon::before {
content: '';
width: 10px;
height: 5px;
border-left: 2px solid currentColor;
border-bottom: 2px solid currentColor;
transform: translate(0, -1px) rotate(-45deg);
opacity: 0; /* Hidden when unchecked */
}
.custom-checkbox__input:checked + .custom-checkbox__icon::before {
opacity: 1; /* Show checkmark when checked */
}
Add Sidebar to Blog Articles
Edit section main-article.liquid
Add stylesheet to top of file
{{ 'component-sidebar-custom.css' | asset_url | stylesheet_tag }}
Add if statements to wrap existing article content to conditionally change the article html structure with the sidebar
{% if settings.show_article_sidebar %}
<div class="content-container article-page page-width">
<aside class="blog-sidebar">
{% render 'sidebar-content-article' %}
</aside>
<main class="main-content">
{% endif %}
.... existing article div here ....
{% if settings.show_article_sidebar %}
</main>
</div>
{% endif %}
Create new snippet sidebar-content-article.liquid
<div class="quick-links-sidebar color-{{ settings.blog_sidebar_color_scheme }}">
<h2>{{ settings.sidebar_navigation_title }}</h2>
<ul id="quick-links"></ul>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const articleContent = document.querySelector('.article-template__content');
const headers = articleContent.querySelectorAll('h2, h3');
const quickLinks = document.getElementById('quick-links');
headers.forEach(function(header) {
const anchor = document.createElement('a');
const li = document.createElement('li');
header.id = header.textContent.replace(/\\s+/g, '-').toLowerCase();
anchor.href = '#' + header.id;
anchor.textContent = header.textContent;
anchor.classList.add('quick-link');
li.classList.add(header.tagName.toLowerCase() + '-link');
li.appendChild(anchor);
quickLinks.appendChild(li);
});
});
</script>