Entra External ID のサインアップ画面をブランドに合わせて調整していると、「キャンセルだけ色や形を変えたい」「戻るボタンは今のままで良い」といったピンポイントな要望が必ず出てきます。しかし実際に CSS を書こうとすると、副ボタンはすべて .ext-button.ext-secondary でまとめてスタイルされ、特定の 1 個だけを安全に狙う方法が見当たりません。本記事では、その理由と現実的な回避策を、アーキテクチャ目線も含めて整理します。
Entra External ID のカスタムブランディングと CSS の前提
まずは、Entra External ID(および Entra ID 全般)のサインイン/サインアップ画面がどのようにカスタマイズされるのか、前提を確認しておきます。
Entra External ID では、「会社のブランド設定(Company branding)」から、背景画像・ロゴ・色だけでなく、カスタム CSS をアップロードして見た目を調整できます。
このとき使えるセレクタは、Microsoft が公開している CSS テンプレートのリファレンスにまとめられています。ボタンについて抜粋すると、次のようなクラスが使われます。
| 用途 | 代表的なクラス | 説明 |
|---|---|---|
| 主要ボタン | .ext-button.ext-primary | 「次へ」「サインアップ」など、ユーザーに取ってほしいメインアクション |
| 主要ボタン(状態) | .ext-button.ext-primary:hover など | ホバー・フォーカス・クリック時のバリエーション |
| 副ボタン | .ext-button.ext-secondary | 「戻る」「キャンセル」など、メイン以外の操作用ボタン |
| 副ボタン(状態) | .ext-button.ext-secondary:hover など | 副ボタンのホバー・フォーカス・クリック時スタイル |
ポイントは次の 2 つです。
- カスタム CSS から触れるのは、ドキュメントに載っているクラスや要素に限られる
- ボタンは「プライマリ」「セカンダリ」の 2 種類でしか区別されていない
つまり、「副ボタンの中の <キャンセル> だけ」という粒度の識別子は、公式には提供されていません。
なぜ「キャンセルだけ」を CSS で変えられないのか
実際の DOM はおおよそ次のようなイメージになります(簡略化)。
<div class="ext-sign-in-box">
<button class="ext-button ext-primary">サインアップ</button>
<button class="ext-button ext-secondary">戻る</button>
<button class="ext-button ext-secondary">キャンセル</button>
</div>
ここで分かる通り、副ボタン(戻る・キャンセル)はどちらも同じ .ext-button.ext-secondary しか付いていません。ID、data 属性、固有クラスなど、ボタンごとに違いを表すフックは追加されていません。
Microsoft Q&A などでも、「.ext-button.ext-secondary はすべての副ボタンに共通で適用され、特定の 1 つだけを CSS で安定して狙うことはできない」という趣旨の回答がなされています。
このため、既定の Company branding + CSS だけで、
- サインアップ画面のキャンセルボタンだけ赤くする
- 同じ画面上の「戻る」はそのままにしておく
といった“ボタン単位” のデザイン変更は仕様上不可能です。
テキストや順番に依存するのが危険な理由
「じゃあ、画面上でキャンセルが一番右にあるから :last-of-type を当てればいいのでは?」と思うかもしれません。しかし、これは非常に壊れやすいアプローチです。
- UI の将来変更(ボタンが増える/減る/順番が変わる)
- ロケールや言語の違い(日/英/多言語でボタン構成が変化)
- Microsoft 側のマークアップ変更(HTML 構造やクラス名の変更)
といった要因で、突然違うボタンにスタイルが乗ってしまうリスクがあります。
テキスト(「キャンセル」という文字列)で狙うことも、CSS には :contains() のような標準疑似クラスがないため不可能です(JavaScript が使えれば別ですが、後述の通りスクリプトはサポートされません)。
仕様から見える「できないこと」と「できること」
ここまでをまとめると、Entra External ID のカスタムブランディング CSS には以下の制約があります。
| 項目 | できること | できない/注意点 |
|---|---|---|
| 背景・ロゴ | 画像や色の変更 | HTML 構造そのものの変更は不可 |
| テキスト | 一部ラベル・説明文の差し替え | ボタンのテキストに合わせた CSS 条件分岐は不可 |
| CSS セレクタ | 公開されている .ext-* クラスへのスタイル適用 | ボタンごとの固有 ID / クラスは提供されない |
| スクリプト | カスタム CSS のみサポート | JavaScript の挿入は不可(<script> はサポート対象外) |
この仕様を踏まえると、
- 「副ボタン全部」を同じデザインにする → 問題なく可能(
.ext-button.ext-secondaryを使う) - 「キャンセルだけ」など、ボタン単位の差別化 → 既定フロー + CSS だけでは 安定しては実現できない
という結論になります。
世代によって変わる選択肢:新しい External ID と従来 B2C
ここから先の方針を決めるうえで大事なのが、自分のテナントがどの世代の「Entra External ID」を使っているかです。
- 従来の Azure AD B2C 世代(Entra ID に統合されつつある既存の CIAM)
- 新しい External ID プラットフォーム(「カスタムポリシー不要」を掲げる次世代 CIAM)
Microsoft は新しい External ID では、カスタムポリシー(Identity Experience Framework, IEF)を前提としない設計に舵を切っています。FAQ でも、「新しい External ID プラットフォームでは IEF カスタムポリシーはサポートされず、代わりにビルトインのユーザーフローで同等のシナリオをカバーする」と明言されています。
一方で、既存の Azure AD B2C テナントでは引き続き IEF カスタムポリシーが利用されており、「高度な UI 制御が必要ならカスタムポリシーへ移行する」というアプローチは依然として有効です。
そこで本記事では、次の 2 パターンに分けて回避策を整理します。
- 従来 B2C / IEF が使える場合:カスタムポリシーで HTML を完全制御する
- 新しい External ID(IEF なし)の場合:アプリ側の UI でキャンセルを制御する
回避策(1):カスタムポリシー(IEF)でボタンに固有 ID を付ける
まずは、従来の Azure AD B2C / Entra ID for customers で IEF カスタムポリシーが使える前提の場合です。
IEF カスタムポリシーでは、
- 各ステップの UI を定義する XML(カスタムポリシーファイル)
- その UI の実体となる HTML テンプレート(自前でホスト)
を自由に編集できます。そのため、キャンセルボタンに id や固有クラスを追加し、CSS でピンポイントに装飾することが可能です。
大まかな手順
| ステップ | 内容 | ポイント |
|---|---|---|
| 1. IEF 有効化 | Azure AD B2C / Entra External ID テナントで IEF(カスタムポリシー)を有効化し、Starter Pack を導入 | Microsoft 提供の Starter Pack をベースにすると最初の学習コストを抑えられます |
| 2. ContentDefinitions 設定 | サインアップ画面など対象ページの ContentDefinitions に、カスタム HTML テンプレートの URL を指定 | テンプレートは Azure Storage 静的サイトや CDN などでホスト |
| 3. HTML テンプレート編集 | キャンセルボタンに id や固有クラスを追加 | 他のボタンと区別できるよう命名規則を揃えると管理しやすい |
| 4. CSS で個別スタイル | #signup-cancel などのセレクタで個別に装飾 | ページ共通のレイアウト CSS と分離すると保守性が高まる |
HTML / CSS の例
カスタムテンプレート側では、例えば次のように記述できます。
<!-- サインアップ画面の一部(カスタムテンプレート) -->
<form method="post" class="signup-form">
<button type="submit" class="ext-button ext-primary">サインアップ</button>
<button type="button" class="ext-button ext-secondary">戻る</button>
<button
id="signup-cancel"
class="ext-button ext-secondary signup-cancel"
type="button">
キャンセル
</button>
</form>
<style>
/* 副ボタン共通の見た目 */
.ext-button.ext-secondary {
border-radius: 4px;
border: 1px solid #666;
background-color: transparent;
color: #333;
}
/* キャンセルだけを“弱く・目立たせない”デザインにした例 */
#signup-cancel {
border-style: dashed;
opacity: 0.7;
}
/* 逆に、注意喚起のために目立たせる場合 */
#signup-cancel.critical {
border-color: #c62828;
color: #c62828;
}
</style>
このように、HTML レベルでフックが用意できる環境であれば、CSS での個別制御は簡単です。
カスタムポリシーを選ぶメリット
- ボタン単位・フィールド単位で細かく UI を制御できる
- JavaScript も使えるため、入力補助やアニメーションなど高度な UX が実現可能
- バックエンド API との連携、複雑な分岐ロジックなど、認証フロー全体を柔軟に設計できる
デメリット・注意点
- ポリシー XML の構造やクレームルールなど、学習コストが高い
- テスト・デプロイ・ロールバックなど、運用プロセスを整備しないと事故リスクがある
- 新しい External ID プラットフォームでは IEF 非対応であるため、将来の移行方針を含めた設計が必要
とはいえ、「どうしてもキャンセルだけ CSS を変えたい」「UX 要件が厳しい」といった場面では、いまだにカスタムポリシーが唯一の公式寄りの解決策になるケースは多いです。
回避策(2):新しい External ID ではアプリ側で UI を握る
もしあなたのテナントが、すでに 新しい External ID プラットフォームで、IEF カスタムポリシーが使えない場合はどうすればよいでしょうか。
この場合は、Entra External ID のサインアップ画面そのものに過度な期待をせず、
- 「認証は External ID に任せるが、サインアップフォームの UI はアプリ側で用意する」
という設計に切り替えるのが安全です。つまり、
- 自前の Web / SPA / モバイルアプリで、ブランドどおりのサインアップ画面を作る
- そこで「キャンセル」ボタンや注意文、ヘルプリンクなどを自由に設計する
- 実際の認証・アカウント作成は Entra External ID の API やユーザーフローを通じて行う
こうしておけば、
- キャンセルボタンだけ色を変える
- キャンセル時に確認ダイアログを出す
- 端末ごとにキャンセル位置を変える(モバイルでは上部、デスクトップでは右下など)
といった UI の細かい要求にも、アプリ側の実装で柔軟に対応できます。
実装パターンのイメージ
例えば SPA(React / Vue など)の場合:
- アプリ内に
/signupページを用意し、ブランドに合わせたフォームを実装 - 「アカウントを作成」ボタンで External ID のサインアップフロー(または認証 API)を呼び出す
- キャンセルボタンでは、単に
history.back()や「トップに戻る」遷移など自前ロジックを実行
Entra External ID 側の画面に依存しないため、「ボタンが何個あるか」「どのクラスが付いているか」といった問題を根本から回避できます。
既定フロー + CSS だけで「やれなくはない」非推奨テク
「とはいえ、今すぐ IEF やアプリ実装修正には踏み切れない。とりあえずキャンセルだけ微妙に変えたい」という場合に、あくまで一時しのぎとしてあり得るテクニックも整理しておきます。
以下はいずれも Microsoft がサポートを保証している方法ではなく、将来的に壊れる可能性が高いため、本番環境では慎重に判断してください。
| テクニック | 狙い | 主なリスク |
|---|---|---|
位置ベース指定:nth-of-type() | 「一番右の副ボタン」などをキャンセルとみなす | ボタン構成・順序の変更で簡単に崩れる |
| 強いセレクタチェーン | 親コンテナのクラスと組み合わせてページ単位で絞り込む | 内部クラス名の変更で丸ごと効かなくなる可能性 |
| ロケール限定の上書き | 特定言語のときだけ、訳文と合わせて見た目を調整 | 将来の翻訳変更・多言語追加に弱い |
例 1:位置ベースで「最後の副ボタン」を狙う
/* サインインボックス内の副ボタンのうち最後のものを“キャンセル”と仮定 */
.ext-sign-in-box .ext-button.ext-secondary:last-of-type {
opacity: 0.7;
border-style: dashed;
}
一見うまくいきますが、
- ユーザーフローのアップデートでボタンが増えた
- A/B テストや新機能で別の副ボタンが追加された
といったタイミングで、意図しないボタンにスタイルが適用される危険があります。
例 2:コンテナクラスを含めたセレクタチェーン
特定のページだけに存在するコンテナクラスがあれば、それを利用して絞り込む方法もあります(例は架空のクラス名)。
/* “サインアップ用” と仮定したコンテナクラスにだけ適用 */
.signup-container .ext-button.ext-secondary {
/* サインアップ画面の副ボタンだけスタイル変更 */
}
しかし、このようなクラスはドキュメント化されておらず、いつ名前や階層が変わってもおかしくない内部実装です。運良く今は動いても、将来のメンテナンス性を考えるとおすすめできません。
JavaScript による動的 ID 付与が現実的でない理由
もしサインインページ内で JavaScript が自由に実行できるなら、
- ロード時にセカンダリボタン一覧を取得
- テキストが「キャンセル」のものにだけ
id="signup-cancel"を付与 - CSS で
#signup-cancelを装飾
といった手も考えられます。しかし、Entra External ID / Entra ID のカスタムブランディングでは、カスタム CSS はサポートされる一方、任意の JavaScript を埋め込む機構は提供されていません。
そのため、「JS でなんとかする」というアプローチは現時点では現実的ではありません。
どのアプローチを選ぶべきか:判断の目安
ここまでの選択肢を、要件別に整理してみます。
| 要件 | 推奨アプローチ | コメント |
|---|---|---|
| 副ボタン全体の色や角丸を変えたいだけ | 既定フロー + .ext-button.ext-secondary で共通 CSS | もっともシンプルでサポートも想定された使い方 |
| キャンセルだけを別のスタイルにしたい(かつ IEF 利用可能) | カスタムポリシー + 自前 HTML テンプレート | ボタン単位で ID / クラスを付与して制御 |
| キャンセルだけを別のスタイルにしたい(IEF なしの新 External ID) | アプリ側でサインアップ UI を実装し、External ID は認証・管理に専念 | UI の自由度をアプリに寄せる設計。やや実装コスト高 |
| とりあえず簡単にキャンセルだけ変えたいが、長期運用の予定 | 非推奨テク(nth-of-type 等)は基本避ける | 短期的なワークアラウンドに留め、早めに正式な手段に移行 |
アクセシビリティと UI デザインの観点
技術的な話から少し離れて、「キャンセルだけ見た目を変える」という要求が本当に UX 上正しいか?という視点も重要です。
- キャンセルを主要ボタンよりも目立たせすぎると、誤操作のリスクが上がる
- 主要アクション(サインアップ)よりもキャンセルに視線が行くと、コンバージョン率に悪影響
- 色覚特性のあるユーザーにとって、色だけの違いは認識しにくい場合がある
一般的には、
- プライマリボタン:ブランドカラーの塗りつぶしボタン
- セカンダリボタン:アウトラインまたはフラットなグレーボタン
- キャンセル:テキストリンク風、または最小限のアウトライン
といった視覚的な階層をつけるのが推奨されます。キャンセルだけ極端に赤くしたり、巨大にしたりせず、
- 配置(右端ではなく左側に置く)
- ラベル(「キャンセル」よりも「前の画面に戻る」など誤解されにくい文言)
といった工夫で誤操作を減らす方が、中長期的には良い UX になることが多いです。
運用面でのヒント:テストと監視
最後に、どのアプローチを採用するにしても共通して大事な運用のポイントを挙げておきます。
多言語・ロケールでのテスト
- 日本語だけでなく、英語や今後追加予定の言語でも必ず画面を確認する
- ボタンの数や文言が言語ごとに微妙に異なる可能性がある
位置ベースや内部クラスに依存した CSS を書いている場合は、特にここで検知しないと、本番環境で初めて崩れに気付く…という事態になりがちです。
レスポンシブ・ブラウザ差異
- PC・タブレット・スマートフォンすべての画面幅で確認する
- 主要ブラウザ(Edge / Chrome / Safari など)での表示崩れもチェック
Entra 側のレイアウトもレスポンシブ対応しているため、画面幅によってボタンの並びや改行位置が変わることがあります。これも位置ベースの CSS を壊す要因です。
変更履歴の管理
- アップロードした CSS ファイルは Git 等でバージョン管理する
- いつ、どの変更がサインアップ画面に影響したのか追えるようにする
特に IEF / カスタムポリシーを採用する場合は、
- ポリシー XML
- HTML テンプレート
- CSS / JavaScript
といった複数ファイルが絡むため、CI/CD パイプラインを整備しておくと安心です。
まとめ
本記事のポイントを改めて整理すると、次の通りです。
- Entra External ID の既定ユーザーフローでは、副ボタンはすべて
.ext-button.ext-secondaryという共通クラスでスタイルされ、キャンセルだけを CSS で安定して装飾することはできない - カスタム CSS で触れるのは公開されたセレクタのみで、ボタンごとの固有 ID / クラスは提供されない
- 従来の Azure AD B2C / IEF が利用できる環境であれば、カスタムポリシー + 自前 HTML テンプレートによってボタンに固有 ID を付けるのが、もっとも堅牢な回避策
- 新しい External ID プラットフォームでは IEF が前提ではないため、サインアップ UI をアプリ側で実装し、External ID は認証・ユーザー管理に専念させる設計が現実的
:nth-of-type()などの位置ベース指定や、内部クラスに依存したセレクタチェーンは、「やれなくはない」が壊れやすく非推奨- UX の観点では、キャンセルだけを極端に目立たせるより、プライマリ/セカンダリ/キャンセル間の視覚的階層と誤操作防止を意識したデザインが重要
「キャンセルだけ CSS を変えたい」という一見シンプルな要望は、Entra External ID の仕様や将来のプラットフォーム方針と密接に関わるテーマです。短期的なワークアラウンドで済ませるのか、それともこの機会に IEF や新 External ID へのアーキテクチャ見直しを行うのか——自組織のロードマップと照らし合わせて、最適な選択肢を検討してみてください。

コメント