macOS 26 Liquid Glass:ScrollView の外側に padding を置くとスクロールエッジエフェクトが消える

macOS 26 の Liquid Glass では、NavigationStack 配下の ScrollView がツールバーに到達していれば、自動的にグラデーションブラー(スクロールエッジエフェクト)が適用されます。しかし ScrollView外側.padding() があると、エフェクトが無効化され、従来型のツールバー表示になる仕様があるようです。

これで丸2日間、Claude Code Opus 4.6と一緒にハマりまくってました。というわけで、備忘録を残しておきます。同じ問題に遭遇したら、このページをClaude Codeに教えてあげてください。

スクロールエッジエフェクトとは

macOS 26 で導入された Liquid Glass デザインでは、スクロール可能なコンテンツがツールバーの下を通過するとき、境界線の代わりにグラデーションブラーで自然にフェードします。これは NavigationStack + ScrollView(または List)の組み合わせで自動的に有効になります。

参考: WWDC25 Session 323 — Liquid Glass in SwiftUI (7:49〜11:10)

問題の再現

NG padding が ScrollView の外側

struct ContentView: View {
    let columns = [GridItem(.adaptive(minimum: 150))]

    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVGrid(columns: columns, spacing: 12) {
                    ForEach(0..<100) { i in
                        RoundedRectangle(cornerRadius: 8)
                            .fill(.quaternary)
                            .frame(height: 120)
                            .overlay { Text("Item \(i)") }
                    }
                }
            }
            .padding(24) // ← ここが原因
            .navigationTitle("Demo")
            .toolbar {
                ToolbarItem(placement: .automatic) {
                    Button("Star", systemImage: "star") {}
                }
            }
        }
    }
}

結果: ツールバーとコンテンツの境界が従来どおりのシャープな線になります。

OK padding を ScrollView の内側に移動

struct ContentView: View {
    let columns = [GridItem(.adaptive(minimum: 150))]

    var body: some View {
        NavigationStack {
            ScrollView {
                LazyVGrid(columns: columns, spacing: 12) {
                    ForEach(0..<100) { i in
                        RoundedRectangle(cornerRadius: 8)
                            .fill(.quaternary)
                            .frame(height: 120)
                            .overlay { Text("Item \(i)") }
                    }
                }
                .padding(24) // ← 内側に移動
            }
            .navigationTitle("Demo")
            .toolbar {
                ToolbarItem(placement: .automatic) {
                    Button("Star", systemImage: "star") {}
                }
            }
        }
    }
}

結果: Liquid Glass のグラデーションブラーが正しく表示されます。

なぜ起きるのか

スクロールエッジエフェクトは、システムが ScrollView のフレームがツールバー領域と接しているかどうか を検知して自動適用しています。

外側の .padding() は ScrollView 自体のフレームを縮めるため、ScrollView が NavigationStack のコンテンツ領域を完全に埋めなくなります。

注意点として、水平・垂直を問わず、方向に関係なくエフェクトが無効化されます。横方向だけのpaddingだとしても、無効になることに注意が必要です。おそらく、Toolbarとすべての領域が接していないとダメ、ということでしょう。

まとめ

 外側 padding内側 padding
ScrollView のフレーム縮むウィンドウ幅いっぱい
ツールバーとの接触離れる接する
スクロールエッジエフェクト無効有効

Liquid Glass のスクロールエッジエフェクトを活かすには、ScrollView を画面端まで広げ、余白はコンテンツ側で確保することが重要です。これは ListScrollView に共通する原則です。