HTML
CSS
bem
CSS設計

HTML/CSS初心者から中級者への一歩を踏み出す練習課題 その4

その3では、与えられた課題をついにクリアし、しかも急な追加要求までこなすことができました。
これであなたも立派なフロントエンドエンジニア、とはすぐにはいきません。

IE11での評価はしましたか?

さあIE対応だ

IE11のサポートが切れた未来にこれを読んでいる人にこの記事は必要ありません。
きっと素敵な世の中になっていることでしょう。

さて2018年現在、IE11をサポートしなければいけない現場がほとんどでしょう。
もしサポートはChromeだけでいいよと言われている幸運な人がいたらその人もこの記事を読む必要はありません。
これまではChromeなどのモダンブラウザで表示確認をしてきたと思いますが、今度はWindowsのIE11で確認してみてください。  

きっとどこか崩れたでしょう?
筆者のコード例も見事にIE11で崩れています。PCサイズで確認していますが、まるでSP時のような縦積みになってしまっています。
ie.png

みなさんも自分のコードを直してみましょう(もし崩れてる部分が1つもない人はすごいです。初心者なんて謙遜せず胸を張って中級者以上を名乗ってください)。
もしどうしても直すことができなければJavascriptで直すことも考えてみてください。

IEバグと戦う

筆者の作成例ではflexboxを多用していますが、IEにはflexboxのバグがたくさんあります。
flexboxのバグに立ち向かう(flexboxバグまとめ)

今回ひっかかったバグ以下です。

  • flexのショートハンドでflex-basisにcalcを使うとが正しく計算されない。
  • flexbox要素がborderやpaddingを持つとflex-basisが正しく計算されない

flexのショートハンドでflex-basisにcalcを使うとが正しく計算されない

flex: 0 0 calc(33.3% - 20px);

このようにショートハンド形式でflex-basisにcalcを使うとIEでは崩れてしまいます。
解決策はショートハンドでなくプロパティをそれぞれ記載すること。

style.css
.panels__item {
    flex-grow: 0;
    flex-shrink: 0; 
    flex-basis: calc(33.3% - 20px);
}

flexbox要素がborderやpaddingを持つとflex-basisが正しく計算されない

解決策は2つ

  • paddingとborderの値をflex-basisの値に含ませる。
  • flexbox要素にborderやpaddingを設定せず小要素側に持たせる。

前者では横並びにするクラスとパネルのクラスが分離できず設計上好ましくないです。
よって後者の方針で解決します。

paddingは.panels__itemの子要素に持たせることでIEでも正しく表示されるようにします。
そのために.panel.panels__itemと分離します。
単純に分離すると高さが揃わなくなるので、.panelheight: 100%;を追加します。
一昔前はこれはうまく機能しなかったのですが、仕様が変わったおかげで簡単にflexboxの孫要素の高さを揃えることができるようになりました。stackoverflow: flexboxの孫要素にheight:100%が効かない理由はなぜですか

borderも.panelをflexboxの孫要素にしたおかげでflex-basisの計算に影響しなくなりました。

どうしてもflexboxの子要素にborderをつけないといけない場合は、borderをもたせたafter要素をposition: absoluteで浮かせ、パネルの全域に広げることで見栄えを再現しつつIEでも正しく表示されるようになります(ハックがすぎているキライはある)。

flexboxの子要素にborderをもたせる例

index.html
<li class="panels__item panel">
      <div class="panel__content">
          <div class="panel__content__icon">
              <img src="dummy.png" alt="ダミー">
          </div>
          <div class="panel__content__item">
              <div class="panel__title">タイトル1</div>
              <div class="panel__text">
                  テキストテキストテキストテキストテキストテキストテキストテキストテキストテキスト
              </div>
          </div>
      </div>
      <div class="panel__footer">
          <ul>
              <li>補足補足補足補足</li>
              <li>補足補足</li>
          </ul>
      </div>
</li>
style.css
.panel {
    position: relative;
    background-color: #fff;
    border-radius: 8px;
}

.panel::after {
    content: '';
    display: block;
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    border: solid 1px #cecece;
    border-radius: 8px;
}

.panel--highlight::after  {
    border: solid 2px #3176d5;
}

.panel__content {
    padding: 20px 20px 0;
}

.panel__footer {
    padding: 0 20px 20px;
}

コード例

これで無事課題をすべてクリアすることができました。
ここまでやって以下の目標を達成できたでしょうか

  • BEM記法に慣れてもらう。
  • パーツ同士が疎結合なクラス設計を意識できるようになる。
  • 保守性を大事にするマインドを身につけてもらう。

全部終えた上で、もう一度はじめから作り直してみるのもいい練習となるでしょう。
この課題を足がかりに経験を積んで自分なりのノウハウを増やして中級者、上級者へと駆け上ってください。

素敵なフロントエンドエンジニアライフを!