Tailwind CSSで画像を他の画像に合わせて切り抜く(マスクする)方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、Tailwind CSSで画像を他の画像に合わせて切り抜く(マスクする)方法をご紹介します。

なお、本稿の内容は v4.1.12(2025年8月18日時点の最新版)のTailwind CSSを前提としています。

実現したいこと

冒頭、実現したいことを整理します。

以下のように、星型の画像の形に合わせて海の画像を切り抜いて表示することが今回のゴールです。

画像をマスクする過程のイメージ。星型の画像の形に合わせて海の画像を切り抜いて当てはめている。
画像をマスクする過程のイメージ

PhotoshopFigmaを用いてあらかじめ切り抜いた画像を用意する方法もありますが、今回はTailwind CSSだけで実現します。

ユーティリティクラスのmask-*でマスクができる

Tailwind CSSのユーティリティクラスである、mask-*シリーズを使用すると画像のマスクができます。(v4.1.0で追加)

tailwindcss.com

基本形のmask-[<value>]は、CSSプロパティのmask-imageに相当します。

mask-imageは2023年12月にすべての主要ブラウザで対応され、CSSだけで画像のマスクが可能になりました。

developer.mozilla.org

mask-[<value>]には切り抜きたい形の画像のURLを指定した上で、background-imageに相当するbg-[<value>]で切り抜きたい画像のURLを指定します。

例えば、星型の画像の形に合わせて海の画像を切り抜く場合は次のようにします。

また、切り抜く画像の調整にはbackground-sizebackground-positionを指定します。

<div class="mask-[url(/img/star.png)] bg-[url(/img/sea.png)] bg-cover bg-center"></div>

Tailwind CSSで画像をマスクした結果。星型の画像の形に合わせて海の画像が切り抜かれている。
Tailwind CSSで画像をマスクした結果

これで、Tailwind CSSだけで画像のマスクが実現できます。

まとめ

今回は、Tailwind CSSで画像を他の画像に合わせて切り抜く(マスクする)方法をご紹介しました。

本稿では基本形をお示ししましたが、境界線のぼかしなど様々なエフェクトが用意されていたりと、特にランディングページで有用かと思われます。

エフェクトについては公式ドキュメントをご確認ください。

tailwindcss.com

Tailwind CSSを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

htmxでページ全体で有効な設定オプションをセットする方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxでページ全体で有効な設定オプションをセットする方法をご紹介します。

なお、方向の内容は v.2.0.6 (2025年8月12日時点の最新版)のhtmxを前提としています。

htmxとは

htmxは、HTMLタグに専用の属性を記述することで、複雑なJSを記述せずにAJAXリクエストの発行を可能にするライブラリです。

htmx.org

マークアップの延長のような感覚でAJAXリクエストを実装できるのがhtmxの強みです。

<!-- button要素をクリックするとPOSTリクエストが発行される -->
<button type="button" hx-post="/sample" hx-trigger="click">
  送信
</button>

実現したいこと

実現したいことを整理します。

htmxではその挙動について設定するオプションが用意されています。

htmx.org

