service-tag コラム|トライベック
HUMAN INSIGHT CX
リサーチソリューション
コンサルティング
クリエイティブ・UX
制作・オペレーション
テクノロジー
データドリブン
マーケティング
サービスについて
オピニオン
トライベック広報
会社概要
社長メッセージ
経営理念
社名・ロゴの由来
トライベック・ニューノーマル
役員紹介
地図・アクセス

COLUMN

コラム

G・Iが執筆した記事一覧

プロダクション
2020年6月22日

classのシンプルなグリッドシステム

今やWebページのレイアウトメソッドとしてすっかり定着したグリッドデザイン。近年では、flex-boxやCSS gridの登場でますます使い勝手が良くなっていますね。一方で、マルチカラムレイアウトのためだけにBootstrapなどの大がかりなフレームワークを導入したり、複雑なCSSを書き起こしたりするのはちょっとめんどう。 12カラムグリッドシステムのイメージ そこで今回は、簡単なclassだけで手軽に3パート・レスポンシブのマルチカラムレイアウトを実現するシンプルなグリッドシステムを作ってみます。 いつも悩ましい多重class 広く利用されているコンポーネントフレームワークBootstrapにも、一般的な12分割タイプのグリッドシステムが搭載されています。たとえば「スマホは2カラム、タブレットは3カラム、PCは4カラムで」といったレイアウトをする場合、下のようにclassを記述します。 <div class="row"> <div class="col-6 col-md-4 col-xl-3"></div> <div class="col-6 col-md-4 col-xl-3"></div> <div class="col-6 col-md-4 col-xl-3"></div> <div class="col-6 col-md-4 col-xl-3"></div> </div> Bootstrapのグリッドシステムは「12を分母とする分数の分子」で列幅を指定するのが特徴で、指定方法こそ慣れれば問題ないものの、classがいくつも並ぶのはもう少しすっきりさせたい気がします。また、12分数で表現できない5カラムや8カラムといった列数が実現できないのも少し物足りないですね。 1クラスで書けたら簡単だけど…… シンプルにひとつのclassだけでメディア別に異なるカラム数を設定したい。たとえば上記の「スマホは2カラム、タブレットは3カラム、PCは4カラム」というレイアウトならば、 <div class="row"> <div class="col2-3-4"></div> <div class="col2-3-4"></div> <div class="col2-3-4"></div> <div class="col2-3-4"></div> </div> こんな風に1クラスで書けたら、直感的だし楽チンでよいのではないでしょうか(ハイフンで区切られた3つの数字には1~12の何を入れてもよい)。ついでに5カラム、7カラム、8カラムといった、12分割ルールでは割り切れなかった段組みにも対応できたらもっとすてきです。 パターンは5,184通り ですが、1クラスであらゆるレイアウトパターンを網羅しようとすると、 12×12×12×3=5184 OMG、5,184通りものスタイルを定義しなければいけません。 .col1-1-1 { width: 100%;} .col2-1-1 { width: 50%;} .col3-1-1 { width: 33.3333%;} : : .col12-12-10 { width: calc( 100% / 10 );} .col12-12-11 { width: calc( 100% / 11 );} .col12-12-12 { width: calc( 100% / 12 );} 5,184通りを列挙することじたいはExcelなどを使えばたやすいですが、このシステムだけのために5000行以上あるCSSをページに読み込ませるのは人道にもとる行為とのそしりをまぬがれません。もっと合理的な方法を考えましょう。 属性セレクタを使う 属性セレクタには、属性名、属性値の完全一致、前方一致、後方一致、部分一致など多様なマッチングオプションがあります。これをうまく活用すれば5,184種類のスタイルを賢く合理化できそうです。 ハイフンで区切られた3つの数字のうち、最初の数字は前方一致、真ん中の数字は部分一致、最後の数字は後方一致でマッチングさせます。 /* 前方一致・スマホ用 */ [class^="col1-"] { width: 100%;} [class^="col2-"] { width: 50%;} : : /* 部分一致・タブレット用 */ [class*="-1-"] { width: 100%;} [class*="-2-"] { width: 50%;} : : /* 後方一致・PC用 */ [class$="-1"] { width: 100%;} [class$="-2"] { width: 50%;} : : これなら、それぞれのメディアクエリについて12種類ずつ、計36パターンのスタイルを定義するだけで5,184通りのレイアウトに対応できます。 できました! デモページ CSS .row { display: flex; flex-wrap: wrap; } .row > * { flex-grow: 0; flex-shrink: 0; } .row [class^="col1-"] { width: calc( 100% / 1 );} .row [class^="col2-"] { width: calc( 100% / 2 );} .row [class^="col3-"] { width: calc( 100% / 3 );} .row [class^="col4-"] { width: calc( 100% / 4 );} .row [class^="col5-"] { width: calc( 100% / 5 );} .row [class^="col6-"] { width: calc( 100% / 6 );} .row [class^="col7-"] { width: calc( 100% / 7 );} .row [class^="col8-"] { width: calc( 100% / 8 );} .row [class^="col9-"] { width: calc( 100% / 9 );} .row [class^="col10-"] { width: calc( 100% / 10 );} .row [class^="col11-"] { width: calc( 100% / 11 );} .row [class^="col12-"] { width: calc( 100% / 12 );} @media (min-width: 668px) { .row [class*="-1-"] { width: calc( 100% / 1 );} .row [class*="-2-"] { width: calc( 100% / 2 );} .row [class*="-3-"] { width: calc( 100% / 3 );} .row [class*="-4-"] { width: calc( 100% / 4 );} .row [class*="-5-"] { width: calc( 100% / 5 );} .row [class*="-6-"] { width: calc( 100% / 6 );} .row [class*="-7-"] { width: calc( 100% / 7 );} .row [class*="-8-"] { width: calc( 100% / 8 );} .row [class*="-9-"] { width: calc( 100% / 9 );} .row [class*="-10-"] { width: calc( 100% / 10 );} .row [class*="-11-"] { width: calc( 100% / 11 );} .row [class*="-12-"] { width: calc( 100% / 12 );} } @media (min-width: 1025px) { .row [class$="-1"] { width: calc( 100% / 1 );} .row [class$="-2"] { width: calc( 100% / 2 );} .row [class$="-3"] { width: calc( 100% / 3 );} .row [class$="-4"] { width: calc( 100% / 4 );} .row [class$="-5"] { width: calc( 100% / 5 );} .row [class$="-6"] { width: calc( 100% / 6 );} .row [class$="-7"] { width: calc( 100% / 7 );} .row [class$="-8"] { width: calc( 100% / 8 );} .row [class$="-9"] { width: calc( 100% / 9 );} .row [class$="-10"] { width: calc( 100% / 10 );} .row [class$="-11"] { width: calc( 100% / 11 );} .row [class$="-12"] { width: calc( 100% / 12 );} } Sass .row { display: flex; flex-wrap: wrap; > * { flex-grow: 0; flex-shrink: 0; } @for $i from 1 through 12 { [class^="col#{$i}-"] { width:calc( 100% / #{$i} ); } } @media ( min-width: 668px ) { @for $i from 1 through 12 { [class*="-#{$i}-"] { width:calc( 100% / #{$i} ); } } } @media ( min-width: 1025px ) { @for $i from 1 through 12 { [class$="-#{$i}"] { width:calc( 100% / #{$i} ); } } } } ...

プロダクション
2020年5月25日

faviconをアニメーションさせてみる

ブラウザのタブに表示されるfaviconが通知を教えてくれることがあります。赤いマークがついたりして、新着情報があることをfaviconがユーザにメンションしてくれます。なかなか気の利いた心遣いです。 通知が来るとリアルタイムでfaviconが変化し、通知に目を通すとその場で元に戻るので、表示するfaviconを動的に切り替えていることがわかります。 ということは、faviconを一定間隔で次々に切り替えていけばパラパラ漫画のようにアニメーションさせられるかも? ──という子供のような思いつきを実行に移してみます。 本当にfaviconを変更できるか? まずは、faviconを簡単に切り替えられるかどうか実験してみます。faviconを2枚用意して、ボタンを押すと切り替わるだけのjQueryを書きました。 <button><img src="./favicon-a.png"></button> <button><img src="./favicon-b.png"></button> $(function() { $('button').on('click', function() { $('link[rel="icon"]').attr('href', $(this).find('img').attr('src')); }); }); 結果は、 うまくいくようですね! どれくらいの速さで動くか? 次に、どのくらいの頻度でfaviconを切り替えられるか実験します。先ほど使った2枚のfaviconをsetIntervalで交互に切り替えるjQueryを書きました。フレームレート(秒間何枚の画像を切り替えられるか)をあれこれ変更して確認します。さてWebコンテンツのようにサクサク書き換わればよいのですが…… <link rel="icon" href="./favicon-a.png" data-alt="./favicon-b.png"> $(function() { const frameRate = 220; //フレームレート(ms) const $target = $('link[rel="icon"]'); window.setInterval(function() { const favIcon = $target.attr('href'); const altIcon = $target.attr('data-alt'); $target.attr({ 'href': altIcon, 'data-alt': favIcon }); }, frameRate); }); 結果は、 実験の結果、筆者の環境ではChromeで約4.5fps、Firefoxでは約9fpsと、想像以上に低いフレームレートでした(一般的な動画は約30fps)。これより切り替え頻度を上げるとコマ落ちします。あまりリッチな表現はできなそうです。 アニメーションを作る フレームレートの低いカクカクの動きしかしてくれないことがわかりましたので、アニメーションも割り切って地味なものにします。「ハートマークが拡大しながらフェードアウトしていく」という簡単な6フレームのアニメーションを用意しました。 最終フレームは通常時のアイコンにしてあります。アニメーション終了後、初期状態にリセットする手間をはぶくためです。 きっかけを与えると上の6フレームのアイコンが一周する、というjQueryを書きました。ハートマークのボタンを押すとアニメーションが走ります。 $(function() { const frameRate = 220; // フレームレート(ms) const frameAmount = 6; // フレーム数 let frameCount = 0; // 現在のフレーム let animationId; // setInterval用ID // [関数]アニメーション開始 function startAnimation() { animationId = window.setInterval(animateFavicon, frameRate); } // [関数]アニメーション処理本体 function animateFavicon() { if (frameCount < frameAmount) { const faviconPath = './frames/favicon_' + frameCount + '.png'; $('link[rel="icon"]').attr('href', faviconPath); frameCount++; } else { // 最後のフレームまで行ったら停止し、カウンターをリセット clearInterval(animationId); frameCount = 0; } } // クリックイベント $('button').on('click', function() { startAnimation(); }); }); 結果…… 地味……! でも、うまくいきました。低いフレームレートと狭い面積という制限はありますが、アイデアしだいでサイトに便利なインタラクションをつけ加えることができるのではないでしょうか。 なお、切り替えのたびにアイコン画像のリクエストがWebサーバに飛ぶことには注意が必要です。ループで回しっぱなしにしたり長大なアニメーションを組んだりするとサーバの負荷になるかもしれません。 ...

お問い合わせ

Web戦略策定からサイト構築、オペレーションまで、最適なワンストップのソリューションを提供します。
お気軽にお問い合わせください。

関連コンテンツ