第2の人生の構築ログ

自分の好きなことをやりつつ、インカムもしっかりと。FIRA60 (Financial Independence, Retire Around 60) の実現を目指します。SE を生業としていますが、自分でプログラミングしながら自分が欲しいと思うアプリケーションを作ることが楽しみです。旅行と温泉、音楽と読書は欠かすことができません。

シンプルで扱い易い、モダンなCSSフレームワーク Bulma を使ってみる

f:id:dr_taka_n:20190907110356p:plain

CSSフレームワークといったら、Bootstrap · The most popular HTML, CSS, and JS library in the world.が有名です。なぜか自ら進んで使ったことはなく、過去 Foundation の方を多く使っていました。

foundation.zurb.com

このフレームはこれでスバラシイと思います。今後も使っていくと思います。

一方で、今回新たにサイトを用意するにあたって、もう少しコンパクトで純粋にCSSだけで構成されている(JavaScriptは使っていない)フレームワークを使いたいと思って探していました。

なかなか評判の良い Bulma: Free, open source, & modern CSS framework based on Flexbox を試してみます。

bulma.io

私が CSS フレームワークを使い始めた契機は、モバイルのシェアの拡大によるPC/モバイル両方に適用可能なレスポンシブル Web デザインの適用でした。本職はデザイナーというわけではなく、サーバ側の実装の方をメインとしています。それっぽい感じのものをそれなりにそこまで時間をかけずに作り上げるには、すでにあれこれ試されていて実績のあるフレームワークに倣った方が良いという判断です。(餅は餅屋に)

Bulma の特徴として、"100% Responsibe""Modular""Modern""Free" があげられています。

f:id:dr_taka_n:20190907100955p:plain

要件としては、Responsive の対応は必須で、各種機能はコンパクトに分割されていること(Modular)、商用利用可能、という点です。全て適っています。"Modern" のところは CSS の専門家ではないので逆に使いながら最近のトレンドというものを学んでみたいと思います。

さて、この記事では、webpack を使った BulmaGetting started を目的としており、その作業のメモになります。ですので、いやそこまでは必要なくすぐに Bulma を試してみたい、という方は以下のページの記述の内容で試すことができます。

bulma.io

webpack を使った Bulma の Getting started (第一歩)

基本は、以下のページに書かれている内容です。一部アップデートが必要なところもありますので、補足します。

bulma.io

1. 作業フォルダを作成し、package.jsonを作成します

ここではbulma-with-webpackという名前のフォルダ(名前は任意です)を作成し、そのフォルダ配下に移動します。

npm init を発行します。とりあえず全てデフォルトでいきますが、entry point だけ上記ガイドで webpack.config.js にしておけとあるので、そうしておきます。

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (bulma-with-webpack) 
version: (1.0.0) 
description: 
entry point: (index.js) webpack.config.js
test command: 
git repository: 
keywords: 
author: 
license: (ISC) 
About to write to /Users/hoge/Repos/try-bulma/bulma-with-webpack/package.json:

{
  "name": "bulma-with-webpack",
  "version": "1.0.0",
  "description": "",
  "main": "webpack.config.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this OK? (yes) 

2. dev dependices をインストールします

npm で必要なパッケージをインストールしておきます。

$ npm install bulma --save-dev
$ npm install css-loader --save-dev
$ npm install extract-text-webpack-plugin@next --save-dev
$ npm install node-sass --save-dev
$ npm install sass-loader --save-dev
$ npm install style-loader --save-dev
$ npm install webpack --save-dev
$ npm install webpack-cli --save-dev

と、サイトには上記だけの記載ですが、以下も必要ですので、合わせてインストールしておきます。

$ npm install mini-css-extract-plugin --save-dev

3. webpack.config を作成します

webpack はv4系を使いますので、以下のようにwebpack.config.jsを記載します。
src をインプットし、dist をアウトプットディレクトリとしています。

webpack.config.js

const path = require('path');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

module.exports = {
  entry: './src/index.js',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: 'js/bundle.js'
  },
  module: {
    rules: [{
      test: /\.scss$/,
      use: [
          MiniCssExtractPlugin.loader,
          {
            loader: 'css-loader'
          },
          {
            loader: 'sass-loader',
            options: {
              sourceMap: true,
              // options...
            }
          }
        ]
    }]
  },
  plugins: [
    new MiniCssExtractPlugin({
      filename: 'css/[name].bundle.css'
    }),
  ]
};

