CSS」カテゴリーアーカイブ

HTMLスケッチでHTML/CSSトレーニング(Backlog編)

HTMLスケッチとは

本記事で言う「HTML」スケッチは、概ね以下の行為を指すものとする

  • 実在するWebページをHTMLとCSSを使って自らの手で再現する
  • 見本となるWebページは単一のページとし、それのソースコードを参照せずに、再現する
  • 再現に使用する手法/技術は、見本に合わせる必要はなく、自分の持っている知識から試行錯誤して再現する

参考 プロデザイナーが実践するHTML/CSSスキルアップ術

HTMLスケッチを行うメリット

  • HTML/CSSのスキル底上げには実際にモノを作るのが一番だが、何を作ったら良いかわからない時に手っ取り早い
  • 公開されているWebページがどのような構造で実装されているかが見えてくるので、Webデザイン力の底上げにもなる
  • 自分でWebデザインした場合には使わないようなレイアウト/スタイルを使うことも出てくるので、技術の幅が広がる

フロントエンジニアがWebデザインスキルを身につける必要はあるか?

これについては色々な意見が飛び交ってるが、個人的にはモダンなフロントエンジニアになるためにはWebデザインスキルも必須だと思う。

最近はリッチクライアント(死語?)が当たり前になってきたため、クライアント側でも各種ライブラリ/フレームワークの導入が一般的になってきてるが、その中でもReactやVue(Component)など、ビューとそのロジックが密になったライブラリ/フレームワークを使う場面も多くなって来ている。ビューとロジックが密ということは、それだけエンジニアとデザイナの作業範囲を分離しづらいということだ。

そうなると、デザインの諸々をデザイナに投げて放ったらかすというもの難しくなってくるため、エンジニアが最低限のデザインを施す必要がある。

よって、特にフロントエンジニアにもWebデザインスキルは必須になってくる(と思う)ので、本記事ではデザイナでなくフロントエンジニアの視点でHTMLスケッチを行う

HTMLスケッチのルール

以下のルールは本記事でのルールなので、実践する場合は各自やりやすいようにルール作りをしたほうが良い

  • 見本は既存Webサービスの特定の1画面をスクリーンショットで収めた範囲とする
  • 基本的にはスクリーンショットの画面を再現し、見えない範囲(オンマウスで見た目が変わるなど)については対応しない
  • JavaScriptが影響する部分は対応しない
  • bootstrapなどのCSSフレームワークの利用を禁止
  • 見本のソースコードを閲覧することは原則禁止する(スケッチ後に答え合わせとして確認する)
  • Saasを使う。今時生のCSSを直接書くのもナンセンスなので。と言ってもネスト構造ぐらいしか使う予定はない
  • 画像ファイルは見本のページから直接ダウンロードする(学習用なので見逃してください)
  • アイコンファイルは、今回はfontawesomeを用いて見本に近いアイコンを利用する
  • ブラウザ対応はそこまで拘らず、とりあえず見本撮影時に用いたChromeのみで検証する

今回の見本

例によってBacklogが好きなのでBacklogの課題一覧画面を対象とする。初めてのHTMLスケッチなので比較的簡単そうで、かつ身近な普段から見慣れている画面を見本とすることにした。

以下が今回見本とするスクリーンショット

作業環境の構築

以下の環境で作業を行う

要素 バージョン
Debian 8.6
sass 3.5.1
Compass 1.0.3

sassのインストール

sassはcssのプリプロセッサで、cssの弱い部分などを改良したメタ言語で書かれたファイルをcssに変換する。
簡単に言えばcssを効率的に記述するために必要なもの。

sassはgemライブラリで公開されてるので、rubyとgemが必要。本記事では割愛するので必要に応じてそれらもインストールすること。

vagrant$ sudo gem install sass

Compassのインストール

Compassは、sassで記述されたファイルの変更を検知し、自動でsassを実行し、変換後のcssファイルを生成してくれるツール。これが無いとファイルを変更するたびに変換コマンドを叩く必要があるので実質必須。

