Safe Area — とは、ノッチとStatusBarからの余白

著者: IT Sectr 公開日: 2026-02-25 読了時間: 8 分

Safe Areaとは — システム要素(ノッチ、Dynamic Island、StatusBar、Homeインジケーター、角丸)によってコンテンツが隠されないことを保証する画面の安全領域です。Safe AreaはiOSとAndroidのアダプティブレイアウトに必須の要素であり、これがないと切り欠きのあるデバイスでインターフェースが正しく表示されない可能性があります。Apple HIG(2025)によると、2017年のiPhone X登場以来、すべてのアプリケーションはSafe Area Layout Guideを使用する必要があります。

重要なポイント

  • Safe Area — システム要素(ノッチ、StatusBar、Home Indicator、角丸)のない画面領域。
  • iOSでは、Safe AreaはSafeAreaLayoutGuideとSwiftUIの.safeAreaInset()修飾子によって実装されます。
  • Androidでは、Safe AreaはWindowInsetsと下位互換性のためのWindowInsetsCompatによって実装されます。
  • iPhone 14 Pro以降のDynamic Islandはノッチを置き換え、Safe Areaでも考慮されます。
  • Google Android Docs(2025)によると、Safe Areaを無視することはGoogle PlayとApp Storeでアプリが却下される3大原因の1つです。

Safe Areaとは?

Safe Areaとは、ハードウェアおよびソフトウェアのシステム要素(カメラの切り欠き(ノッチ)、Dynamic Island、ステータスバー(StatusBar)、ジェスチャーナビゲーションインジケーター(Home Indicator)、画面の角丸、ナビゲーションバー)によってコンテンツが隠されないことが保証される画面の長方形領域です。Safe Areaの境界は、デバイスの回転、キーボードの呼び出し、Split Viewの起動時に動的に変化します。Apple Human Interface Guidelines(2025)によると、Safe Areaを無視することは設計上の欠陥と見なされ、レビュー中にアプリが却下される原因となる可能性があります。

Safe Areaが必要な理由

Safe Areaは、モバイルエコシステムにおける画面の断片化の問題を解決します。iPhone X以前は、すべてのiPhoneが同じ比率の長方形ディスプレイを備えていました。ノッチの登場により、画面の種類は20以上に増加しました — さまざまなノッチサイズ、Dynamic Island、角丸、インジケーター。Safe Areaは、アダプティブマージンのための統一APIを提供することで、開発者をこれらの違いから抽象化します。Apple Developer(2025)によると、iOSはルートビューに自動的にSafe Areaを適用しますが、UICollectionViewとUIScrollViewでは手動設定が必要です。

デバイス切り欠きの種類上部マージン下部マージンStatusBar
iPhone SE(第3世代)なし20px0pxあり
iPhone 13 Proノッチ47px34pxノッチ内
iPhone 14 ProDynamic Island59px34pxDI内
iPhone 16 ProDynamic Island59px34pxDI内
Android Pixel 8パンチホール(カメラ)24px24pxステータスバー

iOSのSafe Area: SafeAreaLayoutGuideとSwiftUI

iOSでは、Safe AreaはUIKitのSafeAreaLayoutGuideとSwiftUIのsafeAreaInset修飾子によって実装されます。SafeAreaLayoutGuideは各UIViewに追加されるレイアウトガイドで、システム要素のない長方形を定義します。Interface Builderでは、Safe Areaは青色の領域として表示されます。SwiftUIはほとんどのコンテナに自動的にSafe Areaを適用しますが、.ignoresSafeArea()を使用して無視することもできます。

Swift
// UIKit: SafeAreaLayoutGuide
let safeGuide = view.safeAreaLayoutGuide
button.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    button.topAnchor.constraint(
        equalTo: safeGuide.topAnchor),
    button.leadingAnchor.constraint(
        equalTo: safeGuide.leadingAnchor),
    button.trailingAnchor.constraint(
        equalTo: safeGuide.trailingAnchor),
])

UIKitのSafeAreaLayoutGuideは、4つのアンカー(上、下、先頭、末尾)を定義し、ノッチ、StatusBar、Home Indicatorを自動的に考慮します。このアプローチはiOS 11以降のすべてのiOSデバイスで機能します。SwiftUIでは、NavigationStackまたはVStack内のコンテンツ修飾子によって同じ効果が得られ、SwiftUIが自動的にSafe Area Insetsを適用します。

