WithCodeMedia-1-pc
previous arrowprevious arrow
next arrownext arrow

WithCodeMedia-1-sp
previous arrowprevious arrow
next arrownext arrow

SafariとChromeで表示が崩れる原因と直し方|差異対策

生徒

Chromeでは完璧なのにSafariで崩れるんです…ブラウザごとの差ってどう対策しますか?

ペン博士

リセットCSSで初期値を揃えるのが基本だよ。あとはSafari特有のクセ(100vhやsticky)を知っておくと崩れが激減する。今日は定番の対策をまとめるね。

「Chromeでは完璧に見えるのに、Safariで開くとレイアウトが崩れる」「iPhoneで確認したら文字サイズがおかしい」――Webサイト制作でこうした悩みにぶつかったことはないでしょうか。ブラウザ間の表示差異はフロントエンド開発における頻出問題のひとつで、初心者から経験者まで多くのエンジニアを悩ませています。

表示崩れが起きる根本的な原因は、ブラウザごとにHTMLやCSSの解釈エンジンが異なることにあります。SafariはWebKit、ChromeはBlink、FirefoxはGeckoといった独自のレンダリングエンジンを搭載しており、同じCSSコードを与えても微妙に異なる描画結果を返すことがあります。

この記事では、ブラウザ差異が生まれるメカニズムから始まり、Safari特有の問題点、iOS環境での注意事項、そして実践的な解決策まで体系的に解説します。コード例を豊富に用意したので、コピペしてすぐに使えます。

  • ブラウザごとにレンダリングエンジンが異なる理由と影響範囲
  • リセットCSS・ノーマライズCSSで差異を吸収する方法
  • SafariだけでレイアウトがくずれるCSSプロパティの対処法
  • iOSの慣性スクロール・フォント自動拡大・100vh問題の解決策
  • @supportsを使ったブラウザ別スタイル分岐の書き方
  • Autoprefixerでベンダープレフィックスを自動付与する手順

目次

ブラウザ差異が生まれる根本的な理由

差異の発生源

表示崩れを根本から解決するには、なぜブラウザ間で差異が生まれるのかを理解しておく必要があります。主な原因は3つあります。

レンダリングエンジンの違い

ブラウザはHTMLとCSSを解析して画面に描画するための「レンダリングエンジン」(レイアウトエンジンとも呼ばれます)を内蔵しています。主要ブラウザのエンジンは以下の通りです。

  • Chrome・Edge・Opera:Blink(Chromiumベース)
  • Safari(macOS・iOS):WebKit
  • Firefox:Gecko

BlinkはもともとWebKitからフォークして独自に進化したため、基本的な部分は似ていますが、新しいCSS機能への対応速度や細かい描画ルールに差があります。特にSafariはAppleが独自路線で開発を続けているため、他のブラウザとの差異が生じやすい傾向にあります。

ベンダープレフィックスと仕様実装の差異

CSS新機能は、W3Cで仕様が確定する前に各ブラウザが先行実装することがあります。その際に「ベンダープレフィックス」(接頭辞)を付けて実験的に提供されます。

  • -webkit-:Safari・旧Chrome(WebKitエンジン)
  • -moz-:Firefox(Geckoエンジン)
  • -ms-:Internet Explorer・旧Edge

現在はほとんどのプロパティが標準化されていますが、特定のプロパティ(-webkit-appearance-webkit-text-strokeなど)は依然としてベンダープレフィックス付きでないとSafariで動作しないケースがあります。

ブラウザのデフォルトスタイル(User Agent Stylesheet)

各ブラウザはHTMLタグに対して独自のデフォルトスタイル(User Agent Stylesheet)を持っています。たとえば<button>要素のデフォルトの見た目、<ul>のmargin/paddingの値、<input>のフォントなどが微妙に異なります。このデフォルト差異がリセットCSSを書かない限り表示崩れの温床になります。


リセットCSS・ノーマライズCSSで差異を吸収する

リセット と Normalize

ブラウザのデフォルトスタイル差異を吸収する最初のステップが「リセットCSS」または「ノーマライズCSS」の導入です。それぞれの特徴と使い方を確認しましょう。

リセットCSSとノーマライズCSSの違い

2つのアプローチには明確な思想の違いがあります。

  • リセットCSS:すべてのデフォルトスタイルを0にリセットする。自分でゼロから組み立てたい場合に向く。
  • ノーマライズCSS(Normalize.css):ブラウザ間の差異だけを均一化し、有用なデフォルトは残す。実用的でよく使われる。

