Building categories page on this site
CSS columns
This article explains how I build "Categories" page on this site. Nothing special, really.
First version
First version of 'Categories' (or 'tags') page on this site was build with flex-box layout. Every "box" had a category logo, category name and amount of articles in that category. Unfortunately, that doesn't work well for me. Not only that it turns out to be hard to maintain (need to add new image for every new category), but there are also legal issues. Sometimes, logo's are copyrighted and you can not use them without permission. Sometimes, you must use logo as is, without converting it to single color version (looks better then grid with 20+ logos in different colors).
CSS columns
After some thinking, I figured out that something like a alphabetic index works best for this and the best way to do it is with CSS columns. Here is how it looks like in Middleman erb template:
<div id="category-list">
<% ('A'..'Z').to_a.each do |letter| -%>
<% letter_hash = blog.tags.select {|k,v| k[0].upcase == letter} %>
<% unless letter_hash.keys.empty? %>
<div>
<h2><%= letter -%></h2>
<ul>
<% letter_hash.each do |tag, articles| %>
<li>
<%= link_to "#{tag} (#{articles.size})", tag_path(tag),
class: "category category-"+tag.downcase.gsub(' ','_') %>
</li>
<% end %>
</ul>
</div>
<% end %>
<% end -%>
</div>
Here is final SCSS:
div#category-list {
columns: 275px;
column-gap: 20px;
margin: 0 15px 20px 50px;
div {
margin: 0 0 20px 0;
padding: 30px 0 0 0;
break-inside: avoid;
min-height: 8rem;
display: flex;
h2 {
z-index: 1;
content: attr(data-letter);
font-size: 6rem;
line-height: 6rem;
display: block;
width: 105px;
margin: 0;
padding: 0;
color: $simplify-grey;
font-weight: 900;
opacity: 0.10;
}
ul {
z-index: 2;
list-style: none;
margin: 10px 0 0 -75px;
padding: 0;
a {
display: block;
font-size: 1.5rem;
font-weight: 600;
&:hover {
text-decoration: underline;
}
}
}
}
}
Most important parts:
- By specifying
columns
in pixel I'm sure that browser will calculate number of columns on the page and I don't need to use any @media queries for this. - Every
div
block will not brake when browser create columns on the page. - Every
div
block have minimal height of 8 rem's. Reason for this is that letter indicator size is 6rem anddisplay
is set toflex
. In all browsers except IE/Edge 7rem was enough. - h2 element is set behind the list with
z-index
, and with opacity of 0.1 for better effect. Width is 105px, a bit wider then letter 'W'. - List have negative left margin and is positioned above h2 element.
- Link in the list is a bit bigger then normal text on the site, and typeface is bold.