feed

2013年11月23日, 編集履歴

固定配置(position: fixed)を使う前によく考えよう

 ブログに表示するSNS連携ウィジェット等にposition: fixed;を指定して固定位置に配置しているものを最近よく見かける。

 しかしながらposition: fixed;を使う場合は慎重になるべきである。
 マージンを取った余白に配置しているつもりかもしれないが、ウィンドウサイズによってはウィジェットが本文にカブってしまっていることがよくある。制作者が想定しているウィンドウサイズで皆が閲覧しているわけではないのだ。スクロールさせたりウィンドウ幅を広げたりして、なんとか読めるようになることもあるが、手間であるし非常に読みづらい。酷いときはブラウザをフルスクリーン表示させて横幅1280ピクセルとってもまだ本文にカブってしまうブログも複数見かける。

 また、始めは非表示、あるいは最小化されていたのに、本文末尾付近までスクロールするとにょきっとアニメーション付きで大きくなるウィジェットも見かける。たいていは本文を読みきる前ににょきにょきと現れて本文を隠す。隠さずとも急に現れることで視線を奪い、本文を見失わせる。

 ウィジェットだけではない。固定配置しているヘッダメニューやフッタメニューも同様である。頻繁に用いるわけでもないメニューがウィンドウ内の場所を占有し、本文のスペースを奪う(ツール的なウェブアプリケーションの場合は可)。

 本文が大事なのであって、ウィジェットやメニューは添え物にすぎない。あったら便利程度のものが主客転倒し本文を読みづらく、あるいはまったく読めなくする。本文にカブる危険を冒してまで固定位置に配置する価値のあるものかどうかを一度よく考えてみるべきだと思う。

 SNS連携ウィジェットなどはタイトル見出し付近、あるいは本文末尾に通常配置すれば十分に用を足す。ヘッダメニューは、本文が短ければわざわざ固定配置するまでもなく、ちょっとスクロールすれば一番上まで到達できるし、本文が長い場合はメニューでスペースを占有させるより本文領域を広くとった方が読みやすくなる。

 固定配置を使う前に、それが本当に必要なものなのかよく考える必要があるだろう。

2013年11月21日, 編集履歴

Jekyllで簡易タグ一覧ページを作る(2013年12月8日追記)

 ブログ記事にタグを設定し、タグ一覧ページを作った(2013年12月8日追記:「Jekyll製ウェブサイトに簡易検索機能を実装する」にて実装した検索機能に統合したためdeprecated)。

Front-matterでタグを付ける

 Jekyllでブログ記事を書くときに、Front-matterにタグを埋め込むことができる。この記事の場合だと、Front-matterは以下のようになっている。

---
layout: post
title: Jekyllで簡易タグページを作る
tags: jekyll github
---

 tags:部分はスペース区切りかYAMLフォーマットのリスト形式で複数のタグを設定することができる。

タグ一覧ページを作る

 タグを付けたら当然その一覧ページが欲しいが、Jekyllにはタグ一覧ページを出力する機能はついていない。プラグイン(Jekyllはプラグインで機能拡張ができる)でそういうのがあるのかもしれんけど、GitHub Pages上でビルドする場合はプラグインは使えないので自分でなんとかするしかない。

 あまり複雑なことをやろうとすると深みにはまるので、シンプルにいく。
 まずはタグ一覧ページとして/blog/tags.htmlファイルを作成する。この中にブログ記事中で設定されているタグと、そのタグが付けられた記事を羅列する。今回は以下のような記述を/blog/tags.htmlに追加した。


{% for tag in site.tags %}
<article>
  <h1 id="tag_{{ tag[0] }}">{{ tag[0] }}</h1>
  <ul>
    {% for post in tag[1] %}
    <li><a href="{{ post.url }}">{{ post.title }}</a></li>
    {% endfor %}
  </ul>