こちらもgemを用いてインストールする

vagrant$ sudo gem install compass

動作確認

compass createで作業環境をまとめて作成できる。

vagrant$ compass create
directory sass/
directory stylesheets/
   create config.rb
   create sass/screen.scss
   create sass/print.scss
   create sass/ie.scss
    write stylesheets/ie.css
    write stylesheets/print.css
    write stylesheets/screen.css
(以下略)

が、今回はscssファイル1個に全てまとめるつもりなので、生成されたsassファイルは消しておく

vagrant$ rm sass/*

compassを実行。watchコマンドで常駐化して変更を検知してくれる

vagrant$ compass watch
Compass is watching for changes. Press Ctrl-C to Stop.

この状態でsassディレクトリいかに、sassファイル(style.sass)を作成する

body {
  .hoge {
    font-size: 12px;
  }
  .fuga {
    font-size: 14px;
  }
}

するとcompassがそれを検知して

Compass is watching for changes. Press Ctrl-C to Stop.
  created sass/style.scss
    write stylesheets/style.css

自動でstyleseets/style.cssを生成してくれる

/* line 2, ../sass/style.scss */
body .hoge {
  font-size: 12px;
}
/* line 5, ../sass/style.scss */
body .fuga {
  font-size: 14px;
}

あとはこの生成されたcssファイルを参照するHTMLファイルを用意すれば準備完了

<html>
  <head>
    <link rel="stylesheet" type="text/css" href="stylesheets/style.css">
  </head>
  <body>
  </body>
</html>

HTMLスケッチの実施

大枠の実装

まずはページ全体の大枠をマークアップすることに。見本から見える必要な構造を想像してHTMLに書き出す(コードが長いのでGithub参照)

ある程度全体構造を意識しながら主にdivで囲って、適切なclassを振ってCSSの適用に備えている。

まだスタイルがまったく適用されていないので、そのまま画面に表示されるだけ。色々足りてない構造もあるが、それは随時追加していくものとする。
ここからスタイルの適用と、それに応じてHTMLの書き換えも行っていく。

カラム割

ページ全体を以下の3カラム構成にする

  • ヘッダー
  • サイドメニュー
  • コンテンツ

カラム割の流行りはflexboxらしいけどCSS弱者なので先ずはfloatを使ったカラム割の経験を積む。サイドメニューの背景には画像ファイルがあったのでBacklogから拝借する。コンテンツ内にもヘッダーがあるので、そこにはprojectと名付けて50px確保する。

body {
  margin:  0;
  padding: 0;
  border:  0;
}
.header {
  height: 50px;
  background-color: #ebf0f2;
}
.wrap {
  .sidebar {
    width: 200px;
    height: 100%;
    float: left;
    background-color: #3b9dbd;
    background-image: url('../images/bg_dot.png');
  }

  .content {
    margin-left: 200px;
    background-color: #f0f0f0;
    .project {
      height: 50px;
      background-color: white;
    }
  }
}

Github

HTMLも微修正して以下の感じに。少しだけ全体像が見えてくる。

サイドメニューの実装