4. src フォルダを作成し、entry ファイルを作成しておきます

src フォルダを作成し、entry ファイル(index.js)を作成しておきます。

src/index.js

require('./mystyles.scss');

5. Sass ファイルを作成しておきます

Sass ファイル(mystyles.scss)を作成しておきます。(記法はSCSSを使います)

src/mystyles.scss

@charset "utf-8";
@import "~bulma/bulma";

6. dist フォルダを作成しておきます

dist フォルダとその配下に css js フォルダを空で用意しておきます。

7. HTML ファイルを作成します

dist フォルダの中に mypage.html を作成し、内容は以下の通りとしておきます。

参照しているスタイルシート(css)のパスは、先程作成した src/mystyles.scssdist フォルダにコンパイルされて出力されるファイルになります。

<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>My custom Bulma website</title>
    <link rel="stylesheet" href="css/main.bundle.css">
  </head>
  <body>
     <h1 class="title">
        Bulma
      </h1>

      <p class="subtitle">
        Modern CSS framework based on <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Basic_Concepts_of_Flexbox">Flexbox</a>
      </p>

      <div class="field">
        <div class="control">
          <input class="input" type="text" placeholder="Input">
        </div>
      </div>

      <div class="field">
        <p class="control">
          <span class="select">
            <select>
              <option>Select dropdown</option>
            </select>
          </span>
        </p>
      </div>

      <div class="buttons">
        <a class="button is-primary">Primary</a>
        <a class="button is-link">Link</a>
      </div>
  </body>
</html>

この時点での表示は以下のような感じになります。これは素の HTML の状態ですので、まだ何もCSSの装飾はかかっていません。

f:id:dr_taka_n:20190907103739p:plain:w400

一度ここまでのファイル構成をおさらいしておきます。
(distフォルダ配下のcssjs フォルダの中に css ファイル、js ファイルがありますが、正確にはこのファイルはこの後の build を実行した後に生成されるものになります。)

$ ll
total 400
drwxr-xr-x    5 hoge  staff     160  9  5 14:43 dist
drwxr-xr-x  448 hoge  staff   14336  9  5 13:50 node_modules
-rw-r--r--    1 hoge  staff  194597  9  5 13:49 package-lock.json
-rw-r--r--    1 hoge  staff     578  9  5 13:49 package.json
drwxr-xr-x    4 hoge  staff     128  9  5 14:01 src
-rw-r--r--    1 hoge  staff     643  9  5 17:10 webpack.config.js
$ tree src/
src/
├── index.js
└── mystyles.scss

0 directories, 2 files
$ tree dist/
dist/
├── css
│   └── main.bundle.css
├── js
│   └── bundle.js
└── mypage.html

2 directories, 3 files

8. build スクリプトを追加しておきます

package.json にビルド用のコマンドを追加しておきます。"build": "webpack --mode production"

   "scripts": {
-    "test": "echo \"Error: no test specified\" && exit 1"
+    "test": "echo \"Error: no test specified\" && exit 1",
+    "build": "webpack --mode production"
   },

実行してみます。

$ npm run build

> bulma-with-webpack@1.0.0 build /Users/hoge/Repos/try-bulma/bulma-with-webpack
> webpack --mode production

Hash: 22541d54a3e85acf8685
Version: webpack 4.39.3
Time: 1129ms
Built at: 2019/09/05 13:50:44
              Asset       Size  Chunks             Chunk Names
css/main.bundle.css    186 KiB       0  [emitted]  main
       js/bundle.js  954 bytes       0  [emitted]  main
Entrypoint main = css/main.bundle.css js/bundle.js
[0] ./src/index.js 30 bytes {0} [built]
[1] ./src/mystyles.scss 39 bytes {0} [built]
    + 1 hidden module