</article>
{% endfor %}

 site.tagsには全タグの情報がハッシュとして入っている。キィはタグの文字列、値はそのタグが付けられた記事の配列になっている。

 Jekyll(Liquid)でハッシュを{% for %}文に掛けると、一時変数には各要素のキィ・値ペアが配列として渡される(インデックス0にキィ、1にその値)。上記の場合、{% for %}文の一時変数tagは配列になっており、tag[0]がタグ文字列、tag[1]がそのタグが付けられた記事情報の配列である。

 ここではタグ毎に記事へのリンク付きでタイトルをリスト表示している。これにてタグ一覧ページは完成。

各記事にタグ一覧ページへのリンクを付ける

 各ブログ記事にタグ一覧ページへのリンクを付ける。
 設定したタグの一覧を出力させるために、ブログ記事のテンプレートとしている_layouts/post.htmlに以下のような記述を追加した。


<nav id="tags">
  <h2>tags:</h2>
  <ul>
    {% for tag in page.tags %}
    <li><a href="/blog/tags.html#tag_{{ tag }}">{{ tag }}</a></li>
    {% endfor %}
  </ul>
</nav>

 page.tagsにその記事で設定したタグ文字列が配列で入っているので、これを使って{% for %}文を回す(注:site.tagsはハッシュ、page.tagsは文字列の配列である)。

問題点

 今回のタグ一覧ページは簡易的なものである。ひとつのページに、すべてのタグとタグが付けられた記事を羅列しているだけで、「JekyllのPagination設定」でやったようなページ分けもない。したがって、記事数が増えるごとにどんどん肥大化していくという問題がある。

 それほど頻繁にブログを更新するわけでもなし、増えてきたら増えてきたでまたそのとき考えるということで、今回はこれまで。

2013年11月20日, 編集履歴

GitHub Pagesでカスタム404ページを配置する

 このウェブサイトは現在GitHub Pagesでホストされている。

 なにも設定していない場合、404ページ——すなわち存在しないURLをリクエストされたときに表示するページは、GitHub Pagesのディフォルト404ページになる。ディフォルト404ページは、このウェブサイト自体とは直接関連のない情報を表示するだけなので、そのままでは都合が悪い。最低限、このウェブサイトのトップページへ誘導するリンクくらいは置いておくべきだろう。

 GitHub Pagesではもちろん、自分で404ページを用意することができる。参照情報はGitHub Pagesのヘルプ「Custom 404 Pages」にある。
 一言で言えば、ウェブサイトを管理するリポジトリィのルートに404.htmlというファイルを配置すれば良い。そうすれば、存在しないURLへのリクエストが発生したときにそのファイルが表示されるようになる。

 というわけで404.htmlを配置した。

2013年11月18日, 編集履歴

Jekyllの最新記事と関連記事

 Jekyllのsite変数はpostsrelated_postsメンバを持つ。postsは全ブログ記事が新しい順に入っており、related_postsは処理中のブログ記事に関連している記事が最大10件分入っている。

<ul>
  {% for post in site.posts limit:5 %}
  <li><a href="{{ post.url }}">{{ post.title }}</a></li>
  {% endfor %}
</ul>

のように書くと、最新のブログ記事へのリンクを5件、リストに出力する。ポイントはfor文のlimit:5site.postsには全記事分の情報が入っているので、limit:5のようにすると5件に制限できる。

 related_postsも同じような使い方ができる。しかし、ディフォルトではrelated_postsには単に最新記事が10件分入っているだけである。ビルド時に--lsiオプションを付けると精度が上がるらしいが、どういうアルゴリズムになっているのかはよく解らない。さらにこのウェブサイトはGitHub Pages上でのビルドとホストしているが、その場合は--lsiオプションは使えない(ローカルでビルドして、その生成物をアップロードする方法ならば可)。
 ディフォルトでも、せめて同じカテゴリィや同じタグを付けた記事が入っていれば使いようがあるのだが……。