ぱっと見一番簡単そうなのがサイドメニューなので安直にこちらから手を出す。HTMLは、メニュー項目をul/liで記述し、アイコンはfontawsomeを利用する。

      <div class="sidebar">
        <div class="burger"><i class="fa fa-bars fa-2x" aria-hidden="true"></i></div>
        <ul class="sidemenu">
          <li><i class="fa fa-home fa-lg" aria-hidden="true"></i><span>ホーム</span></li>
          <li><i class="fa fa-list fa-lg" aria-hidden="true"></i><span>課題</span></li>
          <li><i class="fa fa-plus fa-lg" aria-hidden="true"></i><span>課題の追加</span></li>
          <li><i class="fa fa-wikipedia-w fa-lg" aria-hidden="true"></i><span>Wiki</span></li>
          <li><i class="fa fa-files-o fa-lg" aria-hidden="true"></i><span>ファイル</span></li>
          <li><i class="fa fa-git fa-lg" aria-hidden="true"></i><span>Git</span></li>
          <li><i class="fa fa-cog fa-lg" aria-hidden="true"></i><span>プロジェクト設定</span></li>
        </ul>
      </div>
    .burger {
      text-align: right;
      .fa {
        padding: 10 20 10 0;
      }
    }
    ul.sidemenu {
      padding-left: 0;
      font-size: 95%;
      list-style-type: none;
      li {
        padding-left: 12px;
        margin: 20 0 20 0;
        .fa {
          width: 20px;
        }
        span {
          padding-left: 15px;
        }
      }
    }
  }

Github
まだ比較的まともにCSSも書けてそれっぽい画面が出来上がってる。

ヘッダーの実装

コンテンツは最後として、次にヘッダーに着手する。結果から言えばここが一番苦労した。CSSよくわからない。ユーザアイコン的な画像はBacklogから拝借。li要素を横並びに表示するテクニックを身に着けたのでさっそく使ってる。

    <div class="header">
      <img class="logo" src="images/logo.svg">
      <ul class="menus">
        <li>ダッシュボード</li>
        <li>プロジェクト</li>
        <li>最近みた課題</li>
        <li>最近見たWiki</li>
        <li>フィルタ</li>
      </ul>
      <ul class="icons">
        <li><i class="fa fa-ellipsis-h fa-lg" aria-hidden="true"></i></li>
        <li><i class="fa fa-plus fa-lg" aria-hidden="true"></i></li>
        <li><i class="fa fa-eye fa-lg" aria-hidden="true"></i></li>
        <li><i class="fa fa-bell fa-lg" aria-hidden="true"></i></li>
        <li><i class="fa fa-search fa-lg" aria-hidden="true"></i></li>
        <li class="bars"><i class="fa fa-bars fa-lg" aria-hidden="true"></i></li>
        <li>
          <img class="user-menu" src="images/user.gif">
          <i class="fa fa-angle-down" aria-hidden="true"></i>
        </li>
      </ul>
    </div>
.header {
  background-color: #ebf0f2;
  * {
    vertical-align: middle;
  }
  ul {
    padding: 0;
    margin: 10px 0 10px 0;
    list-style-type: none;
    display: inline-block;
    li {
      display: inline-block;
      margin-left: 12px;
    }
  }
  img {
    width: 30px;
    max-height: 100%;
  }
  img.logo {
    padding-left: 20px;
  }
  .menus {
    font-size: 95%;
    width: 70%;
  }
  .icons {
    width: 25%;
    color: gray;
    text-align: right;
    .bars {
      padding-left: 20px;
      border-left: 1px solid gray;
    }
  }
}

Github

課題一覧の実装