Swift
// SwiftUI: safeAreaInsetとignoresSafeArea
ZStack {
    Color.blue
        .ignoresSafeArea()
    VStack {
        Text("Safe Area内のコンテンツ")
            .foregroundColor(.white)
        Spacer()
    }
}
.safeAreaInset(edge: .bottom) {
    Text("画面下部のバー")
        .padding()
        .background(.thinMaterial)
}

SwiftUIでは、.ignoresSafeArea()によって背景をSafe Areaの外側に拡張でき、.safeAreaInset(edge:)は指定した側のSafe Areaを縮小するカスタムパネルを追加します。これはナビゲーションバー、ツールバー、広告バナーの標準パターンです。

AndroidのSafe Area: WindowInsetsとSystem Bars

Androidでは、Safe AreaはWindowInsets(API 30+)とWindowInsetsCompat(AndroidXライブラリ)によって実装されます。WindowInsetsは、Status Bar、Navigation Bar、IME(キーボード)、システムジェスチャーのマージンを提供します。Android 10(API 29)以降、Googleはすべてのシステム要素の統一されたマージンセットを取得するために、WindowInsetsCompat.getInsets()をWindowInsetsCompat.Type.systemBars()と共に使用することを推奨しています。

Kotlin
// Android: WindowInsets(Kotlin)
class MainActivity : AppCompatActivity() {
    override fun onCreate(
        savedInstanceState: Bundle?
    ) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        ViewCompat.setOnApplyWindowInsetsListener(
            findViewById(R.id.main_content)
        ) { view, insets ->
            val systemBars = insets.getInsets(
                WindowInsetsCompat.Type.systemBars()
            )
            view.setPadding(
                systemBars.left,
                systemBars.top,
                systemBars.right,
                systemBars.bottom
            )
            ViewCompat.ON_APPLY_WINDOW_INSETS_LISTENER
        }
    }
}

この例では、WindowInsetsがすべてのシステムバー(上部のStatus Bar、下部のNavigation Bar)のマージンを返します。setOnApplyWindowInsetsListenerは、マージンが変更されるたび(回転、キーボード呼び出し)に呼び出されます。systemBars()メソッドは、ステータスバー、ナビゲーションバー、カスタマイゼーションバーを1つのセットに結合し、コードを簡素化します。

AndroidのEdge-to-Edge

Android 15以降、Googleは新しいAPIをターゲットとするすべてのアプリケーションにedge-to-edge表示を要求しています。これは、アプリケーションがシステムバーの下に描画され、Safe AreaがhandleWindowInsetsまたはWindowInsetControllerを介して適用されることを意味します。Android Developer Blog(2025)によると、68%のアプリケーションが既にedge-to-edgeに移行しており、大画面デバイスでの視覚的認識が向上しています。

Safe Area、Padding、Insetsの違い

Safe Area、Padding、Insetsは関連していますが異なる概念です。Safe Areaはシステム要素がないことが保証された画面領域です。Paddingは要素の境界からの内部マージンです。InsetsはSafe Area APIが返す特定の数値オフセット値です。Apple Tech Notes(2025)によると、Safe AreaとPaddingの混同は、アプリストアでの適応性の問題の40%の原因となっています。

概念定義プラットフォーム可変性
Safe Areaシステム要素のない領域iOS、Android動的
Paddingビュー内の内部マージンすべてのプラットフォーム静的
Layout Marginsレイアウト端からのマージンiOS(UIKit)静的/動的
WindowInsetsAndroidのシステムマージンAndroid動的

コードを使ったSafe Areaの実装例

典型的なシナリオを見てみましょう:ノッチ付き横向きのUIKitでのSafe Area、カスタムパネル付きSwiftUIでのSafe Area、Android ComposeでのSafe Area。iOS UIKitの例 — Dynamic Island搭載iPhoneのSafe Area内にコレクションを配置。Jetpack Composeの例 — Material 3でWindowInsetsを使用。