例えば、要素をレスポンスのDOMをSwapする際に、titleタグの置き換えも行うかをどうかは ignoreTitleオプションで設定します。(デフォルト値はfalse

htmxではレスポンスの中にtitleタグが含まれる場合、リクエスト元のページのtitleタグが置き換わります。

レスポンス

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>Response page</title>
</head>
<body>
    <div id="response">...</div>
</body>
</html>

リクエスト元

<!doctype html>
<html lang="ja">
<head>
    <meta charset="UTF-8">

    <!-- 標準ではレスポンスのtitleの「Response page」に置き換わってしまう -->
    <title>Request page</title>
</head>
<body>
    <button type="button" hx-get="/path/to/dir" hx-trigger="click" hx-select="#response">click</button>
</body>
</html>

この現象は、hx-swap属性にignoreTitleオプションをtrueに設定すると防げます。

<!-- ignoreTitleをtrueにするとtitleタグの置き換えがされない -->
<button hx-get="..." hx-swap="ignoreTitle:true" ...>...</button>

このオプションについて詳しく知りたい場合は以下の記事をご覧ください。

tech.excite.co.jp

先の例のようにhtmxの属性を用いて宣言すると、設定オプションをセットできます。

一方で今回実現したいことは、特定の設定オプションについてページ全体で有効になるようにセットして、都度の宣言を不要にすることです。

<!-- ページ全体でignoreTitleをtrueに設定して都度の宣言は不要にしたい -->
<button hx-get="..."  ...>...</button>

metaタグを用いてセットできる

設定オプションは、タグ毎にhx-*属性を用いて都度宣言する他に、metaタグを使用することでページ全体で有効になるようにセットできます。

構文は次の通りです。headタグの子要素として配置します。

<meta name="htmx-config" content='{"<Option name>":"<Value>"}'>

例えば、ページ全体でignoreTitleは常にtrueになるようにしたい場合は以下のようにします。

<head>
  ....
  <meta name="htmx-config" content='{"ignoreTitle":"true"}'>
</head>

まとめ

今回は、htmxでページ全体で有効な設定オプションをセットする方法をご紹介しました。

この手法は、プロジェクト内で常に共通する設定をセットしたい場合に便利です。

特に今回例に挙げたignoreTitletrueにセットしておくことは、意図しないtitleタグの置き換えを防止するのに有用です。

htmxを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

Tailwind CSSで監視対象から特定のディレクトリを除外する方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、Tailwind CSSでユーティリティクラスの検知の監視対象から特定のディレクトリを除外する方法をご紹介します。

なお、本稿の内容は v4.1.11(2025年7月22日時点の最新版)のTailwind CSSを前提としています。

実現したいこと

冒頭、実現したいことを整理します。

Tailwind CSSでは、プロジェクト内で使用されているユーティリティクラスに応じて必要な分だけCSSを生成します。

v4以降のTailwind CSSでは、監視対象のディレクトリ・ファイルは自動的に判定されます。

以下のような構造の場合は、特段の設定なしにHTMLファイルがすべて監視対象になります。

.
├── hoge
│   └── index.html
├── foo
│   └── index.html
├── input.css
├── package.json
└── package-lock.json

一方で今回実現したいのは、hogeディレクトリを監視対象から除外することです。

.
├── hoge // このディレクトリを監視対象から除外したい
│   └── index.html
├── foo
│   └── index.html
├── input.css
├── package.json
└── package-lock.json

@source not()を使用すると除外設定ができる

@source()はTailwind CSSの設定ファイル(@import "tailwindcss";が明示されているCSSファイル)で、ソースファイルを明示するために使用します。

これの拡張である@source not()を使用すると特定のディレクトリを監視対象から除外できます。

tailwindcss.com

構文は以下の通りです。

@source not"<設定CSSファイルの場所を起点にしたパス>"

なお、@source not()v4.1.0で追加されました。Tailwind CSS導入済みのプロジェクトの場合はバージョンをご確認ください。

例えば、先にお示ししたプロジェクト構造で、hogeディレクトリを監視対象から除外したい場合は次のようにします。

@import "tailwindcss";

// hogeディレクトリを監視対象から除外
@source not "./hoge";

これで、hogeディレクトリ内のテンプレートファイルでユーティリティクラスを使用してもCSSが生成されなくなります。

まとめ

今回は、Tailwind CSSでユーティリティクラスの検知の監視対象から特定のディレクトリを除外する方法をご紹介しました。

公式ドキュメントにもある通り@source not()は、サードパーティ ライブラリなど、Tailwind クラスを使用しないことが分かっている大きなディレクトリがプロジェクト内に存在する場合に有用です。

Tailwind CSSを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

htmxでリクエスト発行前にHTMLの制約検証APIを使用して検査する方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxでHTMLの制約検証APIを使用して検査合格後にリクエストを発行する方法をご紹介します。

なお、本稿の内容は v2.0.6(2025年7月14日時点の最新版)のhtmxを前提としています。

htmxとは

htmxは、HTMLタグに専用の属性を記述することで、複雑なJSを記述せずにAJAXリクエストの発行を可能にするライブラリです。

htmx.org

マークアップの延長のような感覚でAJAXリクエストを実装できるのがhtmxの強みです。

<!-- クリックするとPOSTリクエストが発行される -->
<button type="button" hx-post="/sample" hx-trigger="click">
  送信
</button>

実現したいこと

実現したいことを整理します。

HTMLでは制約検証APIが提供されており、クライアントサイドでの簡単なバリデーションを行うことができます。

developer.mozilla.org

Google Chromeによる検査結果表示の例

以下は、inputタグのminlength属性を使用して最小の文字数の制約を設定する実装例です。

<!-- 入力値が4文字を下回る場合はフォームリクエストが実行できない -->
<form>
  <label>
    座右の銘
    <input type="text" name="motto" minlength="4">
  </label>
  ...
</form>

一方で今回実現したいのは、htmxを使用してリクエストを発行する場合にも、制約検証APIを使用して検査を行うことです。

<!-- 制約に違反する場合はリクエストが発行されないようにしたい -->
<input 
type="text" 
name="motto" 
hx-post="/sample" 
hx-trigger="keyup changed delay:2s" 
minlength="4"
>

hx-varidate属性でHTMLの制約検証APIの検査を有効化できる

hx-varidate属性でtrueを指定すると、HTMLの制約検証APIを使用した検査を有効化できます。

htmx.org

構文は以下の通りです。hx-validate属性を指定しない場合はfalseの挙動になります。

hx-validate="<Boolean>"

例えば、「入力値は4文字以上でなければならない」という制約をminlength属性で設定した上で、hx-validate="true"を指定すると、制約に違反している場合はリクエストが発行されなくなります。

<!-- 制約に違反する場合はリクエストが発行されない -->
<input 
type="text" 
name="motto" 
hx-post="/sample" 
hx-trigger="keyup changed delay:2s" 
hx-validate="true"
minlength="4"
>

注意点

なお、minlengthなどの検証関連属性やhx-validateの値はブラウザ上で改ざんできてしまうため、サーバーサイドでも検査を行うことを推奨します。

また、クライアントサイドでのバリデーションはユーザ体験を向上させる目的もあるため、制約違反の場合はその旨を表示することが大切であると考えます。

バリデーションを視覚的に表す場合は、Alpine.jsと組み合わせる方法もあります。

tech.excite.co.jp

まとめ

今回は、htmxでHTMLの制約検証APIを使用して検査合格後にリクエストを発行する方法をご紹介しました。

htmxを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

第12回テクデザBeerBashを開催しました

こんにちは。エキサイトでエンジニアをしている吉川です。先日7/4(金)に社内イベントのテクデザBeerBashを開催したので、そのレポートを書いていきます。

BeerBashとは

Beer Bashとはbeer(ビール)+ bash(にぎやかなパーティー)を合わせた造語で、真面目な部分を残しつつ、カジュアルな雰囲気で交流を行うイベントです。 年に3、4回社内スペースで開催しており、同じチーム内の人はもちろん、業務ではあまり関わることがない他部署の人たちとも繋がる場になっています。

今回はオフィス移転後初のBeer Bashで、EXCITE HUBを使ったよりリッチな設備で開催することができました。

当日のコンテンツ

前半は2つのコンテンツについて発表を行い、後半はフリートークの時間にしました。

  • オフィス移転プロジェクトの裏側
  • MCPツールのハンズオン

オフィス移転プロジェクトの裏側

EXCITE HUBは新オフィスの目玉になっていて、「専用のロゴがある」「営業時間中は大型スクリーンに動画が流れている」といった場のデザインもこだわり抜いて作っています。今回はデザイナーチームからその制作の裏側について発表していただきました。

大型スクリーンの投影機材には、複数の映像を合成する機能や、映像やマイクの音声をPCに出力して配信する機能もついています。また社内のネットワーク周りも移転に伴いパワーアップしました。この機材周りのエピソードをインフラチームから発表いただきました。

今回は1コンテンツを複数のLTで構成しました。初の試みだったのですが、全体の満足度を高めつつ登壇者の負担を減らすことができたので、チャレンジしてよかったと感じています。また登壇者のうちお一人はリモート参加でしたが、会場マイクやスピーカーをPCに繋げることで、オフライン登壇と遜色ない形で発表することができました。機材ポテンシャルの高さを実感したので、今後も有効利用していきたいと思っています。

MCPツールのハンズオン

LLMと各種ツールを繋げるMCPについて、ハンズオンを行いました。事前に社内GitHubでコードを展開し、BeerBash中に参加者各々のローカルPC環境で、PlaywrightMCPや自作のBMI計算ツールを動かしました。

登壇者のPCでデモやライブコーディングを行うことは何度かありましたが、参加者のPCで行えるようにするのは初めてで、リポジトリの運用方法や非エンジニアにも伝わるREADMEなど考慮することはたくさんありました。正直荒削りな部分はまだありますが、参加者からは大変ご好評だったので、今後もブラッシュアップを続けていきたいと思いました。

振り返りとまとめ

オフィス移転後初のテクデザBeerBashで、これまでと勝手が違う面も多々ありましたが、無事成功させることができました。コンテンツ内容そのものも重要ですが、複数LTやハンズオンのように新しい施策を打ったのも好評につながっていたと思います。4年目を迎えた本イベントですが、まだまだ進化し続けていきたいと思います。

最後まで読んでいただきありがとうございました!少しでもイベントの雰囲気が伝わっていれば幸いです!もしエキサイトにご興味を持っていただけたら、こちらからぜひご連絡ください!カジュアル面談からでもOKです!

sg.wantedly.com

htmxでHTTPレスポンスエラー時に任意のJavaScriptを実行する方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxでリクエスト発行してHTTPレスポンスエラーとなった場合に、任意のJavaScriptを実行する方法をご紹介します。

なお、本稿の内容は v2.0.6(2025年7月7日時点の最新版)のhtmxを前提とします。

htmxとは

htmxは、HTMLタグに専用の属性を記述することで、複雑なJSを記述せずにAJAXリクエストの発行を可能にするライブラリです。

htmx.org

マークアップの延長のような感覚でAJAXリクエストを実装できるのがhtmxの強みです。

<!-- クリックするとPOSTリクエストが発行される -->
<button type="button" hx-post="/sample" hx-trigger="click">
  送信
</button>

実現したいこと

実現したいことを整理します。

既定のhtmxでは、リクエスト先から404や500が返却されてAJAXに失敗すると、ウェブコンソールにエラーメッセージが出力されます(console.errorが実行される)。

リクエスト先が404でAJAXに失敗した時のGoogle ChromeのConsole

これにより、エラーを検知できますが、ブラウザの検証ツールを開く必要がありユーザーに対しては明示的ではありません。

一方で、今回実現したいことは、リクエスト先から404や500が返却されてAJAXに失敗した場合は、その旨を記したwindow.alertを実行して、簡易的にエラーメッセージを表示することです。

AJAXに失敗した場合に表示したいアラートダイアログ

htmx:responseErrorイベントとhx-on属性を組み合わせると実現できる

htmxが用意しているイベントの一つである、htmx:responseErrorを使用するとレスポンスエラーを検知できます。

htmx.org

これを、イベントに応答するスクリプトが埋め込めるhx-on属性と組み合わせると、レスポンスエラーが発生した場合に任意のJSが実行できます。

htmx.org

構文は以下の通りです。hx-onでイベントを指定する場合はキャメルケースをケバブケースに変換する必要があります。

hx-on:htmx:response-error="<任意のJavaScript>"

例えば、「クリックすると/sampleに対してPOSTリクエストを発行するボタンでレスポンスエラー時はwindow.alertを実行する」場合は以下のようにします。

<button 
type="button" 
hx-post="/sample" 
hx-trigger="click" 
hx-on:htmx:response-error="alert('処理に失敗しました')"
>
  リクエスト発行
</button>

これで、リクエスト先から404や500が返却されてAJAXに失敗した場合は、アラートダイアログが出現するように設定できました。

なお、200・300番台のレスポンスはこのイベントは発火しません。

まとめ

今回は、htmxでリクエスト発行してHTTPレスポンスエラーとなった場合に、任意のJSを実行する方法をご紹介しました。

既定のconsole.errorでは一般ユーザーはエラーを検知できませんが、htmx:responseErrorイベントにより明示的にエラーを示すUIにできるため、特にユーザー操作が多い管理系のアプリケーションで活躍するのではないでしょうか。

htmxを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

【ExciteHD TechCon 2025】Tailwind CSS、Alpine.js、htmxによる「消しやすさ」を軸にしたフロントエンド戦略について発表しました

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、先日弊社で開催されたExciteHD TechCon 2025で発表した、Tailwind CSS、Alpine.js、htmxによる「消しやすさ」を軸にしたフロントエンド戦略についてご紹介します。

ExciteHD TechConについて

ExciteHD TechConは、エキサイトホールディングスで毎年開催している技術カンファレンスです。

エンジニアだけではなく、デザイナー・ビジネス職のメンバーによる発表もあり、職種を超えて技術発信がされていることが特徴です。

今年のTechConについては以下の記事もご覧ください。

tech.excite.co.jp

発表内容

今回私は、『CSS、JSをHTMLテンプレートにまとめるフロントエンド戦略』と題して発表しました。

発表内容の要約は次の通りです。

  • フロントエンドのペインとして「UIを構成する要素が散らばりがちで、追いにくい」点が挙げられる
  • 理想状態は「要素を一発で消せる状態」なのでは
  • 「消しやすい」は追加や拡張もしやすいにつながる
  • CSS・JSをHTMLテンプレートにまとめると理想に近づく
  • 実現方法の一つにTailwind CSS、Alpine.js、htmxがある
  • これらにより要素間の影響がCSS、JSも含めてなくなるので、自分が把握していない要素でも怖がらずに手を加えられる
  • 命名に関する議論も最小限に留められるのでチーム開発だからこそ活きる

フロントエンドのややこしいところ

フロントエンドは、HTML、CSS、JSなどの「UIを構成する要素が散らばりがちで、追いにくい」というペインを抱えることがあると思います。

特に歴史が長いプロダクトでは、CSSやJSのファイルが肥大化したり、不要なものが残り続けてしまいがちです。

昨年20周年を迎えたエキサイトブログでも課題を抱えていました。

フロントエンドの理想状態とは

では、フロントエンドの理想状態はいったいどんな状態なのでしょうか。

その一つに「要素が一発で消せる状態」があると考えます。

要素を消す場合、HTMLを単に削除すれば良いだけではなく、様々な思考を必要とします。

要素に紐づくCSSやJSも合わせて削除したいが、他の要素への影響を気にする必要があったりと、自分以外が実装した要素では特に「一発で消せる」ことは少ないです。

一方で、要素が一発で消せる状態にしておくと、新規追加や拡張もしやすい状態となると考えます。

どうすれば理想状態に近づくのか

「要素が一発で消せる状態」にするにはどうすれば良いのでしょうか。

もう一度、要素を消す場合の思考を振り返ります。

HTMLを消すという作業に対して、CSSやJSも気にする必要があります。

「HTMLだけなら楽なのに…」に対して「HTMLだけにしてしまおう!」というのが、今回ご紹介する戦略です。

どうやって実現するのか

実現手段を考えます。まずは、標準の技術から検討します。

CSSはすべてstyle属性に記述する?

ユーティリティクラスだけでスタイリングするようにする?

JSはすべてインラインスクリプトにする?

標準の技術だけでは困難なため、ライブラリを検討します。

「ひとまとめ」を実現する技術たち

CSSやJSをHTMLに寄せるための手段として、Tailwind CSS、Alpine.js、htmxがあります。

Tailwind CSS

tailwindcss.com

Alpine.js

alpinejs.dev

htmx

htmx.org

戦略はどう活きているか

私が所属するメディア・プラットフォーム事業部内のプロダクトの一部ではご紹介した戦略を採用しています。

その結果、

  • 自分以外が実装した要素でも消しやすく、追加・編集しやすくなった
  • 命名に関するコンテクストを合わせる必要が最小限になった

といった点で効果を発揮しています。

戦略の課題は

一方で、特にTailwind CSSについて次のような課題が浮き彫りになりました。

  • ユーティリティファーストなスタイリングによる可読性の低下
  • 導入にはCLIに触れる必要があり、デザイナーにとってはとっつきにくい

これらに対して、コードフォーマットの自動化やドキュメント整備等の対策を講じています。

まとめ

今回ご紹介したことは、あくまで方法の一つに過ぎず、銀の弾丸ではありません。

一方で、ThymeleafやLaravel Bladeといったテンプレートエンジンが使用できる環境で、フロントエンドは最小構成にしたいといったケースには相性が良いと考えております。

最後に

「分かりやすかった」「エンジニア目線だと目からウロコだった」等の励みになるフィードバックも多く頂戴しました。

また、Best Session Awardも受賞させていただきました。

昨年来2回目の登壇でしたが、来年も登壇できるように日々の業務に一層励みたいと改めて認識した機会となりました。

本発表がどなたかの一助となれば幸いです。ご精読ありがとうございました。

昨年の発表

昨年はFigmaのVariablesについて発表をしました。

tech.excite.co.jp

他の登壇者の発表

他の登壇者の発表についても順次ご覧いただけます。ぜひ、「TechCon」カテゴリをチェックしてください。

tech.excite.co.jp

免責

  • 本資料および講演内容は、発表者個人の見解であり、所属する組織の公式見解を示すものではありません。
  • 本資料に含まれる情報は、発表時点での情報に基づいています。資料作成には細心の注意を払っておりますが、その正確性、完全性、有用性を保証するものではありません。
  • 本資料および講演内容の利用によって生じたいかなる損害についても、発表者および所属組織は一切の責任を負いかねます。
  • 本資料に記載されている会社名、製品名、サービス名は、各社の商標または登録商標です。これらの画像は、各社の情報提供を目的として使用しており、権利侵害を意図するものではありません。

htmxでリクエスト発行前にwindow.confirmを実行する方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxでリクエスト発行前にwindow.confirmを実行して、確認ダイアログが承認された場合にのみリクエストする方法をご紹介します。

なお、本稿の内容は v2.0.4(2025年6月16日時点の最新版)のhtmxを前提としています。

htmxとは

htmxは、HTMLタグに専用の属性を記述することで、複雑なJSを記述せずにAJAXリクエストの発行を可能にするライブラリです。

htmx.org

マークアップの延長のような感覚でAJAXリクエストを実装できるのがhtmxの強みです。

<!-- クリックするとPOSTリクエストが発行される -->
<button
type="button"
hx-post="/sample"
hx-trigger="click"
hx-target="#target"
>
  送信
</button>

<!-- innerHTMLにレスポンスのDOMが挿入される -->
<div id="target"></div>

実現したいこと

実現したいことを整理します。

JSのwindow.confirmを使用して、承認されたときにのみ処理を実行させる体験にすることもあると思います。

アクションが破壊的変更である場合に慎重な操作を促せる点から、特に管理系の機能で有用です。

window.confirmにより表示される確認ダイアログの例

以下は、HTML標準のbuttonタグと掛け合わせたwindow.confirmの実装例です。

<!-- 確認ダイアログが承認された場合に限り、`true`が返されて`submit`される -->
<button
type="submit"
formmethod="post"
formaction="/sample"
onclick="return confirm('フォームを送信しますか?')"
>
送信
</button>

一方で今回実現したいのは、htmxを使用したAJAXリクエスト発行時にwindow.confirmと同じ挙動をさせることです。

<!-- 確認ダイアログが承認された場合に限りリクエストを発行したい -->
<button
type="button"
hx-post="/sample"
hx-trigger="click"
>
送信
</button>

hx-confirm属性でwindow.confirmが実装できる

htmxのhx-conform属性を使用すると、リクエスト前に確認ダイアログを出現させてwindow.confirmと同じ挙動を実現できます。

htmx.org

構文は以下の通りです。

hx-confirm="<message>"

例えば、「ボタン押下時に "本当に送信しますか?"という文言の確認ダイアログを出現させて、承認された場合にのみPOSTリクエストを発行する」場合は次のようになります。

<button
type="button"
hx-post="/sample"
hx-trigger="click"
hx-confirm="本当に送信しますか?"
>
送信
</button>

デフォルトではブラウザ標準の確認ダイアログが出現されますが、UIのカスタマイズも可能です。詳しくは公式ドキュメントをご確認ください。

htmx.org

まとめ

今回は、htmxでリクエスト発行前にwindow.confirmを実行して、確認ダイアログが承認された場合にのみリクエストする方法をご紹介しました。

アクションが破壊的変更である場合に慎重な操作を促せるため、特に管理系のアプリケーションで活躍するのではないでしょうか。

htmxを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

ExciteHD TechCon2025 を開催しました

はじめに

こんにちは。エキサイトでエンジニアをしております、吉川です。 先日6/6(金)にエキサイトHD社内の技術カンファレンス「TechCon」を開催しました。本記事では、その様子をお伝えします。 昨年のTechCon運営の記事は以下からご覧いただけます。 tech.excite.co.jp

TechConとは

TechConは、エキサイトHDが毎年1回開催している技術カンファレンスです。主に2つの目的があります

  1. 社外に「エキサイト」の技術力や取り組みを発信し、採用活動に貢献すること
  2. 部署や職種を超えた社内交流を活性化させること

テーマ:Hello World

TechConでは毎年異なるテーマを掲げ、それを基にセッションのプロポーザルを選定しています。 今年のテーマは「Hello World」としました。これは、プログラミングの世界で最初に学ぶ「Hello World」にちなみ、以下のような意味を込めています

  • 新しく何かを始めたときの「最初のきっかけ」
  • 挑戦の「最初の一歩」
  • 誰かに伝えたい「最初の言葉」

これらの「最初」の経験を社内で共有し、次の"Hello World"へと繋げていこうという思いを込めています。 また、このテーマに沿った専用ページも作成し、登壇者・視聴者のモチベーション向上を図りました(社内からのみアクセス可能)。

セッション内容

今年は、技術的な内容からビジネス的な内容まで、幅広い分野のセッションが実施されました

  • 生成系AIコミックの挑戦
  • AWSHello World! ~ インフラ初心者がAWS移管を完了させるまで ~
  • ビジネスサイドで進めるデータ分析基盤構築
  • 「Hello Clean Architecture: 新メンバーへのオンボーディングと設計の伝え方」
  • (基調講演)AIエージェント
  • How a Flutter App Works on Your Device!!
  • CSS、JSをHTMLテンプレートにまとめるフロントエンド戦略
  • 保守性の高いテストの勘所
  • Playwrightを用いたリグレッションの実装
  • 新卒テクデザ研修発表

運営のHello World

今回は運営としても、いくつかの「Hello World」に挑戦しました。

新環境での開催

前回までは2月に開催していましたが、今回は4月の麻布台ヒルズへのオフィス移転に合わせて、新環境での開催となりました。 新設されたEXCITE HUBの大モニターを活用し、よりリッチなカンファレンス体験を実現しました。

大モニター

また、オンライン配信には弊社サービスの「FanGrowth」の配信機能を採用。これは昨年リリースされた新機能で、FanGrowth以外のエンジニア・デザイナーはあまり馴染みのないものだったので、TechConでの活用を通じて、社内のサービス理解と結束を深めることを目指しました。

FanGrowth

セッション時間の見直し

前回まであったLT(ライトニングトーク)枠を撤廃し、20分のショートセッションと30分のロングセッションに整理しました。各登壇者が十分な時間で内容を伝えられるようにすることで、TechCon全体がよりクオリティの高いものになり、それが社外からの魅力アップや採用につながることを狙いました。

ノベルティ

前回のアクリルキーホルダーが好評だったので、今回のノベルティもTechCon開催後に日常的に使えるアイテムとして、バックハンガーを採用しました。

写真だと四角いのですが、これがS字に開いて机に引っ掛けられるようになります。オフィス移転に伴い、机周りの収納スペースが限られた中で、バッグの置き場所問題を解決する実用的なアイテムとなっています。

バックハンガー

また、今年のTechConロゴを使用した半透明のステッカーも用意。モダンでスタイリッシュなデザインに仕上げました。

ステッカー

その他オフライン参加者に向けて、お菓子やジュースも用意しました。ただセッションを聞いてるだけだと疲れてしまうので、セッションの合間などにリフレッシュできるようにしていました。

懇親会

TechConは日中にセッションを開催し、夕方から懇親会を行っています。今回から懇親会も本格的にし、ケータリングとお酒で参加者同士の交流を深めました。

懇親会

運営を振り返って

運営のHello Worldで挙げた新環境での開催は大成功に終わりました。旧オフィスでも色々手を打って盛り上げられるようにしていましたが、やはりベースとなる設備が変わると雰囲気も大きく変わると実感しました。 今後は社外を巻き込んだカンファレンスに成長させて行きたいので、その一歩にできたと思っています。

セッション面では初めてビジネス側の方を巻き込むことができたのがよかったです。エンジニアConやデザイナーConではないので、今後もTechにまつわる話なら職種を超えたコラボレーションをやっていきたいです。 また職種ではなく会社を超えたコラボレーションという面では、グループ内のiXIT株式会社や、昨年ジョインしたSharely株式会社のメンバーからも参加がありました。 当初は小さく始まったTechConですが、だんだんと多くの方に浸透しているのを感じています。

登壇者のみなさま、視聴者のみなさま、運営チームのみなさま、ご協力誠にありがとうございました! 次回はさらにパワーアップしたTechConを開催いたしますので、ご期待ください!

おわりに

ここまで見ていただきありがとうございました。エキサイトでは業務以外にも、社内交流を盛り上げるための活動を行なっています。 お祭り気分でもできることや、経験がなくても「やってみたい」「楽しみたい」気持ちから参加いただいている方も多いです。 そんなエキサイトにご興味を持っていただけた方、カジュアル面談からでもお話ししませんか? ぜひお気軽にご連絡ください🙌 sg.wantedly.com

JSなしでdialogタグを制御できるbuttonタグのcommand属性を試してみた

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、buttonタグの新しい属性であるcommand属性を使用して、JSなしでdialogタグを制御する方法をご紹介します。

なお、本稿の内容は2025年6月9日時点のHTML Living Standardと各ブラウザの対応状況に準じています。

command属性とは

command属性はbuttonタグの新しい属性の一つで、HTML Living Standardでも追加済みとなっています。

html.spec.whatwg.org

dialogタグ等のJavaScriptのメソッドに対応した値を指定することで、JSと同等なアクションを呼び出すことが可能です。

また、要素の紐づけを指定するcommandfor属性とセットでの使用が想定されています。

command属性とcommandfor属性は、Chrome135Edge 135のみが正式対応となっており、他のブラウザはベータ版のみ対応か未対応となっていますので、ご注意ください。

実現したいこと

実現したいことを整理します。

以下のように、dialogタグを使用してダイアログ要素のボタンを通じた表示/非表示を実現したいです。

See the Pen JSを使用してdialogタグを制御する by AyumuSaito (@ayumusaito-excite) on CodePen.

const dialog = document.querySelector("#dialog")
const showButton = document.querySelector("#show-button")
const closeButton = document.querySelector("#close-button")

showButton.addEventListener("click", () => {
  dialog.showModal();
});
  
closeButton.addEventListener("click", () => {
  dialog.close();
});

このように、従来の方法ではJSの記述が必要です。

Alpine.jsを使用するとHTMLに処理の記述を寄せることもできます。詳しくは次の記事をご覧ください。

tech.excite.co.jp

command属性を使用してダイアログ要素を制御してみる

command属性とcommandfor属性を使用して、ダイアログ要素を制御してみます。

冒頭でご説明した通り、command属性はdialogタグ等のJavaScriptのメソッドに対応した値を指定することで、JSと同等なアクションを呼び出すことが可能です。

例えば、以下の値が用意されています。

対応するメソッド
show-modal .showModal()
close .close()
request-close .requestClose()

command属性に指定したアクションの対象となる要素の指定には、commandfor属性を使用します。

したがって、次の通り指定した場合は、「id属性の値がdialogの要素に対して.showModal()を実行する」といった宣言になります。

<button command="show-modal" commandfor="dialog" ...>...</button>

実現したいことの項で示した例と同じことを、command属性とcommandfor属性を使用して実装すると以下のようになります。

See the Pen commandとcommandforを使用してdialogタグを制御する by AyumuSaito (@ayumusaito-excite) on CodePen.

まとめ

今回は、buttonタグの新しい属性であるcommand属性を使用して、JSなしでdialogタグを制御する方法をご紹介しました。

command属性によりJSを記述することなくdialogタグが制御できるようになるため、ダイアログUIの実装がより簡単にシンプルになるのではないでしょうか。

実運用で超えるべき課題や他のブラウザの対応状況を注視していきたいと思います。

本稿の情報がマークアップされる方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

htmxのリクエストトリガーに別の要素のイベントを指定する方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxのリクエストトリガーに別の要素のイベントを指定する方法をご紹介します。

htmxとは

htmxは、HTMLタグに専用の属性を記述することで、複雑なJSを記述せずにAJAXリクエストの発行を可能にするライブラリです。

htmx.org

以下のように、マークアップの延長のような感覚でAJAXリクエストを実装できるのがhtmxの強みです。

<!-- クリックするとPOSTリクエストが発行される -->
<button
type="button"
hx-post="/sample"
hx-trigger="click"
hx-target="#target"
>
  送信
</button>

<!-- レスポンスのHTMLに置き換わる -->
<div id="target"></div>

実現したいこと

実現したいことを整理します。

htmxではリクエスト発行のトリガーはhx-trigger属性で指定します。

<!-- 自要素のクリックイベントがトリガーになる -->
<button hx-trigger="click" ...>
  送信
</button>

この例では、hx-triggerclickと指定したため、自要素(= hx-post等のリクエスト用の属性を持つ要素)のクリックイベントがリクエストのトリガーとなります。

一方で今回実現したいのは、別の要素のクリックイベントをリクエストのトリガーとすることです。

<!-- #send-buttonのクリックでPOSTリクエストが発行されるようにしたい -->
<div hx-post="/sample" ...></div>

<button id="send-button" type="button">送信</button>

hx-triggerのfrom:*で別の要素のイベントをトリガーに指定できる

hx-triggerの修飾子の一つであるfrom:*を使用すると、別の要素のイベントをリクエストのトリガーに指定できます。

htmx.org

構文は以下の通りです。

hx-trigger="<Web API events> from:<Extended CSS selector>"

例えば、「別の要素である#send-buttonのクリックでPOSTリクエストが発行される」場合は次のようになります。

<!-- #send-buttonのクリックでPOSTリクエストが発行される -->
<div hx-trigger="click from:button[id='send-button']" hx-post="/sample" ...></div>

<button id="send-button" type="button">送信</button>

まとめ

今回は、htmxのリクエストトリガーに別の要素のイベントを指定する方法をご紹介しました。

hx-triggerの修飾子from:*により、複数の要素の複数のイベントをトリガーに指定したいケースに対応できます。

htmxを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

カスタムURLスキーム実装時に詰まったこと (スキームの指定について)

こんにちは。エキサイトでアプリエンジニアをしている岡島です。

最近、FlutterアプリでDeepLinkをカスタムURLスキームで実装する機会がありました。そのとき、動作確認のデバッグ用コマンドではカスタムURLスキームからアプリが起動するのですが、TestFlightで配布したアプリではカスタムURLスキームが無効な状態になっていました。その原因について共有します。

結論

アプリ側でカスタムURLスキームを指定する時に、大文字を含んだスキームで定義してたことが原因でアプリが起動しませんでした。 スキーム名をすべて小文字にすると解決しました。

起こった事象

  • iOSシミュレータでは xcrun simctl openurl booted 'MyApp://path' コマンドでアプリが起動
  • Androidエミュレータでは adb -e shell 'am start -W -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "MyApp://path"' コマンドでアプリが起動

TestFlight経由でアプリを配布した後、カスタムURLスキームのリンクを開いてもアプリが起動しないという状況でした。

原因の調査

デバッグのコマンドでアプリが起動するので実装には問題なさそうなので、 スキームについて調査しました。

するとこのような文を見つけました。 RFC 3986

Although schemes are case-insensitive, the canonical form is lowercase and documents that specify schemes must do so with lowercase letters.

(DeepLでの和訳: スキームは大文字と小文字を区別しないが、正規形は小文字であり、スキームを指定するドキュメントは小文字で指定しなければならない。 )

私の実装では、カスタムURLスキームに「myApp://path」のように大文字を含みスキームを定義していました。 これが原因のようです。

解決策

アプリ側で指定するスキーム名を小文字に統一すると解決しました。

例:

❌ MyApp://path 
⭕ myapp://path 

この修正後、実機環境やTestFlight配布版でも問題なくカスタムURLスキームが動作するようになりました。

まとめ

URLスキームのプロトコルやブラウザの仕様など、基礎的な周辺知識も重要だと感じました。 この記事が誰かのお役に立てれば幸いです。

参考

textarea要素のサイズ変更を提供する方向を制御する方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、textarea要素のサイズ変更を提供する方向を制御する方法をご紹介します。

実現したいこと

冒頭、実現したいことを整理します。

texarea要素は、要素右下のつまみをドラッグすることでサイズ変更が可能です。

CodePenを用意しましたので体験してみてください。

See the Pen サイズ変更が可能なtextarea要素 by AyumuSaito (@ayumusaito-excite) on CodePen.

ブラウザやリセットCSSによりますが、デフォルトでは水平方向・垂直方向の両方でサイズ変更が提供されていることが多いです。

一方で今回実現したいのは、サイズ変更を提供する方向を水平方向か垂直方向かを限定することです。

CSSプロパティのresizeで制御が可能

textarea要素のサイズ変更を提供する方向を制御する方法の一つとして、CSSプロパティのresizeがあります。

内容
none サイズ変更を提供しない(デフォルト値)
both 水平方向・垂直方向の両方でサイズ変更を提供する
horizontal 水平方向のサイズ変更を提供する
vertical 垂直方向のサイズ変更を提供する

この他に、blockinlineがありますが割愛します。

例えば、サイズ変更を垂直方向に限定したい場合はresize: vertical;を指定します。

See the Pen 垂直方向のみサイズ変更が可能なtextarea要素 by AyumuSaito (@ayumusaito-excite) on CodePen.

textarea {
    resize: vertical;
}

注意点

resizeプロパティはCSS Basic User Interface Module Level 3に含まれ、同仕様はW3Cにより2018年6月に勧告されていますが、2025年5月12日現在、iOS版Safariでサポートされていません

www.w3.org

Tailwind CSSの場合

Tailwind CSSresizeプロパティを指定する場合は、resize-*ユーティリティクラスを使用します。

tailwindcss.com

ユーティリティクラス 内容
resize-none resize: none;
resize resize: both;
resize-x resize: horizontal;
resize-y resize: vertical;

まとめ

今回は、textarea要素のサイズ変更を提供する方向を制御する方法としてCSSresizeプロパティをご紹介しました。

textarea要素のサイズ変更を制限することで意図しないレイアウト崩れを防ぎたいといった場合に有用です。

スタイリングする際の一助となれば幸いです。ご精読ありがとうございました。

参考文献

htmxでAJAXリクエスト時に送信されるパラメータをフィルタリングする方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、htmxでAJAXリクエスト時に送信されるパラメータをフィルタリングする方法をご紹介します。

なお、本稿の内容は v2.0.4(2025年4月28日時点の最新版)のhtmxを前提とします。

htmxとは

冒頭、簡単にhtmxについてご説明します。

htmxは、HTMLタグに専用の属性を記述することで、複雑なJSを記述せずにAJAXリクエストの発行を可能にするライブラリです。

htmx.org

<!-- クリックするとPOSTリクエストが発行される -->
<button
type="button"
hx-post="/sample"
hx-trigger="click"
hx-target="#target"
>
  送信
</button>

<!-- レスポンスのHTMLに置き換わる -->
<div id="target"></div>

上述の例では、「button要素のクリックイベントにより/sampleに対してPOSTリクエストを発行し、id="target"が付与されている要素をレスポンスとして帰ってきたHTMLに置き換える」という処理が行われます。

このように、マークアップの延長のような感覚でAJAXリクエストが実装できるのがhtmxの強みです。

実現したいこと

以下のようにform要素内でリクエストを発行する場合、兄弟のinput要素の値はパラメータとして送信されます。

<form>
  <!-- パラメータとして送信される -->
  <input type="hidden" name="param1" value="value1" />
  <input type="hidden" name="param2" value="value2" />

  <button
  hx-post="/sample"
  hx-trigger="click"
  >
    送信
  </button>
</form>

一方で今回実現したいのは、form要素内の一部のinput要素の値のみがリクエスト時に送信されるようにパラメータをフィルタリングすることです。

<form>
  <!-- param1は送信する -->
  <input type="hidden" name="param1" value="value1" />

  <!-- param2は送信しない -->
  <input type="hidden" name="param2" value="value2" />

  ...
</form>

hx-paramsで実現可能

htmxの専用属性のうち、hx-paramsを使用することで、AJAXリクエスト時に送信されるパラメータをフィルタリングできます。

htmx.org

hx-params="not <param-list>"の形式で、排除したいパラメータのkeyを指定します。

<form>
  <input type="hidden" name="param1" value="value1" />

  <!-- 指定されたparam2は送信されない -->
  <input type="hidden" name="param2" value="value2" />

  <!-- hx-paramsに`not param2`を指定 -->
  <button
  hx-params="not param2"
  hx-post="/sample"
  hx-trigger="click"
  >
    送信
  </button>
</form>

ブラウザにてリクエストのPayloadを確認すると次のようになります。

hx-paramsの指定なし hx-params="not param2"を指定

複数のkeyを指定したい場合はhx-params="not param1,param2のようにコンマ続きで記述します。

なお、hx-paramsのデフォルト値は*であり、これはすべてのパラメータを含むことを指します。

まとめ

今回は、htmxでAJAXリクエスト時に送信されるパラメータをフィルタリングする方法をご紹介しました。

hx-parmsにより、同一form内でリクエスト先を変えたい + 一部のパラメータのみを送信したい といった場合に有用です。

htmxを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献

Tailwind CSSでグラデーション背景をスタイリングする方法

こんにちは。エキサイトでデザイナーをしている齋藤です。

今回は、Tailwind CSSでグラデーション背景をスタイリングする方法をご紹介します。

なお、本稿ではv4.1(2025年4月21日時点の最新版)のTailwind CSSを前提とします。

実現したいこと

冒頭、実現したいことを整理します。

CSSでは要素の背景色をグラデーションにすることもできます。

通常のCSSではlinear-gradient()関数を使用します。

例えば、「上方向に赤から青」というグラデーションを表現する場合は以下のようになります。

background: linear-gradient(to top, blue, red);

linear-gradient(to top, blue, red)の結果。上方向に赤から青のグラデーションが描かれている。
linear-gradient(to top, blue, red)の結果。上方向に赤から青のグラデーションが描かれている。

今回実現したいのは、先の例と同様に、

  • グラデーションの方向
  • 始点の色
  • 終点の色

を指定したグラデーション背景をTailwind CSSでもスタイリングすることです。

Tailwind CSSでlinear-gradientを実現する方法

Tailwind CSSでは以下のユーティリティクラスを用いることで、linear-gradientを実現できます。

ユーティリティクラス 説明
bg-linear-* グラデーションの方向
from-* 始点の色
to-* 終点の色

先の例、「上方向に赤から青」をTailwind CSSで表現すると次のようになります。

<div class="bg-linear-to-t from-red-500 to-blue-500"></div>

他にも、deg値や中間色の指定、放射状や円錐のグラデーションも表現できます。

詳しくは公式ドキュメントをご覧ください。

tailwindcss.com

まとめ

今回は、Tailwind CSSでグラデーション背景をスタイリングする方法をご紹介しました。

linear-gradient()関数の場合、引数の値をどう指定したらよいか迷いがちな一方で、Tailwind CSSでは、始点はfrom-*、終点はto-*などと単語で特定できるので分かりやすいのではないでしょうか。

なお、公式ドキュメントではグラデーション背景に関する説明は、background-imageのページに記載されていますので、ご注意ください。

tailwindcss.com

Tailwind CSSを使用される方の一助となれば幸いです。ご精読ありがとうございました。

参考文献