メインの部分。この辺から妥協が生まれる。細かい部分を合わせるのが難しくなってきて、ゴリ押し気味なスタイリングが増えてくる。
テーブルは普通にtableタグを用いて、列単位で装飾。聞くところによるとTableの内部要素(tr/td)にmarginやpaddingを設定するのはナンセンスらしいけど、それを避けて装飾するのが上手く行かなかったので妥協。

        <div class="issues">
          <table>
            <thead>
              <tr>
                <th>種別</th>
                <th>キー</th>
                <th>件名</th>
                <th>状態</th>
                <th>カテゴリー</th>
                <th>登録日</th>
                <th>更新日</th>
                <th>登録者</th>
              </tr>
            </thead>
            <tbody>
              <tr>
                <td><div class="task mark">タスク</div></td>
                <td><a href="">DEV-240</a></td>
                <td>githubのコミットログを@nullでツイートする方法の検討</td>
                <td><div class="status mark">未対応</div></td>
                <td>開発関係</td>
                <td>2017/07/30</td>
                <td>2017/07/30</td>
                <td class="user">
                  <img class="user-menu" src="images/user.gif">
                  <span>sa2knight</span>
                </td>
              </tr>
             <tr>
                <td><div class="task mark">タスク</div></td>
                <td><a href="">DEV-237</a></td>
                <td>vimでもっと強力なコード補完を導入する</td>
                <td><div class="status mark">未対応</div></td>
                <td>開発関係</td>
                <td>2017/07/30</td>
                <td>2017/07/30</td>
                <td class="user">
                  <img class="user-menu" src="images/user.gif">
                  <span>sa2knight</span>
                </td>
              </tr>
             <tr>
                <td><div class="task mark">タスク</div></td>
                <td><a href="">DEV-235</a></td>
                <td>[でぐろぐ]元ツイートページから画像ファイルのパスを抜き出すロジック</td>
                <td><div class="status mark">未対応</div></td>
                <td>開発関係</td>
                <td>2017/07/30</td>
                <td>2017/07/30</td>
                <td class="user">
                  <img class="user-menu" src="images/user.gif">
                  <span>sa2knight</span>
                </td>
              </tr>
            </tbody>
          </table>
        </div>
    .issues {
      padding: 0 30 0 30;
      table {
        width: 100%;
        border: solid 1px #c2c2c2;
        border-radius:   4px;
        border-collapse: collapse;
        thead {
          background-color: white;
          color: #00759b;
          font-size: 85%;
          tr {
            border-bottom: 2px solid #ccc;
          }
          th {
            padding: 7px 0px 7px 0px;
          }
        }
        tbody {
          font-size: 80%;
          a {
            color: #00759b;
            text-decoration: none;
          }
          tr {
            border-collapse: separate;
          }
          tr:nth-child(even) {
            background-color: #f6f6f6;
          }
          tr:nth-child(odd) {
            background-color: white;
          }
          td {
            padding: 5px 15px 5px 15px;
          }
          td > .mark {
            text-align: center;
            color: white;
            padding: 0 10 0 10;
            border-radius: 20px;
          }
          td > .task {
            background-color: #b0be3c;
          }
          td > .status {
            background-color: #ed8077;
          }
          td.user {
            img {
              vertical-align: middle;
              width:  24px;
              height: 24px;
            }
          }
        }
      }
    }

Github
ゴリ押したけど見た目はそれっぽい

課題一覧周辺のUI実装

ページャみたいなモノとかボタンとかのスタイリング。この当たりから作業がとても地味でCSSも汚くなってきた。
コードの修正が分散してきたのでGithub参照

検索フォームの実装とその他修正

あとは検索フォームをスタイリングして全体の仕上げをして完成。
最終的な成果物はこちら

上が今回作成したページで、下が見本となる本家Backlog。比べてみると中国産のパチもんみたいにも見えるが、概ね同じように出来ているので個人的には満足。

所感

良かった点

  • スケッチの過程でスタイリングに関する知らなかった定石/手法を身につけることができた
  • 最後にBacklogのCSSを見て答え合わせした中で、知らなかった属性などを学ぶことができた
  • 自分で一からスタイリングする経験が少なかったので、そういった経験を得られた

失敗した点

  • flota,absolute,text-alignなど、現在はあまり使われないスタイリング手法に頼りすぎて、変更に弱いCSSになったと自負してる。もう少しモダンなスタイリング技術を学びたい
  • BacklogのようなWebサービスは、通常動的にページが生成されるので必然的にHTMLの可読性が低くなるので、参考にしづらかった。俳優のホームページなど、静的なHTMLページを見本にしたほうが勉強になると思う
  • ファイルを更新した後にブラウザも更新するのが面倒だった。ブラウザのオートリロードツールなどを導入すればもう少し楽だったかも

Bowerを使ってフロントエンドの依存関係を管理する

前提

