昔、Internet Explorerが制作時のサポート対象ブラウザとして求められた時代・・・。HTML/CSS/JavaScriptが他のブラウザと同じように表示されない、動作しない、といったことが頻繁にありました。Internet Explorerは通称IEと呼ばれ、IE11が2013年に登場し、2022年6月にサポートが終了するまで長く使われました。
2013年のIEのシェアは60%ほどあり(参照: IE11が急成長 - 11月ブラウザシェア | TECH+(テックプラス))、ウェブ業界で「Chromeでこんな新機能が搭載されました!」と発表されても、IE11で使えず諦めたウェブ制作者は多かったのではないでしょうか?
この記事では、IE11対応が必須だったころの懐かしい“あるある”を振り返ります。
HTML・CSSは「なぜか」崩れる
登場当時はWebGLなど先端的な機能を搭載していましたが、IE11はその後に機能追加がありませんでした。2010年代後半頃には、Chrome・Safari・Firefoxに比べて互換性の低さがウェブ制作者を悩ませます。
IE11の後継のMicrosoft Edge(旧称スパルタン)が2015年に登場しても、IE11の存在感は強く業務用途(社内システム等)などで残り続けました。
そんなIE11で利用できなかったHTMLやCSSの機能を紹介します。
main要素がブロック要素にならなかった
HTMLで定番のmainタグ。IE11前提だと落とし穴がありました。一般的なブラウザではmainは標準でブロック要素として扱われますが、IE9〜IE11ではmainがインライン要素扱いになりました。widthやmargin: 0 auto;が効きません。
対策はシンプルで、CSSにmain { display: block; }を指定します。多くのリセットCSSにこの記述が含まれていましたが、知らなければいきなりIEで崩れます。
<main class="content">
<h1>見出し</h1>
<p>本文が入ります。</p>
</main>
/* IE9〜IE11向け */
main {
display: block;
}
.content {
max-width: 960px;
margin: 0 auto;
padding: 16px;
}
標準のCSS Gridが使えなかった
いまでは当たり前のように利用されているCSS Grid。当時はFlexboxで組むことがほとんどでした。当時のFlexboxにはgapはなかったため、marginを使って要素間の余白を作っていました。
<ul class="cards">
<li class="cards__item">A</li>
<li class="cards__item">B</li>
<li class="cards__item">C</li>
</ul>
.cards {
display: flex;
flex-wrap: wrap;
list-style: none;
padding: 0;
}
.cards__item {
width: calc(33.333% - 16px);
margin: 8px;
}

またIE11登場当時はIE9とIE10も大きなシェアをもっていたため、IE11対応が下限バージョンでなかったことも忘れてはいけません。floatが伝統的に使われていたり、IE10ではFlexboxにベンダープレフィックスが必要でした。
▼ベンダープレフィックス
.nav {
display: -ms-flexbox;
display: flex;
}
.nav__item {
-ms-flex: 1 0 auto;
flex: 1 0 auto;
}
IE11にもGrid相当の機能はありましたが、現在の仕様とは異なる独自実装でした。標準的なCSS Gridと、独自実装のIE11のCSS Grid。どちらも対応するのは大変でした。ビルドツール(Gulpやwebpack等)と組み合わせたAutoprefixerという技術で-ms-gridへ変換する方法もありましたが、使える人だけが使う、という位置づけでした。
▼IE11向けのCSS Grid
/* 出力イメージ(-ms-grid が追加される例) */
.grid {
display: -ms-grid;
display: grid;
-ms-grid-columns: 1fr 10px 1fr 10px 1fr; /* gapが使えないので、代わりに余白分のカラムを用意・・・ */
grid-template-columns: 1fr 1fr 1fr;
gap: 10px;
}
object-fitが使えなかった
いまなら、画像を枠に合わせてトリミングするのは簡単です。
img {
width: 100%;
height: 100%;
object-fit: cover;
}
しかしIE11はobject-fit非対応でした。対策として画像をimgタグで扱うのを諦めて、背景画像にしていました。background-sizeだとcontainとcoverが利用できたためです。

<div class="thumb" style="background-image:url(photo.jpg)"></div>
.thumb {
width: 240px;
height: 160px;
background: center / cover no-repeat;
}
ただし落とし穴もあり、SVG画像を使うとcontainとcoverは効きません。
aspect-ratioが使えなかった
縦横比を確保するCSSのaspect-ratioがありませんでした。そのため当時はpadding-topを使って比率用の領域を確保する手法が用いられていました。
.ratio-16x9 {
position: relative;
width: 100%;
padding-top: 56.25%;
}
.ratio-16x9 > .inner {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}

