jekyllのカスタマイズ(ポスト編)

今回はブログ投稿記事で使用されるスタイル等の細々したものを説明していきます。
ここで紹介されているカスタマイズは、一部bulmaフレームワークの変数やヘルパー関数を使用していますが、基本的に使用しなくても実現可能です。

なにはともあれ、ほとんど趣味的なカスタマイズなので参考になれば幸いです。

設定

追加スクリプトの設定

<!-- head scripts -->
    <!-- mathjaxスクリプト注入 -->
    {% if page.mathjax %}{% include mathjax-v3.html %}{% endif %}
    <!-- highlight.jsスクリプト注入 -->
    {% include highlight-js.html %}

ページ内部で使用するスクリプトは_includes/head-scripts.htmlに追加します。
直接scriptタグを書いてもいいのですが、見づらくなるのが嫌なので別ファイルにしてincludeで読み込むようにします。
MathJaxは結構重いので必要な時にのみ読み込むようにします。

ちなみにこの_includes/head-scripts.htmlの読み込み順序としては、Bulmaフレームワークfontawesomeの後、<body>読み込みの前になります。

MathJaxのスクリプト追加

<!-- Begin mathjax-v3 -->
<script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<!-- End mathjax-v3 -->

MathJax Docsにある通り、上記の様に<script>タグを追加します。

MathJaxを使用することで、数式をきれいにレンダリングできます。MathJaxを使用するには、記事のフロントマターでmathjax: trueを追加します。

\[\begin{eqnarray} \left\{ \begin{aligned} \nabla \cdot \vec{\mathbf{B}} &= 0 \\ \nabla \cdot \vec{\mathbf{D}} &= \rho \\ \nabla \times \vec{\mathbf{H}} &= \vec{\mathbf{j}} + \frac{\partial\vec{\mathbf{D}}}{\partial t} \\ \nabla \times \vec{\mathbf{E}} &= -\frac{\partial\vec{\mathbf{B}}}{\partial t} \\ \end{aligned} \right. \end{eqnarray}\]

こんなふうにマックスウェル方程式も余裕です。
アインシュタインの重力方程式も『\(R_{\mu\nu}-\frac{1}{2}g_{\mu\nu}R+\Lambda g_{\mu\nu}=-\frac{8\pi G}{c^4}T_{\mu\nu}\)』こんな感じでインライン表示できます。

highlight.jsのスクリプト追加

<!-- Begin highlight.js -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.6.0/build/styles/atom-one-dark-reasonable.min.css">
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.6.0/build/highlight.min.js"></script>
<script>hljs.highlightAll();</script>
<!-- End highlight.js -->

構文ハイライトライブラリ(ハイライター)は、デフォルトでrougeが使用されますが、ここでは軽量でかつ高速なライブラリであるhighlight.jsを使用します。
highlight.js usageにある通り、上記の様に<script>タグと<link>タグを追加します。 使用するハイライトスタイルは<link>タグで設定します。

rougeではJekyll側で構文ハイライト処理を行いますのでブラウザ側の負荷は少ないのですが、その反面色分けのための<span>タグが、本体のコードより多く挿入され、結果としてファイル容量が大きくなります。(htmlソースコードのデバッグする時に凄い邪魔)

そんなこともあってブラウザの負荷が若干かかりますが、ブラウザ側で構文ハイライトを行うhighlight.jsを使用しています。

kramdown:
  syntax_highlighter_opts:
    disable: true   # rougeを無効化

デフォルトのrougeを無効化するには、上記のように_config.ymlに設定する必要があります。

コードブロックの微調整

pre {
    background-color: $body-background-color;
}

.content {
    pre {
        padding: 0.2em;
        &[data-title]::before{
            content: attr(data-title);
            margin: 0em 1.0em;
            padding: 0.4em 0.3em 0.2em;
            color: $white;
            background: $grey;
        }
    }
}

コードブロックのスタイルにちょっと手を加えます。
技術系ブログサイトのQiitaでは、コードブロックの頭にコードの説明をするタイトルをつけることができます。それと同じ様なものを実装してみました。

```html
<div id="sample">
    <a href="/">sample link</a>
</div>
```

何も指定しないと、上のような普通のコードブロックになります。

```html
<div id="sample">
    <a href="/">sample link</a>
</div>
```
{: data-title="コードブロックサンプル"}

コードブロックに{: data-title="文字列"}という属性をインライン付加すると、上の様なタブ表示になります。

```html
<div id="sample">
    <a href="/">sample link</a>
</div>
```
{: .hljs data-title="コードブロックサンプル"}

属性にhighlight.jsのクラスhljsを追加してスタイルの色情報を継承することで、上の様な埋め込みタイトル風の表示にすることができます。

キートップ風スタイル

kbd {
    display: inline-block;
    vertical-align: text-top;
    margin: 0;
    padding: 0.2em 0.5em 0.2em 0.5em;
    font-family: $family-monospace;
    font-size: 92%;
    line-height: 1.0;
    color: #202020;
    background-color: #E0E0E0;
    border: 1px solid #606060;
    border-radius: 3px;
    box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.5), 1px 1px 1px rgba(255, 255, 255, 0.3) inset;
    white-space: pre-wrap;
}