要素 バージョン
debian 8.7
node 7.4.0
npm 4.1.2
bower 1.8.0

概要

Debianにnpmを用いてBowerをインストールし、Bowerを簡単に使ってみる

Bowerとは

Bower(バウアー)はフロントエンド開発の依存関係(JavaScript/CSS/HTMLなど)を管理してくれるフロントエンド用パッケージ管理システム。

PHPのComposer、RubyのGem、iOSのcocoaPodsなどの仲間だと思えば良い。

ライブラリなどのインストールをコマンドで行えるようになり、インストールした内容及びその依存関係が、bowser.jsonに書き込まれる。

同一のbowser.jsonさえあれば、他環境にライブラリをインストールする際にコマンド一発で解決する。

Bowerのインストール

npmを用いてインストールを行う。パッケージ管理システム(npm)でパッケージ管理システム(bower)をインストールするのがちょっと面白い。ここではver1.8.0がインストールされる。

$ sudo npm install bower -g
/usr/local/bin/bower -> /usr/local/lib/node_modules/bower/bin/bower
/usr/local/lib
└── bower@1.8.0

bower.jsonの作成

初めにパッケージの依存関係などを記述するbower.jsonを作成する。といっても、JSONファイルを直接作成するのでなく、以下のコマンドを実行すると、対話式に入力を促されるのでそれに従っていけば自動的にbower.jsonが作成される

$ bower init

以下のように、名称、説明文、メインファイル(省略可)、キーワード(省略可)、作者、ライセンス、Webサイト(省略可)などを入力することで、bower.jsonが生成される。ここで入力される情報のうちのいくつかは、自分でbowerにライブラリを公開する場合に必要になるものなので、単に開発で試用するライブラリを管理するという場合は省略して良い。

$ bower init
? name qs-test
? description bower test directory
? main file
? keywords
? authors Sa2Knight <shingo.sasaki.0529@gmail.com>
? license MIT
? homepage
? set currently installed components as dependencies? No
? add commonly ignored files to ignore list? No
? would you like to mark this package as private which prevents it from being accidentally published to the registry? No

{
  name: 'qs-test',
  authors: [
    'Sa2Knight <shingo.sasaki.0529@gmail.com>'
  ],
  description: 'bower test directory',
  main: '',
  license: 'MIT',
  homepage: ''
}

? Looks good? Yes

Bowerを用いてjQueryUIパッケージをインストールする

Bowerを用いたパッケージのインストールは、下記のコマンドで行える。 –save を付与することで、インストール結果をbower.jsonに記録してくれるので実質必須。

$ bower install [パッケージ名] –save

jQueryUIのパッケージ名はjquery-uiなので、以下のように、jQueryUIをインストールする

$ bower install jquery-ui --save
bower jquery-ui#*               cached https://github.com/components/jqueryui.git#1.12.1
bower jquery-ui#*             validate 1.12.1 against https://github.com/components/jqueryui.git#*
bower jquery#>=1.6              cached https://github.com/jquery/jquery-dist.git#3.2.1
bower jquery#>=1.6            validate 3.2.1 against https://github.com/jquery/jquery-dist.git#>=1.6
bower jquery-ui#^1.12.1        install jquery-ui#1.12.1
bower jquery#>=1.6             install jquery#3.2.1

bower.jsonの内容を確認すると、jQueryUI1.12.1に依存している状態にあることが追記されている

$ cat bower.json
{
  "name": "qs-test",
  "authors": [
    "Sa2Knight <shingo.sasaki.0529@gmail.com>"
  ],
  "description": "bower test directory",
  "main": "",
  "license": "MIT",
  "homepage": "",
  "dependencies": {
    "jquery-ui": "^1.12.1"
  }
}

インストールされたパッケージは、bower_componentsディレクトリ以下に配置されるのだが、ここを見てみると、jQueryUIが依存しているjQuery本体もインストールされていることがわかる。

$ ls bower_components/
jquery  jquery-ui

