htmx の基本


htmx とは

htmx は、HTML の属性だけで Ajax や部分更新、履歴管理といった高度なインタラクションを実現できる軽量な JavaScript ライブラリです。JavaScript コードをほとんど書かずに、既存の HTML 要素に hx- から始まる属性を付与するだけで機能を追加できるのが特徴です。

a-blog cms には Ver. 1.3(2011年リリース)から、POST リクエストで部分的に HTML を取得・表示できる post include 機能が存在しました。この機能により、ページの一部だけをサーバーから取得して差し替える仕組みを長く提供してきましたが、利用できるのは POST メソッドのみでした。

今回 a-blog cms Ver. 3.2 からは、この post include の発想を引き継ぎつつ、より柔軟でオープンな標準技術である htmx を採用しました。htmx では hx-post だけでなく、hx-get をはじめとする多様な HTTP メソッドを利用でき、より多くのユースケースに対応できます。これにより、長年推奨してきた post include 機能から、モダンで汎用的な htmx への移行を推奨しています。

主な特徴

  • シンプルな記述: hx-gethx-post などの属性を HTML に追加するだけで、非同期通信やコンテンツの差し替えが可能です。

  • サーバーサイドと相性が良い: 部分的な HTML(フラグメント)をサーバーから返すことで、複雑な JavaScript フレームワークを使わずに SPA ライクな体験を実現できます。

  • プログレッシブエンハンスメント: htmx を使ったページは、JavaScript が無効でも通常のリンクやフォームとして動作します。


基本構文の例

リンクで部分更新 : hx-get

<a href="/news/page/2"
   hx-get="/news/page/2/tpl/include/entry/news-list.html"
   hx-target="#news-list"
   hx-swap="innerHTML">
  もっと見る
</a>

<ul id="news-list">
  <!-- モジュールで出力された記事一覧 -->
</ul>

この例では、リンクをクリックすると /news/page/2GET リクエストを送り、 include/entry/news-list.html のテンプレートを利用し、news のカテゴリーの page/2 の結果の HTML を #news-list の中身に置き換えます。ページ全体のリロードは行われません。

フォーム送信で部分更新 : hx-post

<form hx-post=""
      hx-target="#search-result"
      hx-swap="outerHTML">
  <input type="hidden" name="tpl" value="/include/entry/search-result.html">
  <input type="text" name="keyword" placeholder="キーワード">
  <button type="submit" name="ACMS_POST_2GET_Ajax">検索</button>
</form>

<div id="search-result">
  <!-- 送信結果がここに表示される -->
</div>

この例では、フォーム送信時に POST リクエストをサーバーに送り、include/entry/search-result.html のテンプレートを利用し、キーワード検索結果の HTMLを #search-result 全体と置き換えます。


事前準備について

Ver. 3.2 からは不要に

a-blog cms Ver. 3.2 では、標準の 組み込み JavaScript に htmx が含まれるようになりました。これにより、HTML 要素に hx-gethx-post の属性を記述するだけで自動的にライブラリが読み込まれるため、事前の設定は必要ありません。

なお、JavaScript などで htmx の属性を後から付加する場合、ライブラリが読み込まれないタイミングが発生する可能性があります。そのような場合は、以下の <meta> タグをあらかじめ入れておくことで対応できます。

<meta name="acms-htmx" content="enable">

Ver. 3.1 までは、htmx.org のドキュメントに沿って <head> 内でライブラリを読み込み、設定を記述する必要があります。例えば以下のような準備が必要でした。参考として共有しておきます。

<script src="/js/htmx.min.js"></script>

<script>
  htmx.config.historyCacheSize = -1;
  htmx.config.refreshOnHistoryMiss = true;

  addEventListener('htmx:beforeHistoryUpdate', function (event) {
    const proposedUrl = event.detail.history.path;
    let customUrl = proposedUrl;
    if (proposedUrl.includes('/include/htmx/')) {
        customUrl = proposedUrl.replace(/\/include\/htmx\/.*\.html/, '');
    }
    event.detail.history.path = customUrl;
  });

  document.addEventListener("htmx:configRequest", function(event) {
      const csrfToken = document.querySelector('meta[name="csrf-token"]').content;
      event.detail.headers['X-CSRF-Token'] = csrfToken;
  });

  addEventListener('htmx:afterSwap', function (event) {
    ACMS.Dispatch(event.target);
  });
</script>

Twigテンプレートの有効化


管理画面 > テーマ から、使用テーマの編集画面に入り「Twigテンプレート」を有効にすることで、Twig記法が利用することができるようになります。