キーボード操作のなどの説明の際用いられる<kbd>タグにスタイルを追加します。

Windowsでは<kbd>Ctrl</kbd> + <kbd>R</kbd>で、Macでは<kbd>&#x2318;cmd</kbd> + <kbd>R</kbd>でリロードします。

WindowsではCtrl + Rで、Macでは⌘cmd + Rでリロードします。

文字列を<kbd>タグで囲むだけで、上のようなキートップ風に表示させることができます。

貼り付けイメージに影追加

.content {
    img.dropshadow {
        -webkit-filter:drop-shadow(1px 3px 5px rgba(0, 0, 0, 0.4));
        -moz-filter:drop-shadow(1px 3px 5px rgba(0, 0, 0, 0.4));
        -ms-filter:drop-shadow(1px 3px 5px rgba(0, 0, 0, 0.4));
        filter:drop-shadow(1px 3px 5px rgba(0, 0, 0, 0.4));
    }      
}

デフォルトだと画像を貼るとベタ貼り感ハンパないので、影を落として柔らかくします。
box-shadowじゃなくdrop-shadowを使っているので、アルファで切り抜いた画像でも正しく影をつけられます。

使用する場合は、{:.dropshadow}という属性を次のようにインライン付加します。

![影付ききつねさん](/img/20220904_favicon.png "影付ききつねさん"){:.dropshadow}

普通のきつねさん 影付ききつねさん

左が影なし。右が影あり。

引用をモダンスタイルに

.content {
    blockquote{
        position: relative;
        padding-left: 45px;
        background-color: $white;
        border: 0px;
        box-shadow: 2px 2px 6px hsla(0, 0%, 80%, 1.00);
        &::before{
            content: url(/assets/img/quote.png);
            position: absolute;
            top: 10px;
            left: 10px;
        }
        cite{
            margin-top: 0.5em;
            text-align: right;
            display: block;
        }
   }
}

デフォルトだと左側にボーダーだけのレトロな引用スタイルなので、よく見かける引用符つきのスタイルに変更します。
引用符はこちらの画像を使用しています。引用符 (但しアスペクト比を若干変更しています。)

引用符の画像はblockquoteを基準に、絶対位置で指定しています。それに合わせてblockquoteのパディングを調整しています。その他、引用元記述<cite>を右寄せになる様に変更します。

> 文頭に>を置くことで引用になります。複数行にまたがる場合には改行の都度>を置く必要があります。  
> 引用の中に引用を入れ子にすることができます。また、引用中で**Markdown**を使用することもできます。  
> 引用元を記載する場合は、引用元記述を<cite>タグで囲ってください。
> <cite>引用元:xxxxxxxxxxxx</cite>

上のmarkdown記述は次のようになります。↓

文頭に>を置くことで引用になります。複数行にまたがる場合には改行の都度>を置く必要があります。
引用の中に引用を入れ子にすることができます。また、引用中でMarkdownを使用することもできます。
引用元を記載する場合は、引用元記述を<cite>タグで囲ってください。 引用元:xxxxxxxxxxxx

付箋風メッセージブロック

@mixin dl-mixin($char-color, $border-color, $bg-color, $content) {
    margin-left: 1.5em;
    margin-right: 2em;
    padding: 0.5em 1.5em 0.75em 1em;
    color: $char-color;
    border-left: 0.3em solid $border-color;
    background-color: $bg-color;
    border-radius: 3px;
    position: relative;
    box-shadow: 2px 2px 6px hsla(0, 0%, 80%, 1.00);
    > dt {
        font-weight: bold;
        font-style: normal;
        margin-top: inherit;
        padding-left: 1em;
        &::before {
            content: $content;
            font-size: 3em;
            font-weight: 900;
            font-family: 'Font Awesome 5 Free';
            color: $border-color;
            opacity: 0.3;
            position: absolute;
            margin-left: -0.5em;
            margin-top: -0.2em;
        }
    }
    > dd {
        margin-left: 1.5em;
        margin-bottom: 0;
        > ul {
            margin: 0 0 0 0.5em;    // リーダーを行頭ツライチに
            padding-left: 0.5em;
        }
        li + li {
            margin-top: 0em;        // リスト表示をコンパクトに
        }
        strong {
            color: inherit;
        }

    }
}

