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 標準テーマでは content
と sidebar
の width
がパーセント指定されている。つまりページ幅によって拡縮されるのだが Redmine 3.2 でレスポンシブ対応されたことも踏まえると、
- 標準時の幅は
content
可変、sidebar
固定にする - レスポンシブ レイアウトの幅になったら
sidebar
が消える
というにしたかった。これを実現するなら標準テーマのように float
レイアウトはネガティブ マージン、より好ましい方法としては position:relative
と absolute
を組み合わせるか Flexbox になるだろう。
しかし position:relative
するには DOM 階層の追加が必要。そのため基本的に CSS で外観指定する Redmine テーマには不向き。theme.js
から DOM 操作する手もあるけど静的に定義された大領域を変更するのは好ましくない。また Flexbox を採用するのも Web ブラウザー対応の現状を踏まえるに時期尚早。そのためネガティブ マージンを検討したが、これはこれで半端な対応になる。
結局 sidebar
幅の固定化は見送ることにした。そのかわり content
、sidebar
とそれを包含する main
の関係を整理。標準だと main
に背景色が設定されて sidebar
の子が上にのるような設計なのだが sidebar
を外観上のサイズと一致させ、それ自体で背景色を変更できるように修正。
このあたりは Redmine テーマの CSS をいじったことがないとピンと来ないかもしれない。
その他、バグ修正など
その他、以下の対応を実施。
- Firefox 以外で表示したときヘッダー部分と
main
領域間にできる空白を削除 - プロジェクト設定などでフォームのラベルが見切れる問題を修正
- Redmine 3.2 のチケット一覧でプログレスバー進捗率グラフが欠ける問題を修正
2 と 3 は minimalflat2 の fork 先で修正されていた問題を参考にした。
3 については盲点である。Redmine 3.2 未満だとチケット一覧内のプログレスバー用 <table>
は直に style
属性で width
を指定されていたが 3.2 で廃止。以降は CSS で設定する必要がある。