Kotlin
// Jetpack Compose: Safe Areaのマージン
@OptIn(ExperimentalMaterial3Api::class)
fun SafeAreaScreen() {
    val systemBars = with(
        LocalDensity.current
    ) {
        val insets = WindowInsets
            .systemBars
            .getAsPaddingValues()
        PaddingValues(
            top = insets.calculateTopPadding(),
            bottom = insets.calculateBottomPadding()
        )
    }
    Scaffold(
        contentWindowInsets = WindowInsets(
            top = systemBars.computeTopPadding(),
            bottom = systemBars.computeBottomPadding()
        )
    ) { innerPadding ->
        Column(
            modifier = Modifier
                .padding(innerPadding)
        ) {
            Text("Safe Area内のコンテンツ")
        }
    }
}

Jetpack Composeでは、ScaffoldがcontentWindowInsetsパラメータを介して自動的にWindowInsetsを考慮します。InnerPaddingはcontentに渡され、内部要素に適用されます。padding(innerPadding)修飾子を持つColumnは、テキストがシステムバーの下に入らないことを保証します。

Safe Areaのよくある間違い

Apple(2025)のApp Store Review分析によると、最も一般的な5つの間違いは:横向きでのSafe Areaの無視、SafeAreaLayoutGuideの代わりにハードコードされたマージンの使用、UIScrollViewでのSafe Areaの誤った処理、モーダル表示でのマージンの忘れ、Dynamic Islandへの適応不足です。ハードコードされたマージン(上部に20px固定)が最も一般的な間違いです:iPhone 14 Proでは、その20pxが59pxになり、コンテンツが切り取られます。

  • 横向きの無視 — 横向きでは、Safe Areaのマージンが異なります:Home Indicatorが右側に移動し、上部マージンが減少します。
  • ハードコードされたマージン — 20pxや44pxの値は、ノッチのない古いiPhoneでのみ機能します。現代のデバイスでは、マージンが2〜3倍異なります。
  • ScrollViewとSafe Area — UIScrollViewのcontentInsetAdjustmentBehaviorを.alwaysに設定しないと、コンテンツがシステムバーの下に隠れます。

よくある質問

SwiftUIでSafe Areaのマージンを取得するには?

SwiftUIでは、Safe Areaはほとんどのコンテナに自動的に適用されます。マージンを読み取るには、EnvironmentValuesを使用します:@Environment(\.safeAreaInsets) var safeAreaInsets。カスタムパネルの場合は、.safeAreaInset(edge:content:)を使用します。システム要素の下に拡張する必要がある背景には、.ignoresSafeArea()を適用します。

Androidのedge-to-edgeとは?

Edge-to-edgeは、アプリケーションがシステムバー(Status Bar、Navigation Bar)の下に描画され、Safe AreaがWindowInsetsを介して適用される表示モードです。Android 15以降、GoogleはtargetSdk 35のすべてのアプリケーションにedge-to-edgeを要求しています。Jetpack ComposeではWindowInsetsCompatまたはhandleWindowInsetsを介して実装されます。

WebViewでSafe Areaを処理する必要がありますか?

はい、WebViewもSafe Areaを考慮する必要があります。iOSでは、webView.scrollView.contentInsetAdjustmentBehavior = .alwaysを使用します。Androidでは、XMLにandroid:fitsSystemWindows="true"を追加するか、ViewCompat.setOnApplyWindowInsetsListenerを介してプログラムでpaddingを設定します。CSS環境(env(safe-area-inset-top))はSafariで機能しますが、AndroidシステムのWebViewでは機能しません。

まとめ

  • Safe Area — ノッチ、Dynamic Island、StatusBar、Home Indicatorのない画面領域。
  • iOS:UIKitのSafeAreaLayoutGuideとSwiftUIの.safeAreaInsetで実装。
  • Android:WindowInsets(API 30+)またはWindowInsetsCompat(AndroidX)で実装。
  • iPhone 14 Pro以降のDynamic IslandはSafe Areaの上部マージンを59pxに増加。
  • Safe Areaを無視することはApp StoreとGoogle Playでアプリが却下される主な原因の1つ。
  • ハードコードされたマージンは許容されません — 常にSafe AreaのプログラムAPIを使用してください。

ターンキー方式のモバイルアプリケーションを開発します

IT Sectrは2017年からスタートアップや企業向けにiOS・Androidアプリケーションを開発しています。私たちがご相談に乗り、最適なソリューションをご提案します。

プロジェクトについて相談

こちらもお読みください