このように、Bowerでは、インストール対象のパッケージが依存している他のパッケージについても自動的にインストールしてくれる。(composerやnpm、gemなどに慣れている人にとっては当然だが)

所感

  • npmの影響を大きく受けているらしく、全体的な仕様やコマンドの使い方がnpmに限りなく近い
  • bowerでは、対象パッケージをgitからcloneしてくるだけなので、実際に必要なるファイルはその中の極一部である。それをどのように扱うかはまた別の手段を用いる必要があるようなので、即戦力という感じでは無さそうだ
  • scriptタグでロードする時に依存関係に基づいた順番でロードしなきゃならないって問題は解決できてない
  • と言うかJavaScriptの外部ライブラリってそんな依存管理が必要なほど沢山使うかな
  • bowerの触りをやった程度なのでメリットがあまり掴めてない。詳しい方がいたらご教授願う。
  • bowerのサブコマンドが大量にあるので、余裕があれば色々見てみたい

参考

MEANでデグー飼育アプリを作ってみた

概要

  • 前々からMEANスタックに興味があった
  • 2017/01/22ぐらいからチマチマMEANアプリ作り始めた
  • とりあえず自分にとって実用的であるのが望ましいので、デグー飼育支援アプリを作った
  • MEANだとこんなことができるよの紹介を含め、動作画面を掲載する
  • 完全に個人用なのでサービスの公開はしないが、ソースコードはGithubで公開している

システム構成

OS + MEAN構成は以下の通り

構成要素 バージョン
Debian 8.7
Mongodb 3.2.9
Express 4.14.0
AngularJS 1.4.1
NodeJS 7.4.0

その他、主に開発に用いたツールなどは以下の通り

構成要素 バージョン
npm 4.1.2
babel 6.22.2
eslint 3.0.1
less 3.3.0
gulp 3.9.1
jQuery 3.1.1
jQUeryUI 1.8.19
bootstrap 3.3.7
d3.js 3.5.16
c3.js 0.4.1

ソースコード

https://github.com/Sa2Knight/degu-log よりクローン可能。

環境構築手順も一応READMEにあるので、頑張ればローカルでも動作させられる(多分)
Zaimアカウント及びZaimAPIを利用するためのトークンが必要だったり敷居は高い。

機能一覧

高速な画面遷移

初っ端から機能というより特徴の話だが、本アプリはSPA(っぽい何か)でありながら、URLを変更しながら画面遷移を行える。
そのため、ブラウザの「戻る」「進む」も利用可能であり、URLを直接指定して特定のリソースにアクセスすることもできる。

AngularJSのオプションモジュールである、ng-routeを用いることで、それを簡単に実装できた。
しかも画面遷移が非常に早い。これだけでMEANで開発してよかったと思えるレベル。

簡易ブログ機能

飼育に関する簡易的なブログっぽいものを投稿することができる。
ブログは通常のCRUDの他、カレンダーを表示して記事を一覧することができる。

体重管理機能

デグーの体重を時系列で管理することができる。便宜上、我が家のデグー2匹(パズー、メイ)に特化しており、それぞれ日付に対する体重を記録することができる。
また、時系列に記録した体重を元に、折れ線グラフをリアルタイムで描画することができる。

ペット関連支出管理機能

本機能は、クラウド家計簿サービスであるZaim及び入力した家計簿記録を取得するZaimAPIを用いて実装している。
日頃から入力している家計簿データを元に、月ごとの支出額の一覧及び特定月の支払内容を閲覧できる。

外部APIの利用もやはりSPAとの相性が抜群だ

写真管理機能

写真をアップロードして管理することができる。写真には、タイトル及び1つ以上のタグを付与することができ、それらで検索することができる。
また、写真アップロード時にオリジナルと別にサムネイルを生成し、写真一覧画面にはサムネイルが表示され、クリックすることでオリジナルサイズを確認できるようにアンっている。

所感