2013年11月17日, 編集履歴

JekyllのPagination設定(2013年11月30日追記)

 JekyllのPaginationとは、一ページ中にブログ記事がいくつか羅列してあり、一番下まで行くと「前の記事へ」「次の記事へ」などと前後の記事羅列ページへのリンクが貼ってあり、当該前後ページでまた記事が羅列されているという、よくあるアレである。

_config.ymlの設定

 Paginationを設定するにはまず_config.ymlに、

paginate: 5
paginate_path: "blog/page:num"

のように記述する。上記の場合、一ページ中に羅列される記事数は5件。paginate_path: "blog/page:num"で指定したblogディレクトリィの中にあるindex.htmlファイルが最初のページとなる。blog/index.html内では変数paginatorを使い、記事羅列ページを作成する(したがって、blog/index.htmlはJekyll(Liquid)の変換対象ファイルでなければならないので、YAML Front-matterが必要となる)。
 以降のページは、そのblog/index.htmlがテンプレート的な扱いとなり、blog/page2/index.htmlblog/page3/index.html、…と作られる(page1は作られないことに注意)。

記事の出力

 paginatorposts変数を持っており、そのページ内で羅列される件数分(この場合は5件)の記事情報が保持されている。blog/index.html内で以下のように記述すれば、5件分の記事が出力される。

{% for post in paginator.posts %}
<article>
  <p class="date">{{ post.date | date: "%Y年%m月%d日" }}</p>
  <h1><a href="{{ post.url }}">{{ post.title }}</a></h1>
  {{ post.content }}
</article>
{% endfor %}

 上記は各記事の全文を出力している。全文が必要ない場合はpost.contentの代わりにpost.excerptを使う。

 blog/page2/index.html以降ではblog/index.htmlがテンプレート的に使われて同じ形態のファイルが出力される。paginator.postsには、そのページが出力するべき記事情報が入っている。全記事数が12件でpaginate: 5指定の場合、最初のページ(blog/index.html)では最新5件分、2ページ目(blog/page2/index.html)で次の5件分、3ページ目(blog/page3/index.html)で最後の2件分がpaginator.postsに入っている。paginatorが持つその他の変数も出力するページにあわせて変化する。

前後ページへのリンク出力

 前後ページへのリンクにはpaginator.previous_pagepaginator.next_pageを使う。これらには前後のページ番号(なければnil)が入っている。以下のようにblog/index.htmlに書いた場合、前後ページへのリンクのリストが出力される。

<ul>
  {% if paginator.previous_page %}<li><a href="/blog/{% if paginator.previous_page != 1 %}page{{ paginator.previous_page }}/{% endif %}">前の記事</a></li>{% endif %}
  {% if paginator.next_page %}<li><a href="/blog/page{{ paginator.next_page }}/">次の記事</a></li>{% endif %}
</ul>

 ひとつ注意が必要なのは、2ページ目以降のパスはblog/page2/index.html、…であるが、最初のページのパスはblog/index.htmlであって、blog/page1/index.htmlではないということである。したがって、paginator.previous_page1のときとそれ以外で処理を分ける必要がある。

追記(2013年11月30日)

 前節「前後ページへのリンク出力」について、previous_pageは日付上では新しい方向のページ番号を、next_pageは古い方向のページ番号を意味する。前節のように、変数名に合わせてそれぞれのリンク文字列を「前の〜」「次の〜」とすると、(考え方にもよるが、私は)気持ち悪い。
 なので、リンク文字列をそれぞれ「新しい〜」「古い〜」と改めた。


<ul>
  {% if paginator.previous_page %}<li><a href="/blog/{% if paginator.previous_page != 1 %}page{{ paginator.previous_page }}/{% endif %}">新しい記事</a></li>{% endif %}
  {% if paginator.next_page %}<li><a href="/blog/page{{ paginator.next_page }}/">古い記事</a></li>{% endif %}
</ul>