
CSS
イベント
マガジン
技術ブログ
はじめに こんにちは、ZOZOTOWN企画開発部 企画フロントエンド2ブロックのパクサンイです。普段はZOZOTOWNにあるCMSベースのLPページのメンテナンスや機能追加、企画LPページ環境のメンテナンスを担当しています。 ZOZOTOWNの複数のWebアプリケーション間で、プロモーション用ランディングページコンポーネントを共有するために、 Lit ベースのWeb Componentsを導入しました。本記事ではその事例を紹介します。 ZOZOTOWNでは多数のLPページが開設・更新されており、従来はiframeを使った埋め込み方式でUIを共有していました。しかし、この方式にはさまざまな課題が存在し、レガシー環境からNext.jsベースの新環境へのリプレイスを進める中で、フレームワークに依存しないUI共有アーキテクチャが必要となりました。 本記事では、iframeベースの共有方式が抱える具体的な課題と、LitベースのWeb Componentsを採用した理由と選定プロセスを解説します。さらに、フレームワーク非依存なコンポーネント共有基盤を設計・実装する中で得た経験を共有します。 対象読者 マルチWebアプリケーション環境でUI共有に課題を感じているフロントエンドエンジニア iframeを使ったUI共有方式の代替手段を探している方 Web Componentsの導入を検討している方 目次 はじめに 対象読者 目次 背景・課題 ZOZOTOWNフロントエンドのマルチWebアプリケーション構成 LPコンポーネントの共有仕様 従来のiframeベース共有方式とその課題 1. レイアウト制御の煩雑さ 2. UI制御の複雑化 3. SEOの制約 アプローチ:Web Componentsの導入 要件整理 技術選定:Lit基盤Web Components Litを選択した理由 npmパッケージ方式を除外した理由 設計・実装 全体アーキテクチャ 1. 利用側アプリケーションによるデータ取得・加工 2. Lit ContextによるProps Drilling防止 3. Scriptローディングによる独立したUI更新 4. Shadow DOMからLight DOMへの切り替え ビルド・配信 全体フロー LPコンポーネント開発側(コンテンツ共有専用リポジトリ) 利用側Webアプリケーション 効果 学んだこと 今後の課題 今後の展望 まとめ 最後に 参考資料 背景・課題 ZOZOTOWNフロントエンドのマルチWebアプリケーション構成 現在、ZOZOTOWNのフロントエンドは3つのマルチWebアプリケーションで運用されています。 リポジトリ 説明 主な役割 リポジトリA(レガシー環境) 統合リポジトリ 既存の全ページを管理 リポジトリB(リプレイス環境) コアメインページ ホーム、カート、検索結果、商品詳細ページなど リポジトリC(リプレイス環境) 企画ページ フルスクラッチLP、CMS活用LP レガシー環境では複数のサービスが単一リポジトリで管理されていたため、共通UI共有に関する課題はありませんでした。しかし、リプレイス後にマルチWebアプリケーションが増えたことで、従来の方式ではUIを再利用できなくなりました。 LPコンポーネントの共有仕様 ZOZOTOWNでは特定のLPコンポーネントを複数のページで表示しています。一部のページでは以下の2つの形態で表示されます。 単独ランディングページ — header/footerを含むフルページ モーダル表示 — 特定ページのバナークリック時に、header/footerなしでコンテンツセクションのみをモーダルで表示 つまり、ほぼ同一のUIでありながら、header/footerの有無、SEOメタタグ、計測用トラッキングスクリプトの有無などで差異がある仕様でした。 従来のiframeベース共有方式とその課題 リプレイス後は以下の方式でUIを共有していました。 環境 運用方式 リポジトリA(レガシー) LPページ配信 + iframe用LPページ(header/footerなし)配信 リポジトリB・C(リプレイス) 特定ページにバナー表示 → クリック時にモーダル内でiframeとしてリポジトリAのLPを埋め込み このiframe方式には以下の課題が存在していました。 1. レイアウト制御の煩雑さ iframeは独立したドキュメントを読み込むため、フレームサイズの調整や使用箇所ごとの非表示領域の処理は対応していたものの、煩雑な部分がありました。 2. UI制御の複雑化 各バリエーションに応じて非表示にすべき子コンポーネントもあり、クエリパラメータや postMessage で解決できるものの、ケースが増えるほど複雑化しました。 3. SEOの制約 検索エンジンはiframe内のコンテンツを src 側の所有として認識するため、SEO上の制約がありました。 アプローチ:Web Componentsの導入 要件整理 上記の課題を解決するために、以下の4つの要件を整理しました。 要件 説明 各アプリのデプロイなしにUI更新 iframe方式の利点であった各マルチWebアプリケーションのデプロイなしにUI変更が反映されることを維持 iframe脱却 各アプリケーションでネイティブにUIをレンダリング フレームワーク非依存 React、Vueなど、どのフレームワークでも使用可能であること 軽量バンドルサイズ 利用側に負担のない最小限のサイズを維持 技術選定:Lit基盤Web Components Web Componentsはブラウザのネイティブコンポーネントモデルであり、特定のフレームワーク(React、Vueなど)に依存せず、ブラウザが直接理解する標準技術です。主に以下の3つの中核技術で構成されています。 Custom Elements :開発者が独自のHTMLタグを定義できる。タグ名にはハイフン( - )を含む規約がある。 Shadow DOM :コンポーネントのスタイルとマークアップを外部ページから隔離(Encapsulation)する。 HTML Templates : <template> と <slot> 要素により、再利用可能なマークアップ構造を定義する。 このWeb Componentsをより効率的に開発するため、 Lit ライブラリを採用しました。 Litを選択した理由 選定基準 Litの特徴 バンドルサイズ 約5KB(minified + compressed)で非常に軽量 リアクティブプロパティ Reactive Propertiesにより状態変更時に自動再レンダリング テンプレート Tagged Template Literalsベースで別途コンパイル不要 パフォーマンス Virtual DOM diffingなしに動的部分のみを直接更新 相互運用性 すべてのLitコンポーネントはネイティブWeb Componentであり、HTMLを使うあらゆる場所で動作 npmパッケージ方式を除外した理由 LPページはテキスト更新の頻度が高く、UIも不定期に変更されます。npmパッケージで運用すると、変更のたびに各環境でパッケージ更新+デプロイが必要となり、運用負荷が大きいため除外しました。 設計・実装 全体アーキテクチャ コンテンツ共有専用リポジトリを新たに構築し、以下の設計原則を適用しました。 1. 利用側アプリケーションによるデータ取得・加工 ZOZOTOWNにはページアクセス時に初期設定すべき値やAPIフェッチのためのロジックが各アプリケーションに存在します。これらのロジックをコンテンツ共有専用リポジトリにも含めると管理が二重になりメンテナンス負荷も大きくなるため、このリポジトリでは UIレンダリングのみ を責任範囲としました。 利用側の親アプリケーションでデータを取得・加工してpropsで渡す形式を採用しています。 2. Lit ContextによるProps Drilling防止 UI内部で必須的に共有すべき情報(デバイス種別、性別など)は、 Lit Context を活用したカスタム要素を設けて処理しました。 Lit ContextはReactのContext APIと同様の概念で、Props Drillingなしに上位から下位コンポーネントへデータを渡すことができます。 3. Scriptローディングによる独立したUI更新 各Webアプリケーションで別途デプロイなしにUI変更が可能なよう、 Scriptローディング を採用しました。各アプリケーションでは <script> タグで必要なコンポーネントのJSファイルを読み込み、クライアントでWeb Componentがレンダリングされます。 4. Shadow DOMからLight DOMへの切り替え Web Componentsの代表的な特徴であるShadow DOMは、スタイルを完全に隔離し、コンポーネント内部のCSSが外部に影響せず、外部CSSも内部に影響しません。 しかし、今回のケースでは、Shadow DOMで隔離して管理するUIではなく、利用側から自由にスタイルだけでなく要素にもアクセスできることが重要でした。そのため、Shadow DOMの代わりに Light DOM を採用しました。 ビルド・配信 Viteを使用してLit基盤Web Componentをビルドし、S3にデプロイしてCDN経由で配信します。 全体フロー LPコンポーネント開発側(コンテンツ共有専用リポジトリ) Lit + Vite dev serverでローカル開発 各テスト環境にてHTML + JSで動作確認 問題なければ各環境(S3)にデプロイして確認 利用側Webアプリケーション SSR時にCMS APIでデータ取得(スケジュールに応じて変更されるテキストなどはCMSで管理) クライアントで <script> タグによるJSファイルローディング、Web Componentのレンダリング カスタムタグへCMS API仕様に合わせたデータをpropsで渡す 効果 この仕組みの導入により、以下の効果が得られました。 マルチWebアプリケーション間でiframeを使わずにUIコンポーネントを共有できるようになった 各アプリケーション側のリリース(デプロイ)なしでコンテンツ更新が可能になった 利用側からスタイルだけでなく要素へのアクセスも自由に可能になった(Light DOM採用) CMS連携により、エンジニア以外でも直接スケジュールベースのデータ管理が可能に 学んだこと Litを通じて開発する中で、Web Componentsのベースとなるウェブ標準技術をより深く理解し、関心を持つようになりました。また、CSS変数などを活用してJavaScriptなしにCSSだけでスタイルを制御する方法も知ることができました。 今後の課題 Web Components公式のSSR対応はまだ限定的ですが、Lit SSRなど複数の解決策がライブラリやコミュニティで共有されています。現在、このプロジェクトで管理しているLPページの仕様ではWeb ComponentのSSRは不要ですが、将来に備えた準備は必要だと考えています。 また、現在の運用方式では、Scriptローディング+CMSデータ連携という構造上、テストが非常に重要であり補強が必要です。 今後の展望 移行すべきLPページが多数残っており、段階的にマイグレーションを進めていく予定です。より小さな単位の共用コンポーネントもこの基盤で管理できるよう拡張を検討しています。また、可能であれば、ネイティブアプリケーションでの活用も検討したいと考えています。 まとめ 本記事では、ZOZOTOWNのマルチWebアプリケーション環境におけるiframeベースUI共有方式の課題を解説しました。また、LitベースのWeb Componentsを活用したフレームワーク非依存のコンテンツ共有基盤の構築事例を紹介しました。 ReactベースであればReactでもUIを共有する方法はあります。しかし、今後どのフレームワークでも問題なく移植できるWeb Componentsを選択し、メインスタックと共存しながら運用するのもよいのではないでしょうか。同様の課題をお持ちの方の参考になれば幸いです。 最後に ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com 参考資料 MDN - Web Components Lit 公式ドキュメント Lit Context MDN - Using Shadow DOM MDN - iframe Vite - Building for Production
この記事は、合併前の旧ブログに掲載していた記事(初出:2020年9月8日)を、現在のブログへ移管したものです。現時点の情報に合わせ、表記やリンクの調整を行っています。こんにちは、お久しぶりです。岡部和...
WebサイトやアプリケーションのUIをデザインする際、テキストの色や背景色にどのような「黒」を使っていますか? CSSでとりあえず color: #000000; や color: black; と指定しているエンジニアの方も多いかもしれません。しかし、多くのサービスでは、テキストや背景に「完全な黒(#000000)」が使われていません。黒に近いグレーが使われています。 一見すると些細な違いに思えますが、実はこの「黒の選び方」には、人間の視覚や画面の特性に基づいたロジックが存在します。 今回は、なぜUIデザインにおいて「真っ黒」を避けるのか、その論理的な理由と、「良い黒」の作り方、そして例外的な使われ方を解説します。 理由1:コントラストが強すぎると目が疲れる 紙に印刷された黒い文字を読むのとは異なり、私たちが普段見ているPCやスマートフォンのディスプレイは「発光体」です。 真っ白な背景(#FFFFFF)に真っ黒なテキスト(#000000)を配置すると、画面の輝度の最大値(100%の光)と最小値(0%の光)が隣り合うことになります。この極端なコントラストは、目に対して強い刺激を与えます。 アクセシビリティの観点から「コントラスト比は高い方が良い」とされていますが、高ければ高いほど良いというわけではありません。視覚過敏を持つユーザーや、乱視のユーザーにとっても、100%のコントラストは逆に可読性を下げてしまうのです。 理由2:現実世界に「純粋な黒」はほとんど存在しない 色彩心理学や物理学の観点からも、#000000 は特異な色です。 現実世界を見渡してみてください。アスファルト、カラスの羽、黒いスマートフォンケース……私たちが日常で「黒」と認識しているもののほとんどは、光をわずかに反射しており、環境光の影響を受けてかすかに色味を持っています。光の反射率が完全に0%の「純粋な黒」は、光吸収素材のような特殊な状況にしか存在しません。 そのため、人間の脳は画面上の #000000 を見たとき、無意識に「不自然さ」や「重苦しさ」、あるいは画面に穴が空いているような「圧迫感」を感じ取ります。 UIデザインが目指すのは、現実世界の物理法則に寄り添った自然な認知です。自然界に存在しない完全な黒を避けることで、UI全体から人工的な違和感を取り除くことができます。 理由3:ダークモードで「奥行き」が表現できなくなる 近年標準となった「ダークモード」の設計において、背景を #000000 にすることはUIに制約が発生する恐れがあります。 UIデザインは、ボタンやカードなどの要素に「ドロップシャドウ(影)」をつけることで、要素が重なり合っている「Z軸(奥行き)」を表現します。手前にある要素ほど影が大きく、背景から浮き上がって見えます。 しかし、背景色が #000000(これ以上暗くならない色)の場合、その上に要素を置いて影をつけても、背景と同化してしまい影が見えません。結果として、どの要素が手前で、どれがクリック可能なのかといった階層構造(エレベーション)を視覚的に伝えることが難しくなります。 UIの「黒」の作り方 では、実際にコーディングやデザインをする際、どのような「黒」を使えばよいのでしょうか。 1. 無彩色のダークグレー 最もシンプルで失敗がないのは、明度を10パーセント程度上げたダークグレーです。 2. ブランドカラーを混ぜた「リッチブラック」 純粋なグレー(RGBの値がすべて同じ色)ではなく、ブランドのメインカラー(プライマリーカラー)をわずかに混ぜた黒、通称「リッチブラック」を使用する方法です。 例えば、上記の「Jira」のようにプライマリーカラーが「青」のサービスなら、黒にも少しだけ青味を足します。 これにより、画面全体の色調が馴染み、統一感と高級感が生まれます。 あえて「完全な黒(#000000)」を利用するケース ここまで「使うべきではない」と解説してきましたが、 あえて #000000 を利用するケース も存在します。 OLED(有機EL)ディスプレイ機器でのバッテリー節約 有機ELディスプレイは、黒を表示する際に「そのピクセルの発光を完全にオフにする」という仕組みを持っています。例えばスマートフォンアプリにて背景色を#000000とすれば、該当の端末でバッテリー消費を抑えることができます。 ハイコントラストで世界観を伝える ブランドのコンセプトとして、意図的にエッジを効かせ、強烈なコントラストで強い印象を与えたい際に、あえて純粋な黒と白をぶつける場合があります。 アクセシビリティ要件(ハイコントラストモード) 視覚障害を持つユーザー向けにOSレベルで提供される「ハイコントラストモード」では、視認性を最優先するため、#000000 と #FFFFFF の組み合わせが意図的に使用されます。 まとめ:色の設計は、まず「ロジック」 「なぜその『黒』にするのか」を意識するだけで、UIのクオリティは向上します。 目の疲れを防ぐため(コントラストの調整) 自然な認知を促すため(現実世界とのリンク) 奥行きを表現するため(ダークモードの設計) UIデザインはサービスの固有性を表現する要素もありますが、前提として人間の特性やデバイスの仕様に基づいた「ロジック」があります。これにより、適切な配色が可能になります。 Photo by Ricardo Avelar , Kyaw Zay Ya , Wander Fleur , Michael Maasen Eva Wilcock , Jordi Vich Navarro , Vivek Doshi , Aaron Burden on Unsplash ご覧いただきありがとうございます! この投稿はお役に立ちましたか? 役に立った 役に立たなかった 0人がこの投稿は役に立ったと言っています。 The post 配色ロジック:なぜ、UIの「黒」は黒ではないのか first appeared on SIOS Tech Lab .
動画
該当するコンテンツが見つかりませんでした






















