アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

Redmine テーマ minimalflat2 v1.1.0 リリース

年始のウォーミングアップとして Redmine テーマ minimalflat2 を更新。前回 Redmine 3.2 対応により大きな変更が入ったのに Minor バージョンを更新していなかったので今回は改めて v1.1.0 とした。

以下に変更点などをまとめる。

ツールバーのボタンをダーク系の配色に変更

ツールバーとは、チケットや Wiki 編集画面の texarea 上部のこと。ここに太字や斜体などのボタンが並んでいる。

エディタのツールバー

Redmine 3.2 で追加されたレスポンシブ レイアウトによるボタンも対象にした。3.2 標準の CSS だとコンテンツ右上にあるメニューを枠線で囲んでボタン風に見せている。レスポンシブ レイアウト時のサイドバーはヘッダーにあわせてダーク系にしているので、ボタンもそのようにした。

モバイル表示のボタン

通常のレイアウトも同じ外観にするか悩んだが標準レイアウトだと文字メニューのほうがしっくりくるため、そのままにしている。

ツールバーのボタン変更を JavaScript から CSS に移行

これまでツールバーのボタン変更は theme.js から動的に処理していた。標準のボタンをアイコン フォントへ置き換えるため DOM 操作で <i> を挿入したというのがその理由。しかしこの方法には問題がある。

標準のツールバーは jstoolbar.js で設定され、その後に theme.js が実行されることを利用してカスタマイズしていた。しかしチケット作成画面でステータスなどを変更すると jstoolbar.js が再実行されて theme.js による変更が無効化されてしまう。このタイミングをフックして theme.js も再実行すれば対応できそうだが、起点となる処理が増減する可能性を考慮すると危険である。

そのためカスタマイズを theme.js から CSS へ移行させた。CSS は DOM 操作に頼れないため元の DOM 範囲で対応しなければならない。そこでまずは DOM を分析。Redmine 3.2 のチケット作成画面におけるツールバーだと以下のように構成されている。

<div class="jstElements">
  <button title="強調" class="jstb_strong" tabindex="200" type="button"><span>強調</span></button>
</div>

基本的な階層は .jstElements button span。標準では button の各種クラスに背景画像としてアイコンを割り当てている。これをフォントにするなら button を下地としてその内部に描画したいので <span> に対する before を設定するのがよさそう。

標準 CSS は jstoolbar.css となりテーマの application.css の後に読み込まれる。よって上書きしたいプロパティへ !important を指定しつつ、こんな感じで定義。

@import "./common/Color.styl"

.jstElements {
  button {
    border solid 1px color_indigo !important
    border-radius .2em !important
    background none color_indigo !important
    color color_white !important
    width 28px !important
    height 28px !important
    margin-right .2em !important
    margin-bottom .2em !important
    padding 0 !important
    font-family sans-serif !important
    font-size 13px !important
    line-height 28px !important
    letter-spacing 0 !important
    vertical-align bottom

    &:hover {
      opacity .7
    }

    /* ボタン内の非表示テキスト */
    span {
      display inline-block !important
      overflow hidden
      width 13px
      height 26px
      color transparent
    }

    /* ボタンごとのアイコン設定 */
    &.jstb_strong span:before {
      icon( icon_edit_bold, color_white )
      margin-right 0
    }
  }
}

<span> の幅をボタン全体の半分以下、高さを範囲内 + 余白ほどにする。これと overflow:hidden を組み合わせることで <span> 内のテキストがちょうどよい位置で裁ち落とされる。色を透明にすることで before 用レイアウトだけ保持したまま非表示になる。

この設定を前提として before へアイコン フォントを指定。このテーマでは CSS 開発に Stylus を利用しているためアイコン指定は Mix-In 化されたものを流用できるようにしてある。

icon( content, color ) {
  font-family "icon"
  speak none
  font-style normal
  font-weight normal
  font-variant normal
  text-transform none
  line-height 1

  // Better Font Rendering
  -webkit-font-smoothing antialiased
  -moz-osx-font-smoothing grayscale

  content content
  color color
  margin-right .2em
}

content にアイコンの文字コード、color へ色を指定することで、よしなにアイコンを配置してくれる。

ツールバーのアイコンは IcoMoon を利用しているのだが H1 などのグリフはプリセットにない。そのため自作 SVG を追加。theme.js でカスタマイズしていたときは普通のテキストで H1 や C などと書き、文字サイズを調整してアイコンっぽく見せていた。しかしこの方法は Web ブラウザーのフォント設定に影響される。よって CSS 化と一緒にアイコン フォントすることにした。

<img>theme.js でアイコン フォントに置換しているのだけど、こちらは従来処理を継続することにした。<img><input> といった置換要素には before を設定できない。よって before 用に <img> を span に置換したり src 属性を書き換えるためには JavaScript 必須になる。

ユーザーのプロフィール画像を矩形から円形に変更

最近の Twitter やチャット クライアントでは、ユーザーのプロフィール画像を円形で表示するものが多い。これは矩形中心の Web サイトにおいてよいアクセントになるため採用。飽きたら矩形に戻すかもしれない。

コンテンツとサイドバーのレイアウト指定変更

Redmine 標準テーマでは contentsidebarwidth がパーセント指定されている。つまりページ幅によって拡縮されるのだが Redmine 3.2 でレスポンシブ対応されたことも踏まえると、

  • 標準時の幅は content 可変、sidebar 固定にする
  • レスポンシブ レイアウトの幅になったら sidebar が消える

というにしたかった。これを実現するなら標準テーマのように float レイアウトはネガティブ マージン、より好ましい方法としては position:relativeabsolute を組み合わせるか Flexbox になるだろう。

しかし position:relative するには DOM 階層の追加が必要。そのため基本的に CSS で外観指定する Redmine テーマには不向き。theme.js から DOM 操作する手もあるけど静的に定義された大領域を変更するのは好ましくない。また Flexbox を採用するのも Web ブラウザー対応の現状を踏まえるに時期尚早。そのためネガティブ マージンを検討したが、これはこれで半端な対応になる。

結局 sidebar 幅の固定化は見送ることにした。そのかわり contentsidebar とそれを包含する main の関係を整理。標準だと main に背景色が設定されて sidebar の子が上にのるような設計なのだが sidebar を外観上のサイズと一致させ、それ自体で背景色を変更できるように修正。

このあたりは Redmine テーマの CSS をいじったことがないとピンと来ないかもしれない。

その他、バグ修正など

その他、以下の対応を実施。

  1. Firefox 以外で表示したときヘッダー部分と main 領域間にできる空白を削除
  2. プロジェクト設定などでフォームのラベルが見切れる問題を修正
  3. Redmine 3.2 のチケット一覧でプログレスバー進捗率グラフが欠ける問題を修正

2 と 3 は minimalflat2 の fork 先で修正されていた問題を参考にした。

3 については盲点である。Redmine 3.2 未満だとチケット一覧内のプログレスバー用 <table> は直に style 属性で width を指定されていたが 3.2 で廃止。以降は CSS で設定する必要がある。