テーマ設定のTwigテンプレートを有効に選択する
テーマ設定画面

もしくは、テーマ内の「template.yaml」を以下のように設定することでも可能です。

tpl_top : index.twig
tpl_index : index.twig
tpl_detail : _entry.twig
tpl_404 : 404.twig
tpl_admin : admin.html
tpl_entry_edit : _entry.twig
tpl_login : _member-admin/login.html
tpl_twig : enabled

ブロックエディター


ブロックエディターでは、テキスト、画像、ファイルなどのコンテンツを「ブロック」単位で自由に組み立てることができ、みたままの視認性と柔軟性が大幅に向上します。

主な特徴・機能

  • HTMLのコピーアンドペーストに対応

  • スラッシュコマンド

    • マウスでブロックを選択しなくても、直感的にブロック挿入ができるようになります。

  • メディア機能に対応

    • メディアから画像やファイルを挿入することが可能

    • 大元のメディアで画像を差し替えても自動でブロックエディタ側も連動

  • インライン要素にカスタムクラス

    • 設定画面で設定した任意のクラスをインライン要素に設定可能

  • ブロック要素にカスタムクラス

    • 設定画面で設定した任意のクラスをブロック要素に設定可能

  • 2カラム・3カラムレイアウトに対応

    • みたままの状態でマルチカラムレイアウトに対応

  • マークダウンに対応

    • マークダウン記法で入力すると自動的にHTMLに変換します

使用方法

編集テンプレートのカスタムフィールド例

カスタムフィールドをブロックエディタにする場合は、以下のように記述します。

記述ルール

  • js-block-editor クラスを付与した要素が、ブロックエディタとして初期化

  • data-target 属性で、エディタ本体を表示する要素を指定

  • data-html 属性で、編集後のHTMLが格納される input 要素を指定

  • 必ず <input type="hidden" name="xxxxx:extension" value="block-editor" /> を指定

<div class="js-block-editor" data-target=".js-target" data-html=".js-html">
  <div class="js-target acms-admin-form-width-full"></div>
  <input type="hidden" class="js-html" name="hoge" value="{hoge}">
  <input type="hidden" name="field[]" value="hoge">
  <input type="hidden" name="hoge:extension" value="block-editor" />
</div>

表示テンプレートの出力例

ブロックエディタで編集したHTMLを出力するには、以下のように記述します。

記述ルール

  • 必ず raw (ACMSテンプレート) or safe_html (Twigテンプレート)校正オプションを指定

{hoge}[raw] <!-- ACMSテンプレートの場合 -->
{{ hoge|safe_html }} <!-- Twigテンプレートの場合 -->

基本設定

初期設定が js/config.js で設定されています。

blockEditorMark: '.js-block-editor',
blockEditorConfig: {
  setMainImageMark: '.js-block-editor-set-main-image',
  tableScrollableWrapperClass: 'acms-table-scrollable',
  tableScrollableClass: 'js-table-unit-scroll-hint',
  imageLightbox: 'SmartPhoto',
  /**
    * BlockEditorコンポーネントに渡されるprops
    */
  editorProps: {
    editorProps: {
      attributes: {
        /**
          * @description この値を変更するときは、system/src/scss/global/_variables.scss の$entry-classも変更すること
          */
        class: 'acms-entry',
      },
    },
  },
},

メイン画像設定機能

メディア画像のメニューにメイン画像に設定するボタンが用意されています。このボタンを押した時に blockEditorConfig.setMainImageMark に設定されているセレクタの要素(メディアのカスタムフィールド)に、選択している画像をセットします。

メイン画像に設定ボタンを押すことにより、メイン画像に設定できます。
メイン画像に設定する

カスタムフィールド例

<div class="js-media-field">
  <div class="js-droparea" data-thumbnail="{entry_main_image@thumbnail}" data-type="image" style="width:200px"></div>
  <p class="js-text acms-admin-text-danger" style="display:none">許可されていないファイルのため挿入できません。</p>
  <div class="acms-admin-margin-top-mini">
    <button type="button" class="js-insert acms-admin-btn" data-type="image">メディアを選択</button>
  </div>
  <input type="hidden" name="entry_main_image" value="{entry_main_image}" class="js-value js-block-editor-set-main-image" />
  <input type="hidden" name="field[]" value="entry_main_image" />
  <input type="hidden" name="entry_main_image:extension" value="media" />
</div>

従来は、メディア・画像ユニットのみメイン画像に設定することができましたが、Ver. 3.2 から メディアのカスタムフィールドを、Entry_Summaryなどのモジュールで、メイン画像として出力できるようになりました。