MEANという、MもEもAもNもほぼ使ったこと無い状態から、1つずつ勉強しながらなんとか実用性も多少あるWebアプリを作ることができた。特にSPAを1から作るのは初めての経験だったので、従来型のWebアプリとの違いを感じながら楽しく開発することができた。以下、主な所感を列挙する

  • MongoDBはJavaScriptライクに読み書きを行え、スキーマに依存せずにデータを管理できるので手軽で楽しい
  • AngularJSは双方向データバインディングが一番強いと思ったが、フルスタックのMVCであればAngularJSでなくても良いかなとは思う。
  • Nodeを使えばだいたいのことは対応するNodeモジュールがあって、サーバサイドを一通りJavaScriptで書ける。強い。
  • Expressについては、今回はRestfulなAPIサーバとしてしか使わなかったので触り程度しかわからなかった
  • SPAはクライアントの待機時間が極端に短くなるのでストレス無く利用できることを強く実感
  • クライアントサイドの負担を増やし、サーバサイドの負担を減らす新しい分散システムだと感じた
  • SPAでも画面遷移ごとにURLを変化させたほうが絶対便利だと思った
  • サーバサイドはRestfulなAPIに特化させるように実装したほうが分担が明確で良い
  • JavaScriptはBabelを導入して、全てES6で記述した。やはり最新仕様のJavaScriptは書きやすい。もう戻りたくない。
  • ESLintを導入してコーディング規約を強制した。おかげで比較的高品質のコードを終始簡単に弄るすことができた
  • Bootstrapに頼りきりだった割にUIが雑で残念
  • 一応LESSも導入したが特に使いこなせてない
  • テスト(ユニット,E2E)を書きたかったが、その余裕がなかった。そのうち書きたい
  • とにかく新しい技術/ツールで溢れた開発で楽しい1ヶ月半だった

次はTypeScript及びAngular2に手を付けてみたい。Angular2のほうが良さげであれば、本アプリを移植することも検討する。

LESSを用いたCSSの効率化とGulpによる自動コンパイル

前提

前提となる環境は以下の通り。

ツール バージョン
node 7.4.0
npm 4.1.2
gulp 3.9.1

上記環境のインストールについては下記参照
Debian8.7にMEAN開発環境を構築する
Babel+Gulpで始めるES6

LESSとは

CSSをロジカルに記述できるメタ言語。通常のCSSを拡張する形で、主に以下の機能が利用できるようになる。作成したLESSファイルは、LESSコンパイラを通してCSSに変換して利用する。

  • 変数代入
  • 階層構造化
  • 条件分岐
  • ミックスイン
  • 継承
  • 豊富な標準関数

LESS.jsによる動的なコンパイル

LESSは、基本的にコンパイラを用いてデプロイ前に静的に変換するが、コンパイル環境を持たずとも、LESS.jsを用いることでWebブラウザ上で動的にCSSに変換することができる。

LESS.jsはCDNから利用できるので、該当のHTMLページでそれをロードし、それより上でLESSのファイルをCSSと同じようにロードする。下記にその例を示す。

<html>
<head>
  <link rel="stylesheet/less" type="text/css" href="hoge.less">  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/less.js/2.2.0/less.min.js"></script>  
</head>
<body>
</body>
</html>

これで、LESS.jsは読み込まれた時点でリソースに存在するlessファイルをcssに変換する。非常にお手軽ではあるが、ブラウザに変換を任せてしまうこと、コード量が多くなってしまうことから、デプロイ時には静的変換をかけるようにし、LESS.jsの使用は開発中に限ったほうが良いと思われる。

lessコンパイラのインストール

本記事の前提の項で触れているとおり、gulp(3.9.1)が使える状態から始まっているので、ここではgulpでlessを利用するためのパッケージをインストールする

$ sudo npm install -D gulp-less

インストールされたバージョンを確認

$ npm ls gulp-less
degulog@1.0.0 /home/vagrant/less-test
└── gulp-less@3.3.0