padding-top: 56.25%;の箇所は16:9の比率を示す指定ですが、一見何を記載しているかわからないですよね。
position: stickyが使えなかった
固定ヘッダーや目次の追従表示は、いまならposition: stickyが便利です。しかしIE11はposition: sticky非対応でした。
当時は、JavaScriptを駆使してスクロール量を監視し、position: fixed相当のクラスを付け替える実装が定番でした。
var nav = document.querySelector('.nav');
var top = nav.offsetTop;
window.addEventListener('scroll', function () {
if (window.pageYOffset > top) {
nav.classList.add('is-fixed');
} else {
nav.classList.remove('is-fixed');
}
});
loading=lazyが使えなかった
画像の遅延読み込みは、いまならimgタグのloading="lazy"の一発です。しかしIE11はloading属性に非対応です。
そのため当時の現場では、遅延読み込みライブラリの導入が現実的でした。jQueryのLazy Load系プラグインでは、data-originalに本来の画像URLを入れて、表示タイミングで差し替える方法がよく使われていました。
<img class="lazy" src="placeholder.gif" data-original="photo.jpg" alt="">
$('img.lazy').lazyload();
複数行の三点リーダー省略が使えなかった
文言を省略したいときに三点リーダーを使うことがあります。
複数行の省略は、モダンブラウザなら次のような指定で実現できます。
p {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
IE11では従来の単一行の省略しかできませんでした。もし複数行で対策しようとすると、画像をかぶせて下方にフェードアウトさせるとか、別の手段を検討する必要がありました。
mix-blend-modeが使えなかった
mix-blend-modeを使うと重なり合う要素を、「乗算」とかで合成できます。グラフィカルな表現ができる便利なCSSの機能です。
.hero__overlay {
position: absolute;
mix-blend-mode: multiply;
}
2010年代の当時はFigmaがはやる前の時代です。デザインツールはAdobe PhotoshopやIllustrator、Sketchの利用が多かったように思います。デザインツールでレイヤー合成のオーバーレイや乗算などが使われていると、HTMLで再現に困ることが多かったです。
当時のIE11はmix-blend-modeは未対応でした。
そのため、レイヤー合成の場合は、合成した結果を画像化して切り出したり、デザインファイルでレイヤー合成を諦めてもらうしかありませんでした。
参照
WebPが使えなかった
WebPなどの次世代画像形式も、IE11では使えません。ウェブ制作の現場では根強くJPEG/PNGが使われていました。
IE11はpictureタグやsrcset属性にも未対応でした。ただしpicture要素の中にJPEG/PNGのimgタグを置けば、IE11ではそのimgタグが表示されます。picture・sourceタグが無視される代わりに、imgタグだけが残る、という挙動になります。新しいブラウザにはWebPを配信し、未対応ブラウザにはJPEG/PNGを配信できるという意外な方法です。
<!-- モダン向け:WebP → JPEG/PNG の順にフォールバック -->
<picture>
<source type="image/webp" srcset="photo.webp">
<img src="photo.jpg" alt="サンプル画像">
</picture>
今は、WebPをはじめ、次世代のAVIF画像形式もすべてのブラウザで対応しています。
CSS変数が使えなかった
IE11はCSSカスタムプロパティ(CSS変数)非対応です。当時の現場ではSass(SCSS)変数やStylusの変数を使う方法が一般的でした。
/* 当時の現場(Sass変数) */
$spacing: 16px;
.card {
padding: $spacing;
}
余談ですが当時のSassは世代があり、Ruby Sass、LibSass(node-sass)なんてものもありました。今のSassはDart Sassです(もうSassは使われていない?)。
dialog/details/summaryタグが使えなかった
標準のUI要素としてdialogタグやdetails/summaryタグがありますが、IE11は非対応です。当時はモーダルもアコーディオンもdivタグとJavaScriptで自作されることが多かったです。

<!-- divでモーダルを自作する例 -->
<button type="button" data-open>開く</button>
<div class="modal" >
<div class="modal__backdrop"></div>
<div class="modal__content">
<button type="button" >閉じる</button>
<p>モーダルの中身</p>
</div>
</div>
この作り方のデメリットとして、フォーカス管理やキーボード操作、aria-属性などを含めると難易度が上がります(そもそも放置されていることが多かったかも・・・)。
JavaScript編
let・constが使えなかった
IE11はlet/constは限定的にサポートされていましたが制約があったため、変数・定数はvarで記述します。
// constの代わりに「変更しないつもり」でvarを書く
var API_ENDPOINT = '/api/data.json';
// letの代わりにvarを書く
var count = 0;
count += 1;
アロー関数が使えなかった
IE11はアロー関数も非対応です。アロー関数は短く書けるだけでなく、thisの扱いで助かる場面が多い記法です。当時は、次のようにthisを別変数に退避する対策が行われていました。
function someFunction(button) {
var self = this;
button.addEventListener('click', function () {
self.open();
});
}
Promise/async-awaitが使えなかった
Promiseやasync/awaitは当然IE11では搭載されていません。
幸いにもBabelで新しいECMAScript準拠のJavaScriptやTypeScriptを、ES5向けにトランスパイルし、必要なポリフィルを追加すれば、IE11でも動作させることができました。ただ、webpackなどでIE11対応のために環境構築に苦労した方は多いでしょう。
classList.toggle()の第2引数が使えなかった
classList.toggle()は第2引数の真偽値で付与/削除ができます。
// elはHTMLElementの参照
el.classList.toggle('is-open', isOpen);
しかしIE11はtoggle()の第2引数に非対応です。結果的にadd()とremove()で実装されることが多くありました。
if (isOpen) {
el.classList.add('is-open');
} else {
el.classList.remove('is-open');
}
fetch()が使えなかった
いまのJavaScriptではfetch()関数を使って非同期通信でクライアントとサーバー間のデータの通信を行うことが多いでしょう。しかし、IE11はfetch()関数に未対応でした。
そのため、XMLHttpRequestで実装する必要がありました。
var xhr = new XMLHttpRequest();
xhr.open('GET', '/api/data.json');
xhr.onload = function () {
// 受け取り処理
};
xhr.send();
多くの方は、ポリフィル/ライブラリを導入して通信処理を作っていたと思います。jQuery.ajax()かaxiosなどのライブラリが有名でした。
▼jQueryのコード
// jQuery.ajax() の例
$.ajax({
url: '/api/data.json',
method: 'GET',
dataType: 'json'
}).done(function (data) {
// 受け取り処理
});
とりあえず入っていたmeta:X-UA-Compatible
HTMLのheadでよく見かけた次の指定です。
<meta http-equiv="X-UA-Compatible" content="IE=edge">
X-UA-Compatibleは、IEに「どのドキュメントモードで表示するか」を指示する仕組みです。IE11時代、X-UA-Compatibleは意図せず「互換表示」で描画されるのを防ぐために役立ちました。
IEは既定で古いドキュメントモード(例:IE7相当)に切り替わることがあり、これによりCSSレイアウト崩れやJavaScriptの挙動不一致が発生しました。このmetaタグを指定することで、常にそのIEで利用可能な最新エンジン(IE11標準モード)で描画させることができました。
今はIE11がないため、意味のない指定となります。
今も利用できるIEモード
そんな懐かしいIE11ですが、Windows 11でもMicrosoft Edgeブラウザを利用すれば、限定的にIEモードを利用できます。IEモードは少なくとも2029年までサポートされます。


IE11でも動くサンプルコード
本記事のサンプルを掲載していますので、ぜひIEモードを使ってご覧ください。当時の苦労を思い出すことができると思います。
まとめ
ここまで挙げた例は、どれも「いまなら短いコードで書ける」ものばかりです。
しかし、多くのウェブ制作者を苦しめていたのは、モダンなHTML・CSS・JavaScriptを使えない不満だけではなく、「なぜかIEだと崩れる」という事象が多かったことです。IEで表示が崩れるたびに検索エンジンで解決方法を調べたり、作り方を変更したりと骨が折れた制作者が多くいたことでしょう。
IEで表示できない苦労はフロントエンドエンジニアでないと理解されづらく、人知れず数倍の作業時間を要していた制作者がいたはずです。
今はIEの後継のEdge(Chromium版)をはじめ、Chrome・Safari・FirefoxがInterop等(参照『Announcing Interop 2026 | WebKit』)の取り組みによって足並みを揃えて進化しています。ブラウザの開発の歩みに感謝しつつ、ウェブの発展に想いを馳せてみましょう。

