はじめに
CSSフレームワークを選ぶとき、「見た目は整えたいけど、JavaScriptのバンドルサイズは増やしたくない」と感じたことはありませんか。BootstrapやMaterial UIは便利な反面、コンポーネント用のJSがついてきて、使わない機能まで読み込んでしまうことがあります。
そんな悩みに正面から応えてくれるのが、今回紹介するBulmaです。FlexboxをベースにしたモダンなCSSフレームワークで、GitHub Starsは5万を超えています。最大の特徴は、JavaScriptを一切含まない、純粋なCSSだけのフレームワークであること。この記事では、Bulmaの特徴からインストール方法、実践的な使い方まで解説していきます。
Bulmaとは
Bulmaは、Flexbox(一部CSS Grid)を土台にした、クラスベースのCSSフレームワークです。is-primaryやhas-text-centeredのように、英単語をそのままクラス名にした直感的な命名規則が特徴で、コンポーネント名を覚えなくてもコードを読むだけで意味が推測できます。
主な特徴
- JavaScript依存ゼロ - フレームワーク本体にJSは一切含まれません。ナビゲーションのバーガーメニューやモーダルの開閉といった動的な挙動は、自分でシンプルなJSを書く前提で設計されています。そのぶんバンドルサイズが軽量です
- Flexboxベースのレイアウト -
columnsとcolumnを組み合わせるだけで、レスポンシブなグリッドレイアウトが直感的に組めます - 意味の分かるクラス命名 -
is-*(状態・バリエーション)、has-*(付加的な性質)というプレフィックスのルールが一貫しているため、初見でも読みやすいです - Sassによるカスタマイズ - Sass変数を上書きするだけで、独自のデザインテーマに調整できます
- HTMLだけで完結するコンポーネント - ボタン・カード・タグ・パンくずリストなど、多くのコンポーネントはクラスを付けるだけで見た目が完成します
インストール
npm
npm install bulma
yarn / pnpm
yarn add bulma
# または
pnpm add bulma
インストール後は、Sassファイルとしてインポートするのが一般的です。
@charset "utf-8";
@import "bulma/sass/utilities/_all.sass";
// 変数のオーバーライドはインポートより前に書く
$primary: #7957d5;
@import "bulma/sass/base/_all.sass";
@import "bulma/sass/elements/_all.sass";
@import "bulma/sass/components/_all.sass";
@import "bulma/sass/layout/_all.sass";
CDN
ビルド環境を用意せず、とりあえず試したい場合はCDNから直接読み込めます。
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.4/css/bulma.min.css">
Bulmaの基本的な使い方
is-*のクラスを組み合わせるだけで、ボタンや通知のバリエーションが作れます。JavaScriptを一行も書いていない点に注目してください。
Bulmaのボタンはbuttonクラスにis-primaryやis-dangerといった色バリエーション、is-roundedやis-outlinedといった形状バリエーションを重ねがけするだけで見た目が完成します。通知はnotificationクラスにis-infoのような色クラスを組み合わせます。
<button class="button is-primary">Primary</button>
<button class="button is-success is-rounded">Success</button>
<button class="button is-danger is-outlined">Danger</button>
<button class="button is-large is-warning">Large</button>
<div class="notification is-info is-light">
<button class="delete"></button>
is-lightを付けると淡い背景色になります
</div>
実際に動かせるものが下です。クラス名を書き換えると、ボタンや通知の見た目がその場で変わります。
buttonにis-primaryやis-roundedを付け足すだけで見た目が変わる、この積み木のような組み合わせ方がBulmaの基本です。通知の閉じるボタンのように、動作が必要な部分だけ自分でJSを添えます。
Bulmaの実践的なユースケース
Bulmaのレスポンシブなカラムレイアウト
columnsとcolumnの組み合わせは、Bulmaの核となるレイアウト機能です。画面幅に応じてカラム数を変えたい場合は、is-half-tabletのようにブレークポイント別の指定ができます。
Bulmaのグリッドは、親要素にcolumnsを、子要素にcolumnを付けるだけで成立します。is-half-mobileのようにブレークポイント名(mobile / tablet / desktop)をクラス名の末尾に付けることで、画面幅ごとに異なる幅を指定できます。
<div class="columns is-mobile">
<div class="column is-half-mobile is-one-third-tablet">
<div class="box">カラム1</div>
</div>
<div class="column is-half-mobile is-one-third-tablet">
<div class="box">カラム2</div>
</div>
<div class="column is-one-third-tablet">
<div class="box">カラム3</div>
</div>
</div>
実際に動かせるものが下です。ブラウザの幅を変えると、カラムの並び方がブレークポイントごとに切り替わる様子を確認できます。
is-half-mobileはスマホ幅で半分、is-one-third-tabletはタブレット以上で1/3幅になる指定です。メディアクエリを自分で書かなくても、クラス名を並べるだけでブレークポイントごとの挙動を制御できます。
Bulmaのフォームコンポーネント(field / control)
fieldとcontrolでラベルと入力欄をまとめるのが、Bulmaのフォームの基本構造です。has-icons-leftを付けると、アイコン付きの入力欄も簡単に作れます。
fieldが1つの入力単位を表し、内側のcontrolが実際のinputやselectをラップします。controlにhas-icons-leftを付けると、icon要素をアイコンとして左側に配置できます。
<div class="field">
<label class="label">メールアドレス</label>
<div class="control has-icons-left">
<input class="input" type="email">
<span class="icon is-small is-left">✉</span>
</div>
</div>
<div class="field">
<div class="control">
<button class="button is-primary is-fullwidth">登録する</button>
</div>
</div>
実際に動かせるものが下です。
チェックボックスの利用規約に同意するを外したまま送信ボタンを押しても、Bulma自体はバリデーションを行いません。controlの中身をJavaScriptで検証したい場合は、is-dangerクラスをinputに付けてエラー表示にするなど、状態に応じたクラスの出し分けを自分のコードで行う必要があります。
Bulmaのナビゲーションバー(バーガーメニュー)
Bulmaのnavbarは、スマホ幅で表示するハンバーガーアイコンまで用意していますが、開閉のロジックはJSを持たないため自分で書く必要があります。これはBulmaが「JavaScriptゼロ」を貫いていることの象徴的な例です。
navbar-burgerにはアイコン用のspanが3本入っており、CSSで≡の見た目を作っています。クリック時にnavbar-burgerと、対応するnavbar-menuの両方へis-activeクラスをトグルするのが実装の要点です。
<a role="button" class="navbar-burger" data-target="navMenu">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
<div id="navMenu" class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item">ホーム</a>
</div>
</div>
document.querySelectorAll('.navbar-burger').forEach((burger) => {
burger.addEventListener('click', () => {
const target = document.getElementById(burger.dataset.target)
burger.classList.toggle('is-active')
target.classList.toggle('is-active')
})
})
実際に動かせるものが下です。
ウィンドウ幅を狭めてバーガーアイコンをクリックすると、メニューが開閉します。navbar-burgerとnavbar-menuの両方にis-activeをトグルするだけ、というシンプルさがポイントです。
Bulmaのモーダル(modal)
modalコンポーネントも同様に、見た目のCSSはBulmaが用意しますが、開閉の制御はis-activeクラスのトグルを自分で書きます。
modalの直下にmodal-background(背景の半透明レイヤー)とmodal-card(本体)を並べ、is-activeを付けるかどうかで表示・非表示を切り替えます。背景クリックでも閉じられるようにmodal-backgroundにもクリックイベントを仕込むのが定石です。
<div class="modal" id="demo-modal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">確認</p>
</header>
<section class="modal-card-body">本文</section>
</div>
</div>
const modal = document.getElementById('demo-modal')
const toggle = () => modal.classList.toggle('is-active')
document.getElementById('open-modal').addEventListener('click', toggle)
modal.querySelector('.modal-background').addEventListener('click', toggle)
実際に動かせるものが下です。
「モーダルを開く」ボタンを押すとmodalにis-activeが付いて表示され、背景・キャンセル・×ボタンのどれを押しても同じtoggle関数で閉じます。開閉のたびに要素を作り直す必要がなく、クラスの付け外しだけで完結する点がBulmaのモーダル実装の特徴です。
まとめ
Bulmaは、Flexboxベースの読みやすいクラス設計と、JavaScriptを一切含まないシンプルさが魅力のCSSフレームワークです。
is-*/has-*という一貫した命名規則で、初見でもクラスの意味が推測できるcolumns/columnによるレスポンシブレイアウトが直感的- JSを含まないぶん軽量で、必要な挙動だけを自分でコントロールできる
- Sass変数のオーバーライドで、デフォルトの見た目から自由にカスタマイズできる
「コンポーネントの見た目はフレームワークに任せたいが、動的な挙動は自分で制御したい」というプロジェクトには、Bulmaの割り切った設計がちょうどよくフィットします。まずはCDNで読み込んで、ボタンやカラムレイアウトから触ってみてください。