> ## Documentation Index
> Fetch the complete documentation index at: https://developers.hubspot.jp/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# カスタムモジュールのコーディング

> カスタムモジュールは、ウェブサイト全体で使用できる再利用可能な要素です。速度、ユーザーエクスペリエンス、アクセシビリティーに関するベストプラクティスを考慮しながら構築します。

ページ、ブログ、[見積もり](/cms/start-building/building-blocks/templates/quotes)（英語）のモジュールを作成する場合は、モジュールのコンテンツ、スタイル設定、機能を制御するための3つのフロントエンド関連ファイルがモジュール内にあります。

* module.html
* module.css
* module.js

<Info>
  Eメールモジュールは、module.cssとmodule.jsに対応していません。理由としては、EメールクライアントではJavaScriptがサポートされないことと、リンクされたCSSファイルのサポートが限られていることが挙げられます。
</Info>

これらのファイルは、モジュールのインスタンスがページ上にある場合には、常にページ上にレンダリングされます。

特定のページ内に同じモジュールのインスタンスが複数ある場合、HubSpotによってそのモジュールの`module.css`と`module.js`が1回だけ読み込まれます。既定では、`module.css`と`module.js`が非同期的に読み込まれることはありませんが、モジュールのmeta.jsonに[css\_render\_options and js\_render\_options](https://developers.hubspot.jp/docs/cms/building-blocks/modules/configuration)を含めることで、この動作を変更できます。

モジュールはデザインマネージャー内で作成するか、または[HubSpot CLI](https://developers.hubspot.jp/docs/guides/cms/tools/local-development-cli)を使用してローカル環境で作成できます。モジュールファイルは、デザインマネージャー上ではマルチペインエディターに表示されます。

ローカルでモジュールを確認すると、ファイルはmodule-name.moduleフォルダーに格納されます。

<Frame>
  <img src="https://www.hubspot.com/hubfs/Knowledge_Base_2021/Developer/cms-dev-custom-module1.png" alt="cms-dev-custom-module1" />
</Frame>

モジュールの作成と管理にデザインマネージャーまたはCLIのいずれを使用するかは、チームの状況や好みに応じて決めます。

<Frame>
  <img src="https://www.hubspot.com/hubfs/Knowledge_Base_2021/Developer/cms-dev-custom-module0.png" alt="cms-dev-custom-module0" />
</Frame>

[効率的な開発者ワークフローの構築](/cms/start-building/introduction/developer-environment/creating-an-efficient-development-workflow)に記載されている推奨事項を参照してください。

## HTML + HubL（module.html）

module.htmlファイルはHTMLおよびHubLを対象としています。一般に、モジュールがページエディターまたはテンプレートファイルのどこに配置されているかに応じて、module.htmlファイルの内容がどこにレンダリングされるかが決まります。

このファイルは、モジュールがどこに配置されていても、ページ内で[HubL include](https://developers.hubspot.jp/docs/cms/hubl#including-files-in-files)と同じように動作します。module.htmlファイルからは、[HubLを使ってモジュールのフィールド値にアクセスできます](https://developers.hubspot.jp/docs/cms/building-blocks/modules#using-module-field-data-to-render-html)。

## CSS（module.css）

モジュールにCSSを追加するには、`module.css`ファイルを使用します。

一般に、`module.css`ではHubLのごく一部のサブセットのみがサポートされます。ただし、モジュールとリンクされたアセットとして画像を追加する場合に[`module_asset_url("my-image.png")`](/cms/reference/hubl/functions#module-asset-url)を使用できます。これにより、画像などのアセットをモジュール自体にパッケージ化できます。例：

```css theme={null}
.testimonial-module__wrapper {
  background: url("{{ module_asset_url("bg-pattern.png") }}");
  background-repeat: repeat;
  min-height: 200px;
  width: 100%;
  display: block;
}
```

ここでは、モジュール内のフィールドに基づいてモジュールが動的に変化するように、モジュールのCSSを設定する方法を説明します。

### モジュールフィールド値に基づくスタイル

モジュールのフィールドに基づいてモジュールのスタイルに効果を与えるには、いくつかの方法があります。特定の用途に応じて最適な方法を選択してください。

* [CSSクラス](#css-classes)
* [require\_cssブロック](#require-css-block)
* [インラインスタイル](#inline-styles)

#### CSSクラス

編集時に選択可能なオプションをモジュールのスタイルにあらかじめ設定しておくには、モジュールフィールドを追加して、`module.css`ファイルのCSSクラスに対応するクラスを`module.html`ファイル内で設定することができます。

例えば、画像とテキストの1つのモジュールがある状況が考えられます。選択フィールドに基づいてテキストの右または左に画像を制作担当者が配置できるようにする必要がありします。このためには、`module.html`と`module.css`ファイルを次のように設定できます。

```hubl theme={null}
<!-- module.html -->

<section class="img-text__wrapper img-text--{{ module.positioning }}" aria-label="{{ module.heading }}">
  {# module.position is a choice field with two values "img-left" or "img-right". This dictates the order they appear on desktop. Controlled by CSS #}
  <div class="img-text__img">
      <img src="{{ module.image.src }}" alt="{{ module.image.alt }}">
  </div>
  <div class="img-text__text">
      <h2>
        {% inline_text field="heading" value="{{ module.heading }}" %}
      </h2>
      {% inline_rich_text field="text" value="{{ module.text }}" %}
  </div>
</section>
```

```css theme={null}
/* module.css */

/* CSS that makes the image show adjacent to the text,
and positioned based on the positioning field.*/

/* The media query ensures that on mobile the image
will always appear above the text for
visual consistency. */

@media (min-width: 768px) {
  .img-text__wrapper {
    display: flex;
    align-items: row;
  }
  .img-text__img,
  .img-text__text {
    flex: 1;
    padding: 10px;
  }
  .img-text--img-right {
    flex-direction: row-reverse;
  }
}
```

### require\_cssブロック

特定のプロパティーを制作担当者が直接制御できる必要があり、クラスが適切でない場合は、`require_css`ブロックにスタイルタグを使用する方法が最適です。

クラスを使用することなく制作担当者が特定のプロパティーを直接制御できるようにするには、`require_css`タグ内に`module.html`ファイルにスタイルを追加できます。例：

```hubl theme={null}
<div class="img__wrapper">
  {% if module.image.src %}
    {% set sizeAttrs = 'width="{{ module.image.width }}" height="{{ module.image.height }}"' %}
    {% if module.image.size_type == 'auto' %}
      {% set sizeAttrs = 'style="max-width: 100%; height: auto;"' %}
    {% elif module.image.size_type == 'auto_custom_max' %}
      {% set sizeAttrs = 'width="100%" height="auto" style="max-width: {{ module.image.max_width }}px; max-height: {{ module.image.max_height }}px"' %}
    {% endif %}
    <img src="{{ module.image.src }}" alt="{{ module.image.alt }}" {{ sizeAttrs }}>
  {% endif %}
</div>

{% require_css %}
  <style>
    img {
    border-width:{{ module.border_width }}px;
    border-color:rgba({{ module.border_color.color|convert_rgb}},{{ module.border_color.opacity/100 }});
    border-style: solid;
    }
  </style>
{% end_require_css %}
```

`module.html`ではHubLをレンダリングできるので、モジュールフィールド値をCSS変数として使用できます。制作担当者がページエディター上でフィールドを更新すると、該当するCSSが更新されます。このようなブロックによって、`<style>`タグが`standard_header_includes`ステートメント内のページの`<head>`に移されます。

CSSを`scope_css`タグで囲むことにより、CSSをモジュールインスタンスにのみ適用することもできます。例えば、上記のモジュールコードは次のように変更できます。

```hubl theme={null}
<div class="img__wrapper">
  {% if module.image.src %}
    {% set sizeAttrs = 'width="{{ module.image.width }}" height="{{ module.image.height }}"' %}
    {% if module.image.size_type == 'auto' %}
      {% set sizeAttrs = 'style="max-width: 100%; height: auto;"' %}
    {% elif module.image.size_type == 'auto_custom_max' %}
      {% set sizeAttrs = 'width="100%" height="auto" style="max-width: {{ module.image.max_width }}px; max-height: {{ module.image.max_height }}px"' %}
    {% endif %}
    <img src="{{ module.image.src }}" alt="{{ module.image.alt }}" {{ sizeAttrs }}>
  {% endif %}
</div>

{% require_css %}
<style>
  {% scope_css %}
    img {
    border-width:{{ module.border_width }}px;
    border-color:rgba({{ module.border_color.color|convert_rgb}},{{ module.border_color.opacity/100 }});
    border-style: solid;
    }
  {% end_scope_css %}
</style>
{% end_require_css %}
```

### インラインスタイルを追加する

わずかな数のプロパティーを制作担当者が細かく制御できる必要があり、クラスが適切でない場合は、HTMLのスタイル属性に値を直接追加することができます。

```hubl theme={null}
{# Module.html #}
<div style="background: rgba({{ module.bg_color.color|convert_rgb }},{{ module.bg_color.opacity/100 }});">
  {% inline_rich_text field="richtext" value="{{ module.richtext }}" %}
</div>
```

プロパティーの数が多くてコードが読みにくくなった場合は、`require_css`ブロック手法への切り替えを検討してください。

### 特定のCSSファイルをインポートする

`require_css`は、module.htmlに追加することで、特定のモジュールまたはテンプレートの表示に特定のCSSファイルが必要なことをHubSpotに示すためのHubL関数です。cssファイルを指すリンクタグが、`standard_header_includes`内でページの`<head>`に追加されます。

`require_css`関数では、特定のページ上のモジュールやテンプレートで同じCSSファイルが何回必要とされるかにかかわらず、そのCSSファイルが1回だけ読み込まれます。複数のモジュール間でスタイルが共有される可能性があっても、サイトの全ページで使われるメインのスタイルシートにCSSを直接追加することが望ましくない状況では、この方法が優れています。

`require_css`もリンクによるCSSファイルも同じ目的で利用できますが、`require_css`はフィールド値に基づく条件付きで使用できます。これにより、不要なコードの読み込みが防止されます。

```hubl theme={null}
<!-- module.html -->
{{ require_css(get_asset_url("/modules/shared_layout_styles.css")) }}
```

## JavaScript（module.js）

JavaScriptをモジュールに追加するには、`module.js`ファイルを使用します。

`module.css`ファイルと同様に`module.js`ファイルでもHubLはサポートされません。

### フィールド値に基づくスクリプト記述

モジュールにはいくつかの作成方法があり、フィールド値に基づくJavaScriptの動作が異なります。どの方法をどのような状況で使用するかを理解しておくことで、モジュールが使用される全てのページでパフォーマンス面でのメリットが得られます。

例えば、カスタム画像モジュールがあり、Lightboxで画像が開くように制作担当者が設定できる必要があるとします。制作担当者がこの設定を必要とするのは特定の画像のみで、全てのモジュールインスタンスとは限りません。

### データ属性

データ属性は、開発者が要素に追加するHTML 5標準のカスタム属性です。`class="yourClassName"`と同じように、`data-your-attribute="yourValue"`が全ての要素でサポートされます。

```hubl theme={null}
<!-- module.html-->
<div class="img-module img-module__wrapper" data-lightbox="{{ module.is_lightbox_enabled }}" data-caption="above">
  <!-- module.is_lightbox_enabled is a boolean field, module.caption_position is a choice field. -->
  {% if module.image.src %}
    {% set sizeAttrs = 'width="{{ module.image.width }}" height="{{ module.image.height }}"' %}
    {% if module.image.size_type == 'auto' %}
      {% set sizeAttrs = 'style="max-width: 100%; height: auto;"' %}
    {% elif module.image.size_type == 'auto_custom_max' %}
      {% set sizeAttrs = 'width="100%" height="auto" style="max-width: {{ module.image.max_width }}px; max-height: {{ module.image.max_height }}px"' %}
    {% endif %}
    <img src="{{ module.image.src }}" alt="{{ module.image.alt }}" {{ sizeAttrs }}>
  {% endif %}
</div>
```

データ属性を使用すると、module.jsファイルでの処理用としてモジュールインスタンスのフィールド値を渡すことができます。

この値をmodule.jsファイル内で使用するには、モジュールの全てのインスタンスに対してループ処理を行う必要があります。モジュールに固有のクラス名をモジュールの最も外側にあるラッパー要素に追加することで、その名前を対象として各モジュールインスタンスをループ処理できます。

```js theme={null}
// module.js

let imgModules = document.getElementsByClassName("img-module");
Array.from(imgModules).forEach(function (element) {
  // loop through each of the instances of the module
  // set data attributes to variables to make it easy to work with
  let isLightboxEnabled = element.dataset.lightbox;
  let captionStyle = element.dataset.caption;
  if (isLightboxEnabled) {
    element.addEventListener("click", function () {
      showLightbox(captionStyle); // Execute your code for the action you want to take, you can pass your data attributes into functions from libraries.
    });
  }
});
```

データ属性によって、module.js内で各モジュールインスタンスのフィールド値を取得できます。

### require\_jsブロック

JavaScriptテンプレートライブラリーや、Vue.jsまたはReact.jsなどのリアクティブフレームワークを使用する高度なケースでは、データの出力だけを自分で対応し、レンダリングはフレームワーク側で処理する方が望ましい場合があります。

この場合、テンプレートスクリプトからアクセス可能な変数を提供するには、[`require_js`](/cms/reference/hubl/functions#require-js)ブロックで囲んだスクリプトタグを使用します。

```hubl theme={null}
{% require_js %}
<script>
  let myArray = [
    {%- for item in module.repeating_text_field -%}"{{ item }}",{%- endfor -%}
  ];
</script>
{% end_require_js %}
```

この手法は、レンダリング元となる初期データセットを高度なアプリケーションに提供する際に役立ちます。これにより、データを取得するための最初のJavaScript呼び出しが不要になります。

### require\_js

[`require_js`](/cms/reference/hubl/functions#require-js)は、特定のモジュールまたはテンプレートの正常な読み込みに特定のJavaScriptファイルが必要であることを、HubSpotに示すためのHubL関数です。この関数には、ファイルへのパスと、ファイルの追加先となる位置（“head”または“footer”）の2つの入力パラメーターがあります。

モジュール内では、`require_js`をmodule.htmlにのみ追加できます。`require_js`ステートメントで参照されるJavaScriptファイルは、ページ内のモジュールやテンプレートで何回必要とされるかにかかわらず、ページごとに1回だけ読み込まれます。これによりHTTPリクエスト数が減少し、コードの重複も防止できます。

これは次のような状況で役立ちます。

* 同じJavaScriptを必要とする複数のモジュールまたはテンプレートがある場合、`require_js`を使用することでモジュール間でスクリプトを共有できます。
* webpackのようなJavaScriptバンドラーを使用する場合、jsファイルを特定の1つの位置に出力する方が簡単なことがあります。`require_js`を使用すると、JavaScriptをモジュールに関連付けることができます。

`require_js`もリンクによるJavaScriptファイルも同じ目的で利用できますが、`require_js`にはフィールド値に基づく条件を付けることができます。これにより、不要なコードの読み込みが防止されます。さらに、必要な場合にはJavaScriptをheadに読み込む方法もあります。

<Tip>
  JavaScriptはレンダリングの妨げになるので、[`require_js`](/cms/reference/hubl/functions#require-js)がJavaScriptを配置する位置は既定でfooterになっています。[パフォーマンスの最適化に関する詳細をご覧ください。](/cms/best-practices/testing-staging-performance/speed)
</Tip>

## 関連情報

* [CMS Hubで構築したウェブサイトのパフォーマンス最適化](/cms/best-practices/testing-staging-performance/speed)
* [モジュール](https://developers.hubspot.jp/docs/guides/cms/content/modules/overview)
* [モジュールフィールド](https://developers.hubspot.jp/docs/guides/cms/content/fields/overview)