dl.note   { @include dl-mixin($grey-dark   , $grey   , $grey-lightest, '\f303'); }
dl.tip    { @include dl-mixin($success-dark, $success, $success-light, '\f058'); }
dl.info   { @include dl-mixin($info-dark   , $info   , $info-light   , '\f05a'); }
dl.warning{ @include dl-mixin($warning-dark, #ffbc6b , $warning-light, '\f071'); }
dl.caution{ @include dl-mixin($danger-dark , $danger , $danger-light , '\f05e'); }

補足事項などを目を引きたい場合、付箋風メッセージブロックで状況に合ったスタイルで表現することができます。
定義リストをベースに、クラス属性ごとにスタイルシートで外観を装飾しています。

具体的には、親要素のdlを基準にしてFontAwesomeのアイコンを半透明化して絶対位置で貼り付けて、あとはそれに合わせて文字の位置をパディングやマージンで調整しています。
それとメッセージブロック内でリスト表示を使用すると行間が開きすぎるので、コンパクトになるように調整します。

あとは、それぞれのクラスに合わせて配色とアイコンを設定しています。(scss@mixinはこういう時に使うとすごく便利。)

メッセージのタイトル
: 定義リストに属性`{:.note}`を付加することで、この様な付箋スタイルのメッセージブロックにすることができます。  
  行末に半角空白を2つの後改行することで、複数行に分けて書くこともできます。
{:.note}

↓こんな感じなります。

メッセージのタイトル
定義リストに属性{:.note}を付加することで、この様な付箋スタイルのメッセージブロックにすることができます。
行末に半角空白を2つの後改行することで、複数行に分けて書くこともできます。
確認
定義リストに属性{:.tip}を付加するとこうなります。
情報
定義リストに属性{:.info}を付加するとこうなります。
注意
定義リストに属性{:.warning}を付加するとこうなります。
警告
定義リストに属性{:.caution}を付加するとこうなります。

字下げの微調整

.content {
    &>p, &>dl, &>table, &>blockquote, &>pre{
        margin-left: 1em;
        margin-right: 1em;
    }
    &>ul, &>ol{
        margin-left: 3em;
    }
}

本文のコンテンツを見やすくするために、字下げで調整します。
(レスポンシブルデザインでは好まれませんが…)

記事の冒頭に投稿日と更新日を追加

<div class="content">
    <p class="post-date">
      <!-- 投稿日、更新日フォーマット変更 -->
      投稿日: {{ page.date | date_to_xmlschema | date: "%Y年%m月%d日 %H:%M %Z" }}
      {%- if page.last_modified_at -%}
        <br>更新日: {{ page.last_modified_at | date_to_xmlschema | date: "%Y年%m月%d日 %H:%M %Z" }}
      {%- endif -%}
    </p>
    <!-- タグ表示位置変更 -->
    <div class="tags">
      {% for tag in page.tags %}
        {% include tag.html tag=tag style="is-info is-light is-medium"%}
      {% endfor %}
    </div>
  
    {% if page.series %}
        {% include series.html %}
    {% endif %}

    {{ content }}
</div>

{% include post-nav.html %}     <!-- 記事ナビゲーションボタンのためにこれを追加 -->

{% unless site.hide_share_buttons %}
{% include share-buttons.html %}
{% endunless %}

{% if site.disqus.shortname %}
  {% include disqus.html %}
{% endif %}

投稿日だけでなく更新日も表示するようにします。それに合わせて日時のフォーマットを変更します。
更新日を格納する変数はなんでもいいのですが、last_modified_atという変数は、プラグインのjekyll-feedjekyll-sitemapでも更新日として参照されているのでそれに倣います。

日時フォーマットは"%Y年%m月%d日 %H:%M %Z"として、日本で標準的な並び順と末尾にタイムゾーンを略語表記で表示させます。しかし、なぜか更新日の方だけタイムゾーンがうまく表示できません。なので、一旦date_to_xmlschemaでISO8601形式に変換してから、再度フォーマット変換することでこの問題を回避しています。

ついでにタグの位置を記事末尾から、投稿日/更新日の直後に変更しています。

あと次の項目で説明しますが、記事ナビゲーションボタンを記事本文直後に追加します。

.content{
    .post-date {
        font-family: $family-monospace;
        font-size: $small-font-size;
        line-height: 1.2em;
    }
}

投稿日/更新日をコンパクトに表示するためにスタイルを調整します。

記事ナビゲーションボタンの設置

<div class="post-nav">
    <a class="pre-post {% unless page.previous %} is-invisible {% endunless %}" href="{{ page.previous.url }}">
        <div class="pre-arrow"><i class="fas fa-chevron-left"></i></div>
        <div class="pre-title">
            <div>Previous Post</div>
            <div><strong>{{ page.previous.title }}</strong></div>
        </div>
    </a>
    <a class="next-post {% unless page.next %} is-invisible {% endunless %}" href="{{ page.next.url }}">
        <div class="next-title">
            <div>Next Post</div>
            <div><strong>{{ page.next.title }}</strong></div>
        </div>
        <div class="next-arrow"><i class="fas fa-chevron-right"></i></div>
    </a>
</div>
div.post-nav {
    display: flex;
    justify-content: space-between;
    height: auto;
    flex-wrap: wrap;
    .pre-post, .next-post{
        width: 300px;
        height: 5em;
        margin: 0.3em;
        display: table;
        border-collapse: collapse;
        color: $primary-dark;
        .pre-arrow, .next-arrow{
            display: table-cell;
            background-color: $primary;
            vertical-align: middle;
            text-align: center;
            color: findColorInvert($primary);
            width: 1.5em;
        }
        .pre-arrow {
            border-radius: 5px 0 0 5px;
        }
        .next-arrow {
            border-radius: 0 5px 5px 0;
        }
        .pre-title, .next-title{
            display: table-cell;
            vertical-align: middle;
            background-color: lighten($primary, 35%);
            padding: 0 0.5em;
            strong {
                padding: 0.5em;
            }
        }
        .pre-title{
            text-align: left;
            border-radius: 0 5px 5px 0;
        }
        .next-title{
            text-align: right;
            border-radius: 5px 0 0 5px;
        }
    }
}

このテーマには「前の記事」「次の記事」のようなナビゲーションはついていないので自作しました。
記述が長いだけで何も難しいことはしていません。基本的にボタンの配置と色の指定と位置決めをしているだけです。

_include/post-nav.htmlでは、前記事/後記事それぞれのアンカータグを配置して、リンク先がない場合非表示になるようにしています。

_scss/mystyle.scssでは、前述のアンカータグにボタン風のスタイル付けをしています。二つのボタンはflexboxを使って横並びに配置しています。ボタン自体はdisplay: table, table-cellを用いて<div>要素を一体化させています。

このdisplay: tableを使うと<div>や<p>などのブロック要素をテーブルセルとして扱うことができ、要素内のテキストはtext-align:vertical-align:で横および縦方向の揃え方を指定できて便利です。

どのように表示されるかは、この記事の一番下を見てください。↓

IALについて

最後に、何度も度々出てくる{: xxxx}について説明します。

これはIAL(Inline Attribute Lists)と呼ばれるもので、Markdownレンダラーが生成する要素に新たな属性を付加することができます。

注意
IALは、Jekyllの標準Markdownレンダラーであるkramdownの方言で、PHP Markdown ExtraMarukuの影響を強く受けたとされる機能です。なので他のレンダラーでは使用できない場合があるので注意してください。

IALには大きく分けて二通りあり、一つはインラインレベル要素に対してのIALと、もう一つはブロックレベル要素に対してのIALです。

インラインレベル要素に対してのIAL

このようなmarkdown記述は、

例えば**このように**{:style="color: red;"}直接スタイルを設定できます。
[link](sample.html){:target="_blank"}

レンダラーによって次のように解釈されます。

例えば<strong style="color: red;">このように</strong>直接スタイルを設定できます。
<a href="sample.html" target="_blank">link</a>

この時注意が必要なのは、インラインレベル要素の直後にIALを記述する必要があります。
空白や改行や文字を挟むことはできません。余分な文字列があるとIALとは解釈されず、IALがそのまま出力されてしまいます。

ブロックレベル要素に対してのIAL

このようなmarkdown記述は、

> 引用はブロック要素になります。  
> IALで属性を付加することが可能です。
{:id="myid"}

```c
#include<stdio.h>
```
{:class="myclass"}

レンダラーによって次のように解釈されます。

<blockquote id="myid">
    <p>引用はブロック要素になります。<br/>IALで属性を付加することが可能です。</p>
</blockquote>

<pre class="myclass">
    <code class="language-c">
        #include<stdio.h>
    </code>
</pre>

この時注意が必要なのは、ブロックレベル要素の直前あるいは直後の行頭にIALを記述する必要があります。
また、前述の通りIALは前置型後置型どちらでも使用可能ですが、前置型を使用した場合、IALの前にブロックレベル要素が来ないようにしてください。後置型が優先されるので前にあるブロック要素に属性が付加されてしまいます。

インラインレベル要素IAL、ブロックレベル要素IALどちらでも、以下のような省略表記が可能です。
{:class="myclass"}は、{:.myclass}と省略可能です。また{:id="myid"}は、{:#myid}とすることもできます。


Previous Post
jekyllのカスタマイズ(スタイル編)

Share

最近の投稿

gitの入れ子管理
gitの入れ子管理

gitのリポジトリは入れ子にして管理できます。

jekyllの変数のデータ構造
jekyllの変数のデータ構造

jekyllの変数のデータ構造を紹介します

jekyllのカスタマイズ(その他)
jekyllのカスタマイズ(その他)

その他の設定を紹介します