現代のWeb制作では、Normalize.cssをベースにしつつプロジェクト固有のリセットを上乗せするハイブリッド手法が主流です。

モダンCSSリセットの実装例

以下は2024年現在の実践的なCSSリセットです。box-sizingの統一、不要なmargin除去、画像のブロック化など必要最低限の均一化を行います。

/* モダンCSSリセット */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  font-size: 16px;
  -webkit-text-size-adjust: 100%; /* iOS自動フォント拡大を無効化 */
  text-size-adjust: 100%;
}

body {
  line-height: 1.5;
  -webkit-font-smoothing: antialiased; /* macOS/iOS フォントアンチエイリアス */
  font-family: "Hiragino Kaku Gothic ProN", "Hiragino Sans", Meiryo, sans-serif;
}

img,
video,
canvas,
svg {
  display: block;
  max-width: 100%;
}

input,
button,
textarea,
select {
  font: inherit; /* ブラウザデフォルトのフォント継承問題を解消 */
}

p,
h1,
h2,
h3,
h4,
h5,
h6 {
  overflow-wrap: break-word;
}

ul,
ol {
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

Normalize.cssのCDN経由での導入

Normalize.cssをCDNから読み込む場合は、自分のCSSより前に記述します。

<!-- head内に追加 -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/normalize/8.0.1/normalize.min.css">
<link rel="stylesheet" href="style.css">

npmを使っているプロジェクトならインストールして直接インポートすることも可能です。

/* npmでインストール後、CSSファイル内でインポート */
@import 'normalize.css';

/* 以下に自分のスタイルを書く */

Safari特有の表示崩れと対処法

Safariのクセと対処

Chromeでは正常に表示されてもSafariだけ崩れる場合、以下の問題が原因であることが多いです。それぞれの原因と対処法を具体的なコードとともに解説します。

100vh問題(モバイルSafariのアドレスバー)

モバイルSafariではアドレスバーが表示・非表示で切り替わるため、100vhが実際の表示領域より大きくなり、コンテンツが隠れたりスクロールが発生したりします。

/* NG:モバイルSafariでアドレスバーの高さ分がはみ出す */
.hero {
  height: 100vh;
}

/* OK:svhを使う(Safari 16以降対応) */
.hero {
  height: 100svh; /* small viewport height = アドレスバー込みの最小高さ */
}

/* OK:dvhを使う(動的に変化するビューポート高さ) */
.hero {
  height: 100dvh;
}

/* フォールバック付きの書き方(古いSafariにも対応) */
.hero {
  height: 100vh; /* フォールバック */
  height: 100svh;
}

Safari 15以前を対象にする場合は、JavaScriptでwindow.innerHeightを取得してCSS変数にセットする方法も有効です。

// iOS Safariの実際の表示高さをCSS変数にセット
function setVh() {
  const vh = window.innerHeight * 0.01;
  document.documentElement.style.setProperty('--vh', `${vh}px`);
}

setVh();
window.addEventListener('resize', setVh);
/* CSS変数 --vh を使った記述 */
.hero {
  height: calc(var(--vh, 1vh) * 100);
}

position: sticky がSafariで効かない

position: stickyはSafari 13以降から標準対応していますが、親要素にoverflow: hiddenまたはoverflow: autoが設定されていると動作しなくなります。これはChrome/Firefoxでも同様ですが、Safariでより顕著に問題が出やすいです。

/* NG:親要素のoverflowがstickyを無効にする */
.parent {
  overflow: hidden; /* これがあるとstickyが機能しない */
}

.sticky-element {
  position: -webkit-sticky; /* Safari対応のベンダープレフィックス */
  position: sticky;
  top: 0;
}

/* OK:親のoverflowを見直す */
.parent {
  /* overflow: hidden を削除するか、別の方法で実装 */
}

.sticky-element {
  position: -webkit-sticky;
  position: sticky;
  top: 0;
  z-index: 100;
}

Flexbox の gap プロパティ

gapプロパティ(旧grid-gap)はFlexboxでの使用がSafari 14.1以降にしか対応していません。Safari 14.0以前ではgapがFlexboxで無視されます。

/* Safari 14.0以前のフォールバック方法 */
.flex-container {
  display: flex;
  flex-wrap: wrap;
}

/* フォールバック:margin で代替 */
.flex-container > * + * {
  margin-left: 16px;
}

/* @supportsでgap対応ブラウザだけに適用 */
@supports (gap: 16px) {
  .flex-container {
    gap: 16px;
  }
  .flex-container > * + * {
    margin-left: 0; /* フォールバックをリセット */
  }
}

date input が Safari でテキスト欄になる

<input type="date">はChromeでは日付ピッカーが表示されますが、SafariのmacOS版ではiOS 14.5以降まで対応していませんでした。macOS Safari 14.1以降では対応済みですが、古い環境を考慮するなら代替手段を用意しておく必要があります。

<!-- type="date"が未対応の場合のフォールバック -->
<input type="date" id="date-input" class="date-field">

<script>
// input type="date"の対応確認
const input = document.createElement('input');
input.setAttribute('type', 'date');

if (input.type === 'text') {
  // 未対応ブラウザ:placeholderを設定してユーザーに入力形式を伝える
  document.getElementById('date-input').placeholder = 'YYYY-MM-DD';
  // 必要に応じてflatpickr等のライブラリで代替
}
</script>

-webkit-appearance によるフォーム要素のスタイリング

SafariはフォームパーツにOSネイティブのスタイルを適用します。これをリセットしてカスタムスタイルを当てるには-webkit-appearance: noneが必要です。

/* ボタン・入力欄のデフォルトスタイルをリセット */
button,
input[type="submit"],
input[type="button"],
input[type="reset"] {
  -webkit-appearance: none;
  appearance: none;
  border-radius: 0; /* iOSでは角丸がデフォルトで付く */
  cursor: pointer;
}

input[type="text"],
input[type="email"],
input[type="tel"],
textarea,
select {
  -webkit-appearance: none;
  appearance: none;
  border-radius: 0;
}

/* selectの矢印アイコンをカスタマイズ */
select {
  background-image: url("data:image/svg+xml,...");
  background-repeat: no-repeat;
  background-position: right 12px center;
  padding-right: 40px;
}

iOSの慣性スクロール・フォント自動拡大への対処

iOS Safari特有の動作として、慣性スクロールとフォント自動拡大があります。どちらもUXに直結する問題のため、適切に対処しておきましょう。

慣性スクロール(momentum scrolling)の制御

iOSでは、スクロール可能な要素に-webkit-overflow-scrolling: touchを指定することでネイティブアプリのような慣性スクロールが有効になります。ただし、iOS 13以降ではデフォルトで慣性スクロールが有効になっており、このプロパティは非推奨になっています。

/* iOS 12以前の慣性スクロール有効化(現在は非推奨) */
.scroll-container {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch; /* 非推奨 */
}

/* iOS 13以降:overscroll-behaviorで制御 */
.scroll-container {
  overflow-y: scroll;
  overscroll-behavior-y: contain; /* 親要素へのスクロール伝搬を防ぐ */
}

/* モーダルやドロワー内でのスクロール制御 */
.modal-inner {
  overflow-y: auto;
  overscroll-behavior: contain;
}

iOSのフォント自動拡大を止める

iOSはスマートフォンでの可読性向上のため、特定の条件下でフォントサイズを自動的に拡大することがあります(TextAutosizing)。これをCSSで抑制できます。

html {
  /* iOSのフォント自動拡大を無効化 */
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

/* または特定のコンテナだけに適用 */
.no-auto-zoom {
  -webkit-text-size-adjust: none; /* 注意:アクセシビリティへの影響あり */
}

-webkit-text-size-adjust: noneは、ユーザーがブラウザ設定でフォントサイズを変更できなくなるためアクセシビリティ上好ましくありません。原則100%を使いましょう。

iOSでダブルタップによるズームを防ぐ

古いiOS版ではダブルタップでズームが発生することがあります。metaタグのviewport設定とCSSで対応できます。

<!-- viewport metaタグ:user-scalable=noは非推奨(アクセシビリティ問題) -->
<meta name="viewport" content="width=device-width, initial-scale=1">

<!-- iOS 9.3以降はuser-scalable=noを無視するため意味がない -->
/* touch-actionでダブルタップズームを防ぐ(iOS 13以降) */
a,
button {
  touch-action: manipulation; /* ダブルタップのズーム動作を無効化 */
}

@supportsを使ったブラウザ別スタイル分岐

@supports(フィーチャークエリ)を使うと、特定のCSSプロパティに対応しているブラウザだけにスタイルを適用できます。モダンブラウザでは幅広く使えます。

/* 基本構文 */
@supports (プロパティ: 値) {
  /* 対応ブラウザにだけ適用 */
}

/* 非対応ブラウザにだけ適用 */
@supports not (プロパティ: 値) {
  /* 非対応ブラウザにだけ適用 */
}

/* AND条件 */
@supports (display: grid) and (gap: 16px) {
  .container {
    display: grid;
    gap: 16px;
  }
}

/* コンテナクエリ対応チェック */
@supports (container-type: inline-size) {
  .card-wrapper {
    container-type: inline-size;
  }

  @container (min-width: 400px) {
    .card {
      display: flex;
    }
  }
}

/* ネイティブのネストCSS対応チェック */
@supports selector(& > *) {
  .parent {
    & > .child {
      color: red;
    }
  }
}

@supportsを使うことでプログレッシブエンハンスメント(基本機能を全ブラウザに、拡張機能を対応ブラウザだけに提供する手法)を実現できます。


Autoprefixerでベンダープレフィックスを自動付与する

ベンダープレフィックスを手書きするのは非効率で漏れも生じやすいです。PostCSSプラグインのAutoprefixerを使えば、対象ブラウザに必要なプレフィックスを自動で付与できます。

PostCSS + Autoprefixerのセットアップ

/* インストール(npmプロジェクト前提) */
/* npm install --save-dev postcss autoprefixer postcss-cli */

/* postcss.config.js */
module.exports = {
  plugins: [
    require('autoprefixer')
  ]
}
<!-- package.jsonのscriptsに追加 -->
<!-- "build:css": "postcss src/style.css -o dist/style.css" -->

<!-- .browserslistrcファイルで対象ブラウザを指定 -->
<!-- > 0.5%, last 2 versions, Safari >= 14, iOS >= 14, not dead -->

Browserslistで対象ブラウザを明示することで、本当に必要なプレフィックスだけが付与されます。過去の遺物的なプレフィックスで肥大化することを防げます。

Autoprefixer変換の例

/* 入力(ソースCSS) */
.flex-container {
  display: flex;
  user-select: none;
  backdrop-filter: blur(10px);
}

/* Autoprefixer変換後の出力 */
.flex-container {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-user-select: none;
     -moz-user-select: none;
      -ms-user-select: none;
          user-select: none;
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
}

ブラウザ差異の検証方法

検証の手順

コードを書いたら実際にブラウザで確認することが不可欠です。効率的な検証方法を紹介します。

実機確認とiOSシミュレータ

最も信頼できる確認方法は実機でのテストです。Macを持っているならiOSシミュレータ(Xcode付属)を使うことができます。WindowsでSafariを確認したい場合はBrowserStackLambdaTestのようなクラウドテストサービスが有効です。

Chrome DevToolsのレスポンシブモード

Chrome DevToolsの「デバイスツールバー(Ctrl+Shift+M / Cmd+Shift+M)」を使えば様々な端末サイズをシミュレートできます。ただしChromeのシミュレーションはSafariのレンダリングとは異なります。Safari特有のCSSバグの再現には実機かBrowserStackが必要です。

Safariの開発者ツールを使う

<!-- Safari開発者ツールの有効化手順 -->
<!-- 1. Safari > 環境設定 > 詳細タブ -->
<!-- 2. 「メニューバーに開発メニューを表示」にチェック -->
<!-- 3. iPhoneをMacにUSB接続 -->
<!-- 4. Safari > 開発 > [デバイス名] > ページを選択 -->
<!-- 5. MacのSafari開発者ツールでiOSの実機デバッグが可能 -->

MacのSafariからiOSデバイスに接続してリモートデバッグを行うことで、iOS Safariの実際の動作を確認しながらCSSを修正できます。これが最も正確な確認方法です。

ブラウザ差異チェックリスト

  • フォントの表示・ウェイト(特にWebフォント)
  • Flexbox / Gridのレイアウト崩れ
  • positionプロパティ(sticky / fixed)の動作
  • フォーム要素(input / select / button)のデザイン
  • スクロール動作(慣性・バウンス)
  • アニメーション・トランジションのフレームレート
  • 画像・動画の表示(WebP・AVIF対応状況)
  • CSSカスタムプロパティ(CSS変数)の動作

ブラウザ差異対策のベストプラクティスまとめ

ここまで解説した内容を表にまとめます。案件の冒頭でこのチェックリストを参照することで、後から発覚する表示崩れを大幅に減らせます。

問題 原因 対処法
全体的なデフォルト差異 User Agent Stylesheet リセットCSS / Normalize.css
100vh問題 モバイルSafariのアドレスバー 100svh / 100dvh / JS変数
sticky動作不良 親要素のoverflow 親のoverflowを除去
flex gapが効かない Safari 14.0以前の非対応 @supports + marginフォールバック
フォーム要素のデザイン SafariのOS依存スタイル -webkit-appearance: none
フォント自動拡大 iOSのTextAutosizing -webkit-text-size-adjust: 100%
ベンダープレフィックス漏れ 手書きの管理ミス PostCSS + Autoprefixer
date入力の非表示 macOS Safari 14.0以前の非対応 JavaScriptライブラリで代替

まとめ

ブラウザ表示差は、まずリセットやNormalizeCSSで初期値を揃えるのが基本です。ポイントは①Safari特有のクセ(100vh・sticky・date input)を把握②@supportsで機能ごとに分岐③Autoprefixerでベンダープレフィックスを自動付与、の3点。実機とデベロッパーツールで確認しながら、崩れを一つずつ潰していきましょう。

よくある質問(FAQ)

ChromeでOKなのにSafariでだけ崩れる場合、まず何を確認すべきですか?

まずSafariの開発者ツール(または実機+Mac接続によるリモートデバッグ)でエラーメッセージを確認しましょう。次に、position: stickyの親要素にoverflowが設定されていないか、gapプロパティの対応状況、-webkit-プレフィックスの有無を順番にチェックすると原因を特定しやすいです。

iPhoneで全画面表示のセクションが少しはみ出してしまいます。

height: 100vhが原因です。iOSのSafariではアドレスバー分が100vhに含まれないため、コンテンツがはみ出します。height: 100svh(Safari 16以降)に変更するか、JavaScriptでwindow.innerHeightを取得してCSS変数にセットする方法で解決できます。

リセットCSSはすべてのプロジェクトで必要ですか?

実質的には必要です。ただし、WordPressテーマやBootstrap・Tailwind CSSなどのフレームワークを使っている場合は独自のリセットが内包されています。重複してリセットをかけると意図せず上書きが起きることがあるため、フレームワークのリセット内容を確認してから追加するかどうかを判断しましょう。

Autoprefixerはどの環境で使えますか?ビルドツールがない場合は?

Autoprefixerはnpm(Node.js)環境が必要です。ViteやWebpackに組み込んで使うのが一般的です。ビルドツールを使っていない小規模プロジェクトでは、オンラインのAutoprefixer CSS OnlineにCSSを貼り付ければ変換後のコードを得られます。

Windowsにはないと言われますが、SafariのテストはMacがないとできませんか?

MacなしでSafariをテストするにはBrowserStackLambdaTestなどのクラウドテストサービスを利用するのが現実的です。月額有料ですが、実機と同等の環境でSafariを操作できます。また、SauceLabs(一部無料枠あり)も選択肢になります。Apple公式の手段としてmacOSの仮想マシンをリーガルに使う方法もありますが、セットアップコストが高いため業務でSafari確認が必要ならBrowserStackの導入をおすすめします。


あわせて読みたい関連記事

CSS・Webデザイン実装の総まとめ

CSSの実装テクニックを「レイアウト・装飾・アニメーション・基礎・トラブル解決」の目的別に探せる総まとめページを用意しています。実装で迷ったときの索引としてどうぞ。

AIスキルで、未来の自分をアップデート!

今なら完全無料でAIを学べる!WithAI

今なら完全無料でAIを学べる!

  • 動画や実践で楽しく学べる:初心者でも安心のカリキュラム
  • スマホ・PCどちらでもOK:好きな時間に学習できる
  • 料金は一切ナシ0円でAIスキルが身につく

目的に合わせて選べる「AI副業」「AI転職」「AI活用」の3コースを用意。副収入・キャリアチェンジ・日常の生産性アップまで、あなたのゴールに合わせてAIを学べます。

会員登録はカンタン30秒で完了します。まずは公式LINEから、無料でAI学習をスタートしましょう!

この記事を書いた人

WithCodeでWeb制作を習得後、フリーランスエンジニアとして活動。HTML/CSS・JavaScript・WordPress案件を中心に年間20件以上の制作実績を持つ。「難しい技術をわかりやすく」をモットーに、初心者〜中級者向けの技術記事を執筆。副業・フリーランス独立を目指す方に向けた情報発信に注力している。

– service –WithGroupの運営サービス

  • WithCode
    - ウィズコード -

    スクール

    「未経験」から
    現場で通用する
    スキルを身に付けよう!

    詳細はこちら
  • WithFree
    - ウィズフリ -

    実案件サポート

    制作会社のサポート下で
    実務経験を積んでいこう!

    詳細はこちら

公式サイト より
今すぐ
無料カウンセリング
予約!

目次