Closed8

position: fixed なのに viewport 基準にならない...

nbstshnbstsh

position: fixed とすれば必ず viewport 基準になるものだと思っていたが、そうではないケースに遭遇したのでメモしておく。

以下は一例で、dialog の中で position: fixed; top: 0; left: 0 な要素を作った場合、画面左上に固定されずに dialog の左上に固定される。(shadcn ui と tailwind で実装)

      <div>
        <Dialog>
          <DialogTrigger asChild>
            <Button variant='outline'>Click Me</Button>
          </DialogTrigger>
          <DialogContent className='sm:max-w-md '>
            <div>
              <div className='h-20 grid place-items-center'>Content</div>
              <div className='fixed top-0 left-0 p-3 bg-red-100'>Fixed</div>
            </div>
          </DialogContent>
        </Dialog>
      </div>

nbstshnbstsh
nbstshnbstsh

fixed
The element is removed from the normal document flow, and no space is created for the element in the page layout. The element is positioned relative to its initial containing block, which is the viewport in the case of visual media. Its final position is determined by the values of top, right, bottom, and left.

This value always creates a new stacking context. In printed documents, the element is placed in the same position on every page.

The element is positioned relative to its initial containing block, which is the viewport in the case of visual media って書いてあるんだけどな...

nbstshnbstsh

https://developer.mozilla.org/en-US/docs/Web/CSS/position#fixed_positioning

Fixed positioning is similar to absolute positioning, with the exception that the element's containing block is the initial containing block established by the viewport, unless any ancestor has transform, perspective, or filter property set to something other than none (see CSS Transforms Spec), which then causes that ancestor to take the place of the elements containing block. This can be used to create a "floating" element that stays in the same position regardless of scrolling. In the example below, box "One" is fixed at 80 pixels from the top of the page and 10 pixels from the left. Even after scrolling, it remains in the same place relative to the viewport. Also, when the will-change property is set to transform, a new containing block is established.

これか↓

unless any ancestor has transform, perspective, or filter property set to something other than none (see CSS Transforms Spec), which then causes that ancestor to take the place of the elements containing block

親要素が transform, perspective, filter が設定されていると、viewport ではなくその要素が基準になるのか

nbstshnbstsh

自分の例の場合、dialog の div に transform が設定されていたため、dialog が containing block になったみたい。

nbstshnbstsh

まとめ

transform, perspective, filter が設定された要素の配下で position: fixed を使うと、この要素が基準となり、 viewport 基準の positioning ができなくなる。

このスクラップは5ヶ月前にクローズされました