LoginSignup
8
10

More than 5 years have passed since last update.

【React】z-indexで困る問題

Posted at
1 / 26

今日のテーマ


私はz-indexが嫌い


なぜ?

->デモ解説


step 0

  • スクロールするとModalボタンがheaderに被ってしまう

ヘッダーの z-inedx 1、ドロワーの z-index 2、モーダルは z-index 10。
ヘッダーはしばらくスクロールするとfixedになってmainの上に表示される。
モーダルをヘッダーの上に表示したいので z-index 10 になっているが、
コンテナにz-indexがついているのでボタンまで上に表示されてしまう。

step 1

  • ヘッダーをボタンより上に表示したくて、z-index 20 にする

「Next 0」ボタンを1回押して次に進める。
Modalボタンはヘッダーの下にくるようになったが、
Modalボタンを押すとモーダルがヘッダーに下に出てしまう。
ヘッダーが20、モーダルが10なので、そりゃそうだ。

step 2

  • .modal をヘッダーより上に表示したくて、z-index 30 にする

「Next 1」ボタンを1回押して次に進める。
すると、ヘッダーが20、モーダルが30にもかかわらず、
モーダルがヘッダーの下に表示されてしまう。
モーダルのコンテナ(.modalComponent)が10だからだ。

step 3

  • .modalComponentのz-indexをinitialにする

「Next 2」ボタンを1回押して次に進める。
すると、ヘッダーが20、モーダルが30の順番通りになって、無事モーダルが表示されて!
一見うまくいったようにみえる。
しかしドロワーを開いてみると、今度はドロワーがヘッダーの下に表示されてしまっている。
ヘッダーが20、ドロワーが2なので当然である。

step 4

  • ドロワーを40にしよう!

「Next 3」ボタンを1回押して次に進める。
すると、ドロワーが z-index 40 になり、無事ヘッダーの上に表示された!

これで解決?

今回はわざとアホらしいz-indexのサンプルを作ったが、
業務中でもこういったz-index問題は意外と起る。
しかも、他人の書いたコードに影響を受けまくるし、
z-indexをいじると他人の書いたコードに影響も与えやすい。
しかもバグっていることに気づきにくいし、z-indexは調査もしずらい。
注意深く作ることで回避はできるが、健全な回避方法とは言い難い。

z-indexは、最後の手段にしよう・・・
できればちゃんとDOMtreeの順番通りに表示されるのが直感的だし、
バグも少なく扱いやすい。


めでたしめでたし


そんなわけねーだろ!


今日のお話


【React】z-indexで困る問題


自己紹介

  • 渡辺 貴明
  • nabepon_dev follow me!
  • アジアクエスト株式会社
  • フロントエンドエンジニア

直近でやったプロジェクト

某飲食サービスの姉妹サービス
お察し...
react, redux, css modules, react-router etc...


旧時代

モーダル、fixedヘッダー、ドロワーメニューなど、
手前に表示する要素の実装。

jQuery時代だと、DOM treeの最後の方に表示することで、
z-indexに頼らずとも実装することができた。


手前に表示したいやつはbodyにappend

var $modal = $('<div class="modal">modal</div>')
$(body).append($modal);

表示順もDOMをゴリゴリ弄ればいいだけなので、
jsでなんとかすることができた。


現代

Reactだとこういったことができない。
できるが、React上でDOMを探してappendするようなコードは書きたくない。
ではReactではどう実装するかというと、2パターンが考えられる。


1つはz-indexで頑張る方法。

もう1つはDOMの後ろにあらかじめ配置しておく方法。


DOMの後ろにあらかじめ配置

<div id="root">
  <HeaderComponent />

  <main>
    <div>
      ...
      <FooComponent>
        <button onClick={openFoo}>open</button>
      </FooComponent>
      ...
      <BarComponent>
        <button onClick={openBar}>open</button>
      </BarComponent>
      ...
      ...
    </div>
  </main>

  <FooterComponent />

  <ForwardLayer>
    {isFooOpen ?
      <div class="fooModal"> foo </div>
    : null }

    {isBarOpen ?
      <div class="barModal"> bar </div>
    : null }
  </ForwardLayer>
</div>

Reactだと事前にコンポーネントを配置し、
条件分岐でコンポーネントの表示非表示を行う。
面倒くさい。


Reactでも別の場所に表示したい!


ソリューション



ライブラリを書いた

react-transfer

※ Google翻訳しただけのREADME。翻訳PR待ってます...


使い方

Usageをみる。
Transporter内にある、TransportItemの要素を、Destinationに表示する。
Example
Demo


<div>- component code start</div> から
<div>- component code end</div>
間にコードが書かれているが、実際に表示されるのは
<div>- display component</div> の下。

また、表示前のソート処理を行うなどできるので、
jsで表示順を制御できる。

テストコード があるので、そっち見た方がわかりやすいかも。


【React】z-indexで困る問題


解決!(?)


アジアクエストではメンバーを無限に募集してます!

お仕事も募集してます!
受託開発も業務委託も、
どちらもご相談くださいませ。

nabepon_dev

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10