テーブルのクラス設定

テーブルのメニューにテーブルを横スクロールして表示するように設定するボタンが用意されています。このボタンを押した時、テーブルのHTMLに設定されるクラスを設定できるようになっています。

スクロールするテーブルにするボタンを押すことで、テーブルが横スクロースされて表示できるようになります。
スクロールするテーブルにする

設定

説明

初期値

blockEditorConfig.tableScrollableWrapperClass

table要素の親要素につけるクラス

‘acms-table-scrollable’

blockEditorConfig.tableScrollableClass

table要素につけるクラス

‘js-table-unit-scroll-hint’

スクロールするテーブルのHTML例

<div class="tableWrapper acms-table-scrollable">
  <table class="js-table-unit-scroll-hint" data-scrollable="true">
    <tbody>
      <tr>
        <td>...</td>
        <td>...</td>
        <td>...</td>
      </tr>
    </tbody>
  </table>
</div>

画像の拡大機能の設定

画像の拡大を行うための識別子として、画像リンクの data-rel 属性に、設定する値を設定できます。デフォルト値は SmartPhoto で、標準ではSmartPhotoを使って画像を拡大させます。

また data-group 属性にエントリーID が自動で付与されます。

設定

説明

初期値

blockEditorConfig.imageLightbox

table要素の親要素につけるクラス

‘SmartPhoto’

メディア画像の出力例

<a href="/path/to/sample.png?v=20250710172457" data-rel="SmartPhoto" data-group="169">
  <img src="/path/to/sample.png?v=20250710172457" class="unit-id-169 in-view" width="1200" height="675" loading="lazy" data-mid="50" alt="xxxxxx">
</a>

出力HTMLを囲う要素のクラス名設定

ブロックエディタで出力されるコンテンツ全体を囲む要素に、任意のクラス名を設定することができます。このクラスは管理画面のブロックエディタ編集画面に反映され、独自のスタイル調整に活用できます。

設定

説明

初期値

blockEditorConfig.editorProps.editorProps.attributes.class

コンテンツを囲う親divに設定されるクラス名

‘acms-entry’

編集画面のHTML例

<div class="js-block-editor" data-target=".js-target" data-html=".js-html">
  <div class="js-target acms-admin-form-width-full">
    <div class="acms-admin-block-editor-container">
      <div class="acms-admin-block-editor">
        <div class="acms-admin-block-editor-content" aria-expanded="false">
          <div contenteditable="true" translate="no" class="tiptap ProseMirror entry-style" tabindex="0" autocomplete="off" autocorrect="off" autocapitalize="off" aria-expanded="false">
            編集しているHTML...
          </div>
        </div>
      </div>
    </div>
  </div>
  <input type="hidden" class="js-html" name="xxxxxxxx" value="xxxxxxxxx">
</div>

設定を変更する場合

設定を変更する際は、js/config.js を直接編集しないでください
将来的なアップデートやテーマの互換性維持のため、設定の上書きはテーマ内の HTML テンプレートなどで行ってください。

例:テンプレート内での上書き方法

<script>
ACMS.Ready(() => {
  ACMS.Config.blockEditorConfig.tableScrollableWrapperClass = 'c-table__wrapper';
  ACMS.Config.blockEditorConfig.tableScrollableClass = 'c-table__scrollable';
});
</script>

エディタのカスタマイズ

ブロックエディタのカスタマイズを管理画面から行えます管理画面 > 編集画面 > ブロックエディタ設定 から行えます。

管理ページのブロックエディター設定画面で、ブロックエディタのメニューや、追加できるブロックをカスタマイズできます。
ブロックエディター設定画面

画像リサイズ

ブロックエディターで追加したメディア画像のリサイズサイズを指定します。ブロックエディターでは、全てのメディア画像がこのサイズにリサイズされます(指定サイズより小さい画像はリサイズされません)

画像リサイズの設定をピクセスで指定します。
画像リサイズ設定

ブロックメニュー

ブロックエディターで追加できるブロック項目を設定できます。

ブロックメニューを追加・削除できます。
ブロックメニュー設定画面
  • ブロック:ブロックの種類

  • ラベル:メニュー表示で表示されるテキスト

  • クラス:追加したブロック要素に付与されるクラス

  • グループ:メニュー表示するときのグループを指定します。空の場合、上で設定されているグループが設定されます。

追加ブロックのメニュー表示に反映されます。
追加ブロックのメニュー表示

メニュー設定

メニュー設定では、テキストを選択したときのメニュー項目の制御ができます。不要な要素があればチェックを外してください。

