hugoでカテゴリによって背景を変える
Posted:
背景
カテゴリごとに背景を変えられたら、今見ている記事の分野が少し分かりやすくなる。 また、背景に軽いアニメーションを加えると、技術メモの見た目にも変化を付けられる。
このサイトでは、Markdownのフロントマターにある categories を使い、カテゴリごとにCSSと背景用HTMLを切り替えている。
現在は次の3種類を設定している。
| categoriesの値 | 背景 |
|---|---|
docker | 海の背景と揺れるDockerのクジラ |
AWS | Client、CloudFront、ALB、ECS、RDS、ElastiCacheの構成図 |
bash | tcpdump風のログが流れる黒い画面 |
カテゴリ名は大文字・小文字を区別するため、AWSの記事では aws ではなく AWS と記述する。
Hugoでの分岐
Hugoでは .Params を経由して、ページのフロントマターに設定した値を参照できる。
今回使用するのは .Params.categories である。
処理は次の2か所に分けている。
layouts/partials/head.htmlでカテゴリ別のCSSとJavaScriptを読み込むlayouts/_default/single.htmlで背景表示に必要なHTMLを生成する
背景画像やアイコンは static/images/、カテゴリ別CSSは static/css/ に配置している。
変更箇所
現在の主な関連ファイルは次のとおり。
| ファイル | 役割 |
|---|---|
layouts/partials/head.html | カテゴリ別CSSとJavaScriptの読み込み |
layouts/_default/single.html | 背景用HTMLの生成 |
static/css/docker.css | Docker背景 |
static/css/aws.css | AWS構成図の基本レイアウト |
static/css/aws-icons.css | AWSアイコンとスケールアニメーション |
static/css/aws-flow.css | 接続線とアイコンだけの表示調整 |
static/css/aws-article.css | AWS記事本文と構成図の最終的な見た目 |
static/js/aws-flow.js | オブジェクト間の線と光点の描画 |
static/css/bash.css | tcpdump風背景 |
assets/css/userstyles.css | サイト全体の共通スタイル |
layouts/partials/head.html
<head> 内で、Markdownの categories に応じて読み込むファイルを切り替える。
{{ if in .Params.categories "docker" }}
<link rel="stylesheet" href="/css/docker.css">
{{ else if in .Params.categories "AWS" }}
<link rel="stylesheet" href="/css/aws.css">
<link rel="stylesheet" href="/css/aws-icons.css">
<link rel="stylesheet" href="/css/aws-flow.css">
<link rel="stylesheet" href="/css/aws-article.css">
<script defer src="/js/aws-flow.js"></script>
{{ else if in .Params.categories "bash" }}
<link rel="stylesheet" href="/css/bash.css">
{{ end }}
カテゴリ別のファイルは共通CSSより後に読み込む。 こうすると、背景を持つ記事だけに追加スタイルを適用でき、カテゴリ固有の設定で共通スタイルを上書きできる。
AWSでは役割が増えたため、1つの巨大なCSSにせず、レイアウト、アイコン、通信フロー、記事本文の表示調整を分割している。
layouts/_default/single.html
記事本文を表示した後に、カテゴリごとの背景用HTMLを追加する。
実際のAWS構成図は複数の要素を持つが、分岐の基本形は次のようになる。
{{ if in .Params.categories "docker" }}
<div id="docker-whale"></div>
{{ else if in .Params.categories "AWS" }}
<div id="aws-system" aria-hidden="true">
<div class="aws-architecture">
<!-- AWS構成図 -->
</div>
</div>
{{ else if in .Params.categories "bash" }}
<div id="tcpdump-output" aria-hidden="true">
<!-- tcpdump風のログ -->
</div>
{{ end }}
背景用要素は記事本文より後ろに配置し、position と z-index で重なり順を制御する。
背景は装飾なので、内容を読み上げる必要がないものには aria-hidden="true" を付ける。
Docker背景
Dockerカテゴリでは、海の背景画像を固定し、その上でDockerのクジラを揺らしている。
body {
background: url('/images/sea-background.png') no-repeat center center fixed;
background-size: cover;
}
#docker-whale {
position: fixed;
top: 50%;
left: 50%;
width: 60%;
height: 60%;
background: url('/images/docker.png') center / contain no-repeat;
animation: wave 20s infinite;
z-index: 0;
}
main {
position: relative;
z-index: 100;
}
@keyframes wave {
0%, 100% {
transform: translate(-50%, -50%) rotate(10deg);
}
50% {
transform: translate(-50%, -50%) rotate(-10deg);
}
}
position: fixed にすることで、本文をスクロールしても背景のクジラは画面内に残る。
AWS背景
AWSカテゴリでは、1枚の背景画像ではなく、HTML、CSS、SVG、JavaScriptを組み合わせて構成図を表示している。
現在の構成は次の流れを表している。
Client
↓
CloudFront
↓
Application Load Balancer
↓
ECS Tasks
├─ RDS Writer / Readers
└─ ElastiCache Primary / Replicas
JavaScriptは実際に描画された各オブジェクトの位置を取得し、SVGの曲線で接続する。 そのため、画面幅が変わった場合や、スケールアウトのアニメーションでノードが移動した場合も線が追従する。
ECS Task、RDS Reader、ElastiCache Replicaは、opacity: 0 から opacity: 1 へ変化させてスケールアウトを表現する。
この透明度はノードの増減を表すアニメーションとして意図的に残している。
本文背景と構成図の透明度を分ける
要素全体に opacity を指定すると、その子要素にある文字やアイコンもすべて薄くなる。
本文の読みやすさを調整したい場合は、本文全体の opacity ではなく、背景色のアルファ値を変更する。
現在のAWS記事では、本文を白60%、背後の構成図を40%見せている。
main {
background-color: rgba(255, 255, 255, 0.6) !important;
}
main article,
.blog-post-content {
background-color: transparent !important;
}
.aws-architecture {
opacity: 1 !important;
}
rgba(255, 255, 255, 0.6) の最後の 0.6 は、白背景の不透明度が60%であることを表す。
構成図そのものは不透明のままにして、本文の白背景だけで見え方を調整する。
このように設定箇所を分けておくと、構成図の色や接続線を薄くせず、本文の可読性だけを調整できる。
Bash背景
Bashカテゴリでは、画面全体に黒い背景を置き、緑色のtcpdump風ログを縦方向へ流している。
#content #tcpdump-output {
position: fixed;
inset: 0;
width: 100vw;
height: 100vh;
overflow: hidden;
z-index: 1;
background-color: black;
}
#content #tcpdump-output .tcpdump-content {
position: absolute;
width: 100%;
height: 200%;
animation: scroll 10s linear infinite;
}
#content #tcpdump-output .tcpdump-text p {
color: #008000;
}
本文は背景より前面に置き、白い半透明背景を使って可読性を確保する。
Markdownでカテゴリを指定する
Docker記事の例。
---
title: docker
date: "2021-08-08T21:39:03.284Z"
categories:
- "docker"
tags:
- "docker"
---
AWS記事では大文字の AWS を指定する。
---
title: aws/s3
date: "2021-08-21T22:30:03.284Z"
categories:
- "AWS"
tags:
- "s3"
---
Bash記事の例。
---
title: bashでcgi
date: "2019-07-30T22:30:03.284Z"
categories:
- "bash"
tags:
- "bash"
---
実装時の注意点
- カテゴリ名の大文字・小文字をフロントマターとテンプレートで一致させる
- 背景用CSSとJavaScriptは対象カテゴリの記事だけで読み込む
- 本文の可読性は
opacityではなくbackground-color: rgba(...)で調整する - 背景用要素には
pointer-events: noneを設定し、本文のリンクや選択操作を妨げないようにする - 装飾目的の背景は
aria-hidden="true"にする - 動きが必須でない場合は
prefers-reduced-motionでアニメーションを停止できるようにする - 複雑な背景はCSSやJavaScriptを役割ごとに分割する