Child mini-css-extract-plugin node_modules/css-loader/dist/cjs.js!node_modules/sass-loader/dist/cjs.js??ref--4-2!src/mystyles.scss:
    Entrypoint mini-css-extract-plugin = *
    [0] ./node_modules/css-loader/dist/cjs.js!./node_modules/sass-loader/dist/cjs.js??ref--4-2!./src/mystyles.scss 186 KiB {0} [built]
        + 1 hidden module

正しく動作しているようです。dist フォルダにコンパイルされた css が出力されましたので、この時点でのスタイルが適用されているはずですので、dist/mypage.html を確認してみます。Bulma が効いています。

f:id:dr_taka_n:20190907104608p:plain:w500

9. Bulma をカスタマイズしていきます

独自のカスタマイズを入れていきます。mystyles.scss を以下のように変更して再度 npm run build します。

先程は全ての Bulma のソースを読み込んでいましたが、ここでは、分割された各機能を個別に読み込んでいます。(下部にある@importのところです。)

また、広域変数で独自の値を設定しています。例えば、色ですとか($purple: #8A4D76;)、フォントのところです($family-sans-serif: "Nunito", sans-serif;)。 このように Bulma の設定値を外から変更することができます。(このあたりは他のフレームワークでも同じだと思います)

@charset "utf-8";
// @import "~bulma/bulma";

// Import a Google Font
@import url('https://fonts.googleapis.com/css?family=Nunito:400,700');

// Set your brand colors
$purple: #8A4D76;
$pink: #FA7C91;
$brown: #757763;
$beige-light: #D0D1CD;
$beige-lighter: #EFF0EB;

// Update Bulma's global variables
$family-sans-serif: "Nunito", sans-serif;
$grey-dark: $brown;
$grey-light: $beige-light;
$primary: $purple;
$link: $pink;
$widescreen-enabled: false;
$fullhd-enabled: false;

// Update some of Bulma's component variables
$body-background-color: $beige-lighter;
$control-border-width: 2px;
$input-border-color: transparent;
$input-shadow: none;

// Import only what you need from Bulma
@import "../node_modules/bulma/sass/utilities/_all.sass";
@import "../node_modules/bulma/sass/base/_all.sass";
@import "../node_modules/bulma/sass/elements/button.sass";
@import "../node_modules/bulma/sass/elements/container.sass";
@import "../node_modules/bulma/sass/elements/title.sass";
@import "../node_modules/bulma/sass/form/_all.sass";
@import "../node_modules/bulma/sass/components/navbar.sass";
@import "../node_modules/bulma/sass/layout/hero.sass";
@import "../node_modules/bulma/sass/layout/section.sass";

ちゃんと反映されているようです。

f:id:dr_taka_n:20190907105158p:plain:w500

しかし、ちょっと窮屈な感じがしますね・・・hero クラスを使ってコンテンツを括ります。

bulma.io

dist/mypage.html

   <body>
+    <section class="hero">
+      <div class="hero-body">
+        <div class="container">
     <h1 class="title">
       Bulma
     </h1>
@@ -33,5 +36,8 @@
       <a class="button is-primary">Primary</a>
       <a class="button is-link">Link</a>
     </div>
+        </div>
+      </div>
+    </section>
   </body>

それっぽくなりました。。

f:id:dr_taka_n:20190907105506p:plain:w500

ヘッダー、フッターを入れてみます。

dist/mypage.html

   <body>
     <section class="hero">
+      <div class="hero-head">
+        <div class="container">
+          <p>Header</p>
+        </div>
+      </div>
       <div class="hero-body">
         <div class="container">
     <h1 class="title">
       Bulma
     </h1>
@@ -33,5 +41,11 @@
       <a class="button is-primary">Primary</a>
       <a class="button is-link">Link</a>
     </div>
+    <div class="hero-foot">
+      <p>Footer</p>
+    </div>
         </div>
       </div>
     </section>
   </body>

f:id:dr_taka_n:20190907105953p:plain:w500

レイアウトも行い易く、必要な部品は大半そろっていそうでなかなか使えそう、というのがちょっと触ってみた感想です。継続して使っていこうと思います。