使いたいメニューにはチェックを入れ、不要なメニューはチェックをはずします。
テキストのメニュー設定画面
テキストを選択することで、メニューが表示されます。
テキストの装飾メニュー

カスタムクラス

カスタムクラスでは、選択したテキストを span で囲って任意のクラスを設定するときの、クラスを設定できます。

*「メニュー設定」で「カスタムクラス」にチェックが入っている必要があります。

ラベルとクラス名を好きな数だけ設定します。
カスタムクラス設定画面
選択したテキストに、カスタムクラスで「注意ラベル」を設定してる例です。
カスタムクラスのメニュー表示例

カラーパレット

ブロックエディター内で使用するカラパレットの選択肢を設定します。

16進数のカラコードで指定します。(例:#330000)
カラーパレット設定画面
色選択UIの下に、設定したカラーのリストが表示されます。
カラーパレットの表示例

文字サイズ

選択したテキストのフォントサイズを変更する時の、文字サイズの選択肢を設定します。

*「メニュー設定」で「文字サイズ」にチェックが入っている必要があります。

ラベルと値(px,em,rem)のセットで、選択肢を設定します。
文字サイズ設定画面
選択したテキストの文字サイズを、文字サイズ選択肢から選択したサイズに変更します。
文字サイズのメニュー表示例

フォント

選択したテキストのフォントを変更する時の、フォントの選択肢を設定します。

*「メニュー設定」で「フォント」にチェックが入っている必要があります。

ラベルとフォント名のセットで、選択肢を設定します。
フォント設定画面
選択したテキストのフォントを、フォント選択肢から選択したフォントに変更します。
フォントのメニュー表示例

コードをハイライトする


この組み込みJSを使用するとこで、ブログ記事やコンテンツ内のソースコードに対して、highlight.js を使って自動的にハイライト表示されるように設定されています。

使用例

以下のように pre > code で囲まれた範囲にスタイルがつきます。

<pre>
  <code>
  ...
  </code>
</pre>

設定

初期設定が js/config.js で設定されています。

highlightMark: 'pre',
highlightConfig: {
  theme: 'atom-one-light', // テーマを指定(https://highlightjs.org/examples を参照)
  languages: ['bash', 'css', 'javascript', 'json', 'php', 'sql', 'typescript', 'xml', 'yaml', 'twig'], // ハイライトする言語を指定(https://highlightjs.org/download を参照)
},

項目

説明

初期値

highlightMark

pre タグ内のコードブロックが自動的にハイライトされます。

‘pre’

highlightConfig.theme

テーマを指定します。指定するテーマは、 https://highlightjs.org/examples を参照ください。

‘atom-one-light’

highlightConfig.languages

ハイライトする言語を指定します。

['bash', 'css', 'javascript', 'json', 'php', 'sql', 'typescript', 'xml', 'yaml', 'twig']

設定を変更する場合

設定を変更する際は、js/config.js直接編集しないでください
将来的なアップデートやテーマの互換性維持のため、設定の上書きはテーマ内の HTML テンプレートなどで行ってください。

例:テンプレート内での上書き方法

<script>
ACMS.Ready(() => {
  ACMS.Config.highlightConfig.theme = 'atom-one-dark';
  ACMS.Config.highlightConfig.languages = [...ACMS.Config.highlightConfig.languages, 'python', 'typescript']; // pythonとtypescriptを追加
});
</script>

ブロックエディターユニット


ブロックエディターユニットは、テキスト、画像、ファイルなどの様々なコンテンツを「ブロック」単位で自由に組み立てることができ、表示みたまま編集することができ、記事やページの構成を直感的に編集できます。

表示みたまま編集可能なリッチなエディタ
ブロックエディタ編集画面

使用するための設定

管理画面 > 編集画面 > 編集設定 の「ユニットメニュー」にブロックエディターを追加します。

  • モードを「block-editor」を設定

  • ラベルは任意のラベル

モードには「block-editor」を設定してください。
ユニットメニュー画面

上記が設定できると、エントリー編集画面の「ユニットを追加」ボタンから、ブロックエディタを追加できます。

ユニット追加ボタンを押すと、ユニットの選択肢が表示されるので、設定で追加したブロックエディターを追加します。
エントリー編集画面のユニット追加ボタン

ブロックエディターの設定・カスタマイズ

ブロックエディターの基本的な使い方や設定方法、カスタマイズ手順については、
「組み込みJSのブロックエディター」セクションで詳しく解説しています。

ブロックエディターについて詳しく見る