gulpにタスクを定義

ここでは、app/styles/style.lessに変更を検知したら、それをcssに変換し、app/styles/build/style.cssに保存するタスクを記述する。

gulpfile.js

var gulp = require('gulp');
var less = require('gulp-less');

gulp.task('less' , function() {
  gulp.src('app/styles/style.less')
      .pipe(less())
      .pipe(gulp.dest('app/styles/build/'));
});

gulp.task('watch' , function() {
  gulp.watch('app/styles/style.less' , ['less']);
});

gulp.task('default' , ['less' , 'watch']);

これで、gulpコマンド実行時と、実行中にファイルが書き換わった際に自動でコンパイルしてくれるのでコーダーは一切意識すること無くLESSだけを記述することができる。

LESS構文例

ここからは、LESSの主な機能について特に意味のない極シンプルなコード例を示す。コードは、変換前のlessファイル、変換後のcssファイルの順で掲載する。

変数の利用

@変数名: 値
の形式で宣言できる。単純な計算や文字列展開も可能。

変換前

@header1: 18px;
@header2: @header1 - 4;
@imgdir: "/img";
h1 {
  font-size: @header1;
}
h2 {
  font-size: @header2;
}
.content {
  background-image: url("@{imgdir}/bg1");
}

変換後

h1 {
  font-size: 18px;
}
h2 {
  font-size: 14px;
}
.content {
  background-image: url("/img/bg1");
}

階層構造化

ある要素の子要素にのみスタイルを振ると行った場合に有効。もう冗長にしか見えないコードを書く必要がない。

変換前

h1 {
  font-size: 18px;
  a {
    text-decoration: none;
  }
}

変換後

h1 {
  font-size: 18px;
}
h1 a {
  text-decoration: none;
}

条件分岐

変数の値を元に、スタイルの設定を分岐させる

変換前

@width: 400px;

.content when (@width <= 400px) {
  font-size: 12px;
}
.content when (@width > 400px) {
  font-size: 14px;
}

変換後

.content {
  font-size: 12px;
}

ミックスイン(関数)

イメージは関数呼び出し?宣言済みのスタイルを取り込むことができる。

変換前

.my-header(@font-size: 16px) {
  text-align: center;
  font-size: @font-size;
}
h1 {
  .my-header();
}
h2 {
  .my-header(14px);
}

変換後

h1 {
  text-align: center;
  font-size: 16px;
}
h2 {
  text-align: center;
  font-size: 14px;
}

継承

ミックスインと似ているが、生成されるCSSを見ると分かる通り、こちらのほうがコード量が少なく、親子関係もわかりやすくなる。

変換前

.my-header {
  text-align: center;
}
h1 {
  &:extend(.my-header);
  color: red;
}
h2 {
  &:extend(.my-header);
  color: blue;
}

変換後

.my-header,
h1,
h2 {
  text-align: center;
}
h1 {
  color: red;
}
h2 {
  color: blue;
}

豊富な関数

LESSには様々な関数が用意されている。以下はその1例で、@base-colorを元に、それより10%明るい色を計算して設定してくれる

変換前

@base-color: #aa1111;
h1 {
  color: lighten(@base-color , 10%);
}

変換後

h1 {
  color: #d81616;
}

所感

  • 個人的には、階層構造化できる点が一番大きい。CSSでいつも冗長な記述をしている気がしてならなかったので
  • Node環境を用意できなくてもJavaScriptファイルをロードするだけでLESSが使えるというのは大きい。これならデザイナーさんなども手軽に利用できる
  • 最近学習した技術と比較しても、覚えることが非常に少なくそれでいてパワフルな生産性を生み出せるコスパの良い技術だと思った。従来のCSSに対して上位互換を持っている分、既存のCSSをそのまま使いつつ一部分だけLESSで拡張すると行ったこともできるので、導入コストは非常に小さいと思われる

参考