ons-toolbarに配置したons-iconの位置ずれ

ons-toolbarにons-iconを配置すると、アイコンがツールバーの上下中央から少しずれてしまうことがあります。

HTML

<ons-page id="first-page">
  <ons-toolbar>
    <div class="center">Page 1</div>
    <div class="right">
      <ons-toolbar-button onclick="">
        <ons-icon icon="fa-cog" size="lg"></ons-icon>
      </ons-toolbar-button>
    </div>
  </ons-toolbar>
</ons-page>

この位置ずれについて調べました。

Note

Onsen UIFont Awesomeのお話になります。

CSSスタイルの優先順位

突然ですが、まず最初にCSSスタイルの優先順位について確認しておきます。
スタイルの優先順位 — HTMLクイックリファレンスを参考にざっくりまとめてみました。

  • よりタグに近い、より後から読み込まれたスタイルが優先される
  • セレクタの種類による優先順位
    • idセレクタ>classセレクタ>タイプセレクタ>全称セレクタ
    • 要素を特定したidセレクタ・classセレクタは、要素を特定しないidセレクタ・classセレクタより優先される
    • 優先順位が同じになった場合は最後に指定したスタイルが適用される
  • !important を付けると最優先になる

こうゆうのは文章を追うよりも実際にコードを見たり動かしたりしたほうが覚えますよね。そこで確認の意味も含め、私が考えたCSSクイズを出題したいと思います。

div要素は何色になるでしょう?

全部で2問。答えはこのページに直書きしているので、なるべくスクロールせず答えを隠して考えてもらえたらと思います。

第1問

style.css

.hoge {
  background-color: blue;
}

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>CSS TEST</title>
  <style>
  .hoge {
    background-color: yellow;
  }
  </style>
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <div class="hoge" style="width:300px; height:300px;"></div>
</body>
</html>
第2問

external.css

.piyo {
  background-color: red;
}

style.css

.hoge {
  background-color: blue;
}

HTML

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>CSS TEST</title>
  <link rel="stylesheet" href="external.css">
  <link rel="stylesheet" href="style.css">
  <style>
  div {
    background-color: yellow;
  }
  </style>
</head>
<body>
  <div class="hoge piyo" style="width:300px; height:300px;"></div>
</body>
</html>

答えを隠すためにスペースを入れますね。

もういいかな …

さて、正解は …

どちらもです。当たりました?

第1問は優先順位を「インライン>外部スタイルシート」と覚えていると間違えてしまいます。

第2問はclass属性内のクラス名の記述順序は優先順位に無関係ということです。意外と説明されていないようですので間違えやすいのではと思いました(私は間違えてました)。

位置ずれの原因と対策

本題に入ります。
ons-iconコンポーネントのsize属性はアイコンの大きさを設定します。値はlg, 2x, 3x, 4x, 5x, およびピクセルで、それぞれFont Awesomeのクラス名に対応しています。

font-awesome.css

.fa-lg {
  font-size: 1.33333333em;
  line-height: 0.75em;
  vertical-align: -15%;
}
.fa-2x {
  font-size: 2em;
}
.fa-3x {
  font-size: 3em;
}
.fa-4x {
  font-size: 4em;
}
.fa-5x {
  font-size: 5em;
}

fa-lgクラスだけ特殊のようです。font-sizeを親のフォントサイズの33倍にし、line-heightをその0.75倍しています。line-height = fontsize(親) × 1.33 × 0.75 = fontsize × (4/3) × (3/4) = fontsize、ということでline-heightを親のフォントサイズに合わせているんですかね?で、それを親のbaselineの位置から親のline-heightの15%分を下げると。うんうん、なるほど、さっぱりわかりません。実際やってみるとうまくいきますし、今年は夏でもほんとオーサムということでFont Awesomeを信じることにします。

ここで、sizeを lg, 2x, 24px にして表示を比べてみます。

HTML

<ons-page id="first-page">
  <ons-toolbar>
    <div class="center">Page 1</div>
    <div class="right">
      <ons-toolbar-button onclick="">
        <ons-icon icon="fa-cog" size="lg"></ons-icon>
      </ons-toolbar-button>
    </div>
  </ons-toolbar>
</ons-page>

size=”lg”

size=”2x”

size=”24px”

sizeに lg を指定したときだけずれます!

Debug ToolでDOM構造を確認すると、ons-iconコンポーネントは展開されてons-iconクラス、fa-cogクラス、faクラス、fa-lgクラスが付与されています。

index.html

<link rel="stylesheet" href="lib/onsenui/css/onsenui.css">

<ons-icon icon="fa-cog" size="lg" modifier="material" 
class="ons-icon fa-cog fa fa-lg"></ons-icon>

次に、上記index.htmlでリンクされているonsenui.cssを見てみます。ここでは、最初のほうでfont-awesome.min.cssのインポートを行っています。

onsenui.css(最初のほう)

@import url("font_awesome/css/font-awesome.min.css");

そして、その後に各コンポーネントのクラス定義などが記述されています。

つまり、Font Awesomeのスタイルを読み込んでからOnsen UIのスタイルを読み込むことになります。

ここで、ons-iconコンポーネントに付与されているons-iconクラスとfa-lgクラスを比べてみます。

font-awesome.css(最初に読み込む)

.fa-lg {
  font-size: 1.33333333em;
  line-height: 0.75em;
  vertical-align: -15%;
}

onsenui.css(後に読み込む)

.ons-icon {
  display: inline-block;
  line-height: inherit;
  font-style: normal;
  font-weight: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

Font Awesomeのfa-lgクラスとOnsenUIのons-iconクラスを一緒に指定すると、fa-lgクラスのline-heightの値がons-iconクラスのline-heightの値で上書きされます。

これが位置ずれの原因でした。

対策として自作のstyle.cssでline-heightを再度定義したところ、無事、上下中央に配置されました。

style.css

.fa-lg {
  line-height: 0.75em;
}

前述の第2問と同じで「class=”ons-icon fa-cog fa fa-lg”」と記述されていても fa-lg クラスではなく ons-icon クラスが有効になります。私はそこのところを勘違いしていて、なぜだろうと悩みながらline-heightやmargin、vertical-alignなどをこねくり回していました。

複数のライブラリを併用しているときに不思議な現象に出会ったら、ファイルの読み込む順番やスタイルの優先順位を確認するとデバッグの効率がよくなるかもしれませんね。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA