【CSS】z-index 競合を防ぐ isolation: isolate

どうも、くまだです。

CSSのisolation: isolateについて。

isolation: isolate

isolation: isolate;は自分を新しいスタッキングコンテキストにするプロパティです。

スタッキングコンテキストとは、重なり順を管理するグループのようなものです。同じグループ内でしか z-index は比較されません。

  <section class="pattern-block">

    <div class="pattern-block__columns">
      <div class="pattern-block__column">
        <div class="pattern-block__caption" data-status="before">before:<code>.isolation-wrapper</code> に isolation なし</div>
        <div class="blend-stage" data-stage="case2-before">
          <div class="big-square">
            <div class="isolation-wrapper">
              <div class="small-square">small-square (difference)</div>
            </div>
          </div>
        </div>
      </div>
      <div class="pattern-block__column">
        <div class="pattern-block__caption" data-status="after">after:<code>.isolation-wrapper</code> に <code>isolation: isolate</code></div>
        <div class="blend-stage" data-stage="case2-after">
          <div class="big-square">
            <div class="isolation-wrapper" data-isolation="on">
              <div class="small-square">small-square (difference)</div>
            </div>
          </div>
        </div>
      </div>
    </div>

  </section>
    * { box-sizing: border-box; }
    body {
      font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Hiragino Sans", "Yu Gothic UI", sans-serif;
      padding: 24px;
      max-width: 1200px;
      margin: 0 auto;
      background: #f5f5f7;
      color: #222;
      line-height: 1.6;
    }
    h1 { font-size: 1.4rem; margin-bottom: 6px; }
    h2 { font-size: 1.1rem; margin-top: 0; }
    .intro {
      color: #666;
      font-size: 0.85rem;
      margin-bottom: 24px;
    }
    .intro code {
      background: #eee;
      padding: 1px 5px;
      border-radius: 3px;
      font-size: 0.8rem;
    }
    .pattern-block {
      background: #fff;
      border: 1px solid #e0e0e0;
      border-radius: 10px;
      padding: 20px;
      margin-bottom: 28px;
    }

    .pattern-block__columns {
      display: grid;
      grid-template-columns: 1fr 1fr;
      gap: 16px;
    }
    .pattern-block__column {
      border: 1px solid #e0e0e0;
      border-radius: 8px;
      overflow: hidden;
    }
    .pattern-block__caption {
      padding: 8px 12px;
      font-size: 0.8rem;
      font-weight: bold;
    }
    .pattern-block__caption[data-status="before"] {
      background: #fde8e8;
      color: #c0392b;
    }
    .pattern-block__caption[data-status="after"] {
      background: #e3f7e7;
      color: #1f7a3d;
    }


    /* ============================================================ */
    /* mix-blend-mode の合成範囲(MDN 公式例ベース)                */
    /* big-square (lime) > isolation 親 > small-square (lime + difference) */
    /* 期待:                                                       */
    /*   isolation なし → 合成が祖先 big-square (lime) まで遡る → */
    /*                    lime - lime = 黒                          */
    /*   isolation あり → 合成が isolation 親内で完結 →           */
    /*                    親背景なし → 別の色(lime - 白系)       */
    /* ============================================================ */
    .blend-stage {
      position: relative;
      height: 240px;
      overflow: hidden;
    }
    .big-square {
      width: 100%;
      height: 100%;
      background: #00ff00; /* lime(緑)祖先要素の背景 */
      display: grid;
      place-items: center;
      padding: 20px;
    }
    .isolation-wrapper {
      position: relative;
      width: 160px;
      height: 160px;
    }
    .isolation-wrapper[data-isolation="on"] {
      isolation: isolate;
    }
    .small-square {
      position: absolute;
      inset: 30px;
      background: #00ff00; /* 親 big-square と同じ lime */
      mix-blend-mode: difference;
      display: grid;
      place-items: center;
      color: white;
      font-size: 0.8rem;
      font-weight: bold;
      text-shadow: 0 0 4px black;
    }

isolation なしの状態では、.small-square の mix-blend-mode: difference は、合成範囲が祖先 .big-square まで遡ります。同じ lime 同士の difference 合成なので、結果は黒(lime – lime = 黒)になります。

isolation を .isolation-wrapper`に付けた状態の場合、.small-square の合成範囲は .isolation-wrapperの中に限定されます。.isolation-wrapperには背景色を付けていないので、祖先 .big-square (lime) と直接合成されなくなり、.small-square は元のime 色で表示されます。

isolation: isolate がいちばん活躍するのは、コンポーネント内の z-index が外側の z-index 体系に干渉するのを防ぎたいときです。

ここまで読んでくださりありがとうございました。

この記事を書いた人