Site icon Tips Note by TAM

覚えるのはこれだけ!Pug(Jade)のよく使う9つの書き方

以前Pug(Jade)を使った制作環境を作る方法を紹介しました。

Pug(Jade)で効率的なマークアップ環境を作る

今回はPugでマークアップをしていくときに、よく使う書き方を紹介します。

ベースになるルールは9個あります。

  1. タグ名はHTMLタグになる
  2. 改行をしてインデントをつければ入れ子になる
  3. インライン要素や改行にはパイプライン(|)を使う(ここだけ慣れが必要)
  4. HTMLはドット(.)で終わる要素の中に入れておけば解釈される
  5. 属性は丸括弧内に記述する
  6. クラス属性はドット(.)、ID属性はシャープ(#)で表す
  7. コメントにはHTMLとして出力されるものと、されないものがある
  8. イコール(=)を使えばエスケープできる
  9. インクルード(include [ファイル名へのパス])で共通化したファイルを挿入できる

Pugとはなにか?

Sassを使ってCSSを作成している人は多いと思いますが、PugはHTMLにおけるSassのようなものです。
Pugを使うメリットとしては、通常のHTMLだけではできない(SSIのような)共通化ができること、開始タグと終了タグというものがないのでタグの閉じ忘れや閉じ間違いが起きないというところがあります。
つまり、修正に強いHTMLを書くのに最適なツールということです。

<main>
  <article>
    <header class="home-Hero">
      <h1 class="home-Hero_Logo"><img src="#" alt=""></h1>
    </header>
    <section class="home-About">
      <div class="home-About_Title">
        <h2 class="home-About_Heading sw-Heading">About</h2>
        <p class="home-About_Description">CSS Talkとは?</p>
        <svg class="home-About_Clips">
          <defs>
            <clippath id="home-About_TitleClip" clipPathUnits="objectBoundingBox">
              <polygon points="0,0 1,0 1,.934 .997,.943 .994,.948 .991,.95 .523,.95 .5,1, .477,.95 .009,.95 .006,.948 .003,.943 0,.934"></polygon>
            </clippath>
          </defs>
        </svg>
      </div>
    </section>
  </article>
</main>

例えば上記のHTMLはあるサイトの一部ですが、コンパイル前のPugでは以下のようにスッキリとした状態になっています。要素同士の階層構造が分かりやすいですし、終了タグがないのでインデントを変えるだけで階層構造を簡単に変えることもできます。

main
  article

    //- ヘッダ
    header.home-Hero
      h1.home-Hero_Logo
        img(src="#" alt="")

    //- About
    section.home-About
      .home-About_Title
        h2.home-About_Heading.sw-Heading
          | About
        p.home-About_Description
          | CSS Talkとは?
        svg.home-About_Clips
          defs
            clippath#home-About_TitleClip(clipPathUnits="objectBoundingBox")
              polygon(
              points="0,0 1,0 1,.934 .997,.943 .994,.948 .991,.95 .523,.95 .5,1, .477,.95 .009,.95 .006,.948 .003,.943 0,.934")

Pugをコンパイルする環境

Pugにはコンパイルをするための環境が必要です。
Gulpに慣れている場合はテンプレートを用意しているので試してみてください。browser-syncも入っているので、リアルタイムに変更されたHTMLを表示してくれますし、コンパイルエラーが出たときにはデスクトップ通知で知らせしてくれます。

gulp-pug-test | GitHub

手軽に試したい場合はJadeのジェネレーターを試してみてください(Pugの記法すべてに対応していないので注意してください)。

Pugの記法

Pugの使い方や記法は公式ドキュメントを確認するのが確実です。

Getting Started – Pug

以前はJadeという名前でしたが、Jade2.0.0からPugという名前に変わりました。機能面でも追加や変更されたもの、削除されたものもあるのでJadeとPugに完全な互換性がないことに注意してください。

特徴としては、

  • 開始タグと終了タグがなく、インデントで階層を表現する(タブとスペースが混ざったりするとエラーになるのでEditorConfigを使います)
  • クラス名やID名がCSSの記法と同じドット(.)とシャープ(#)で分かりやすい
  • 別ファイルをSSIのようにインクルード(ファイルの中身だけ取得)できる
  • JavaScriptが書けるので変数やif文などが使える

変数やif文は一般的なWebサイトをマークアップするのであれば必ず必要なものでもないと思います。
効率化のために使うこともできますが、なるべく多くの人が理解出来て、触ることができるようにしておきたいので、個人的には複雑な書き方は避けています。
ですので、今回も基本的なマークアップの記法やインクルードといった範囲で紹介していきます。

  1. HTMLタグ
    1. 改行
    2. インライン要素
    3. サードパーティーコンテンツ
  2. 属性
    1. クラス属性
    2. ID属性
  3. コメント
  4. エスケープ
  5. インクルード(includes)

HTMLタグ

Pugには開始タグと終了タグはありません。タグ名を記述すればHTMLタグとして解釈してくれます。

//- Pug
div
<!-- HTML -->
<div></div>

タグ名の後に半角スペースを入れればその後にテキストが記述できますし、改行をしてインデントを付ければul > liのように入れ子にすることができます(この記事ではインデントをスペース2つで記述しています)。

//- Pug
p pタグです

ul
  li liタグです
  li liタグです
<!-- HTML -->
<p>pタグです</p>

<ul>
  <li>liタグです</li>
  <li>liタグです</li>
</ul>

インライン要素

スタイリングのために<p>の中に<span><br>のようなインライン要素を複数記述することがあると思います(HTML5以降はインライン要素という概念はなくなりましたが、今回は便宜上「インライン要素」と呼びます)。
いちばん簡単な書き方は直接HTMLタグを記述してしまうことです。

//- Pug
p pタグです<span class="span">spanタグです</span>pタグの続きです
<!-- HTML -->
<p>pタグです<span class="span">spanタグです</span>pタグの続きです</p>

もしくは、タグ名をインターポレーション(#[])で囲うことでPugとして解釈させることもできます。この書き方だと終了タグがないので、HTMLの直書きより読みやすくなります。

//- Pug
p pタグです#[span.span spanタグです]pタグの続きです
<!-- HTML -->
<p>pタグです<span class="span">spanタグです</span>pタグの続きです</p>

おすすめなのは、パイプライン(|)を使って、複数行で書くことです。

//- Pug
p pタグです
  span spanタグです
  | pタグの続きです

インライン要素が1つしかないときはHTMLタグを使って1行で書いてしまったほうが分かりやすいかもしれませんが、複数のインライン要素を記述する場合はパイプラインを使って改行しておいたほうが編集しやすくなります。

//- Pug
p pタグです<span>spanタグです</span>pタグの続きです<span>spanタグです</span>pタグの続きです

p pタグです
  span spanタグです
  | pタグの続きです
  span spanタグです
  | pタグの続きです

改行

<br>を使って改行する場合は以下のようになります。<p>タグの中は入れ子がなく、すべて並列になるので、インデントもすべて同じ位置になります。

//- Pug
p pタグです
  br
  | pタグです
  span spanタグです
  br
  | pタグです
<!-- HTML -->
<p>pタグです<br>pタグです<span>spanタグです</span><br>pタグです</p>

初めのうちはパイプラインと<br>などのインライン要素との位置関係が分からなくなって、コンパイルエラーを何回も起こしてしまうかもしれませんが、パターンが分かってくると自然と記述できるようになってきます。

サードパーティーコンテンツ

例えば、YouTubeやGoogle Maps、Google Analyticsなどで取得したHTMLをPugの記法に修正するのは面倒ですし、ミスが発生する恐れがあります。
HTMLをそのままPugファイルに貼り付けたい場合は以下のように、ドット(.)を入れてから改行をして、入れ子になった状態でHTMLを貼り付けるようにします。

//- Pug
.
  <iframe width="560" height="315" src="https://www.youtube.com/embed/1OKZOV-iLj4"></iframe>

タグ名やクラス名を入れても問題ありません。

.sw-ResponsiveEmbed.
  <iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12966.991898658345!2d139.7454329!3d35.6585805!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x481a93f0d2a409dd!2z5p2x5Lqs44K_44Ov44O8!5e0!3m2!1sja!2sjp!4v1491922441312" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe>
<!-- HTML -->
<iframe width="560" height="315" src="https://www.youtube.com/embed/1OKZOV-iLj4"></iframe>

<div class="sw-ResponsiveEmbed"><iframe src="https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d12966.991898658345!2d139.7454329!3d35.6585805!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x481a93f0d2a409dd!2z5p2x5Lqs44K_44Ov44O8!5e0!3m2!1sja!2sjp!4v1491922441312" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe></div>

属性

hrefsrcのような属性は半角の丸括弧の中に記述します。属性の間は半角スペースかカンマ(,)、あるいは両方で区切られていればOKです。
属性が複数あって1行にすると読みにくい場合は、改行やスペースで整形しても解釈してくれます。
ちなみにタグ名はli: aのようにコロン(:)を付けると、1行で記述することもできます(コロンを付けた要素にはテキストを記述することはできないので注意してください)。

//- Pug
ul
  li: a(href="example.com" target="_blank") aタグです
  li: a(href="example.com", target="_blank") aタグです
  li
    a(href="example.com",
      target="_blank") aタグです

input(type="checkbox" checked)
input(type="checkbox" checked="checked")
<!-- HTML -->
<ul>
  <li><a href="example.com" target="_blank">aタグです</a></li>
  <li><a href="example.com" target="_blank">aタグです</a></li>
  <li><a href="example.com" target="_blank">aタグです</a></li>
</ul>

<input type="checkbox" checked>
<input type="checkbox" checked="checked">

クラス属性

クラス属性はドット(.)で表すこともできます。

//- Pug
p.text
  a.link(href="example.com") aタグです

p.text: a.link(href="example.com") aタグです
<!-- HTML -->
<p class="text"><a class="link" href="example.com">aタグです</a></p>

<p class="text"><a class="link" href="example.com">aタグです</a></p>

複数のクラス属性を指定する場合はスペースを入れないようにドットをつなげていけばOKです。
もしくは、(class="")のように、属性として指定してもかまいません。

//- Pug
p.text.text-type1
  a.link.link-type1(href="example.com") aタグです

p.text(class="text-type1")
  a.link(class="link-type1" href="example.com") aタグです
<!-- HTML -->
<p class="text text-type1"><a class="link link-type1" href="example.com">aタグです</a></p>

<p class="text text-type1"><a class="link link-type1" href="example.com">aタグです</a></p>

(class="")の中にクラス名を記述するシチュエーションとしては、.u-hide@medium.u-8/12のようにスタイルシート側の記述時にバックスラッシュ(\)でのエスケープが必要なクラス名を使いたい場合などです。CSSの指定は以下のようになります。

/* CSS */
@media (min-width: 768px) {
  .u-hide\@medium {
    display: none;
  }  
}

.u-8\/12 {
  width: 66.666666667%;
}

ID属性

ID属性はシャープ(#)で表すこともできます。
ちなみにHTMLタグを省略してクラスかIDを指定すると<div>として解釈されます。

//- Pug
#id-attributes
<!-- HTML -->
<div id="id-attributes"></div>

スタイル属性

スタイル属性は少し記述が変わって、ブレース({})で囲ってからプロパティと値を記述します。ハイフンが含まれるプロパティはクオーテーション(""'')で囲う必要があるので注意してください。

//- Pug
p(style={color: "red", "font-weight": "bold"}) pタグです
<!-- HTML -->
<p style="color:red;font-weight:bold;">pタグです</p>

カンマ(,)の省略はできませんが、改行をして整形することはできます。

//- Pug
  p(style={
    color: "red",
    "font-weight": "bold"})
    | pタグです

コメント

PugのコメントにはHTMLに表示されるコメントと、Pug内だけで表示されるコメントの2種類があります。//のようにスラッシュ2つだけだとHTMLに残って、//-のようにハイフンをつけるとHTMLには残らなくなります。

//- Pug
// これはHTMLに表示されるコメントです

//- これはHTMLに表示されないコメントです
<!-- HTML -->
<!-- これはHTMLに表示されるコメントです-->

複数行のコメントもできます。

//- Pug
//
  これは複数行で表示されるコメントです
  2行目のコメントです
<!-- HTML -->
<!--
これは複数行で表示されるコメントです
2行目のコメントです
-->

IEなどのコンディショナルコメントはそのまま書けばOKです(インデントは正確に再現されないこともあるようです)。

//- Pug
<!--[if IE 8]>
<html lang="en" class="lt-ie9">
<![endif]-->
<!--[if gt IE 8]><!-->
<html lang="en">
<!--<![endif]-->
<!-- HTML -->
<!--[if IE 8]>
<html lang="en" class="lt-ie9">
<![endif]-->
<!--[if gt IE 8]><!-->
<html lang="en">
<!--<![endif]-->

エスケープ

HTML文書の中ではセキュリティのために5つの文字列(& < > " ')をエスケープすることが推奨されています。Pugでは、記述方法を少し変えるだけでエスケープもしてくれます。

//- Pug
p= "Q&Aです"
<!-- HTML -->
<p>Q&amp;Aです</p>

イコール(=)の後にあるテキストのエスケープが有効になり、パイプライン(|)が入るとエスケープが解除されるようです。

//- Pug
p= "Q&Aです"
  br
  | Q&Aです
  br
  = "Q&Aです"
<!-- HTML -->
<p>Q&amp;Aです<br>Q&Aです<br>Q&amp;Aです
</p>

インクルード(Includes)

インクルードを使うと、別ファイルとして作成しているPugファイルの中身を挿入することができます。
例えば、ローカルナビゲーションやバナーのような、カテゴリーなどで使いまわせる共通エリアの管理に便利です。

例えばバナーエリアをPugで作成します。

//- Pug
.st-SideBanner
  .st-SideBanner_Inner
    aside.st-SideBanner_Item
      a.banner-Side(href="#")
        .banner-Side_Image
          img(src="#" alt="")
    aside.st-SideBanner_Item
      a.banner-Side(href="#")
        .banner-Side_Image
          img(src="#" alt="")

バナーエリアを挿入するPugファイルで以下のようにインクルードします(ここでは/index.pug/_include/_SideBanner.pugを挿入する想定です)。ファイルの拡張子である.pugは省略もできます。

//- Pug
include _include/_SideBanner.pug

basedirオプションを指定している場合はルート相対パスで指定することができるので、以下のような記述が可能です。

//- Pug
include /_include/_SideBanner.pug

API Reference – Pug

まとめ

複雑な処理をしなければPugはそれほど難しいものではないと分かっていただけたでしょうか。

覚えておくルールは以下の9個です。

  1. タグ名はHTMLタグになる
  2. 改行をしてインデントをつければ入れ子になる
  3. インライン要素や改行にはパイプライン(|)を使う(ここだけ慣れが必要)
  4. HTMLはドット(.)で終わる要素の中に入れておけば解釈される
  5. 属性は丸括弧内に記述する
  6. クラス属性はドット(.)、ID属性はシャープ(#)で表す
  7. コメントにはHTMLとして出力されるものと、されないものがある
  8. イコール(=)を使えばエスケープできる
  9. インクルード(include [ファイル名へのパス])で共通化したファイルを挿入できる

多少の慣れは必要になりますが、学習コストとしてはそれほど大きなものではないと思っています。
以前、大規模な案件で、普段コードを触らないディレクター3人もテキストやリンクの修正でPugを使ってもらったことがありました。

Pugのいちばんのメリットは、後から編集しやすいコードになることだと思っています。
Emmetのようなツールでは、速く書くことはできても、結局はHTMLなので編集のしやすさは変わりません。
Pugであれば、Emmetのように速く書くこともできますし、編集しやすいコードに保つこともできるようになります。
ぜひ試してみてください。