Iframe terlihat mudah dipakai, sehingga batasnya sering baru terasa saat halaman berperilaku aneh: widget kosong, skrip gagal membaca dokumen sematan, atau halaman melambat. Semua gejala itu berpijak pada aturan yang sama — dokumen sematan tetap dokumen terpisah dengan aturan keamanannya sendiri. Chapter ini merangkum batasan utamanya — same-origin policy, penolakan dari pemilik situs lain, dan biaya kinerja — beserta mitigasinya.

Same-Origin Policy: Dokumen Tetap Terpisah #

Same-origin policy adalah aturan keamanan inti browser: sebuah dokumen hanya boleh membaca dan mengubah DOM dokumen lain bila keduanya ber-asal sama, dengan origin sebagai kombinasi protokol, domain, dan port. Dokumen di dalam iframe membawa origin sendiri, dihitung dari URL src-nya. Bila origin itu berbeda dari origin halaman induk, skrip halaman induk tidak dapat menjangkau DOM dokumen sematan, dan sebaliknya. Isolasi ini dirancang sengaja: tanpa aturan itu, halaman sembarang dapat membaca isi situs lain di tab sampingnya.

Sandbox pada chapter sebelumnya bekerja di garis yang sama: tanpa allow-same-origin, dokumen sematan memakai origin unik sehingga terisolasi total, bahkan dari server yang sama sekalipun. Komunikasi tetap mungkin lewat API khusus seperti postMessage yang menyerahkan pertukaran data kepada kode kedua pihak. Untuk keperluan course ini, poin pentingnya satu: menyematkan bukan berarti berbagi.

Situs Lain Dapat Menolak Di-embed #

Batas berikutnya datang dari pemilik situs yang disematkan. Server dapat menyertakan header yang memerintahkan browser menolak dokumennya di dalam frame: X-Frame-Options dengan nilai DENY (tolak semua origin) atau SAMEORIGIN (hanya origin yang sama), serta directive frame-ancestors pada CSP (Content Security Policy) yang aturannya lebih rinci. Bila perintah itu berlaku, browser menolak menampilkan dokumen tersebut; yang tersisa pesan penolakan atau area kosong. Inilah penjelasan bila sebuah sematan tampak kosong padahal URL-nya benar — situs sengaja menolak di-embed, umumnya untuk mencegah serangan clickjacking.

text
Contoh header respons dari server www.example.com:
X-Frame-Options: DENY

Versi CSP: hanya origin yang sama yang boleh menyematkan
Content-Security-Policy: frame-ancestors 'self'

frame-ancestors menggantikan X-Frame-Options pada browser modern dan menerima daftar origin, misalnya frame-ancestors 'self' www.example.com. Sebagai penulis HTML, tidak ada atribut yang meniadakan header ini; satu-satunya jalan adalah memakai URL embed resmi yang disediakan situs tersebut. Platform yang membolehkan penyematan biasanya menyiapkan halaman khusus untuk itu, seperti URL pemutar video dan URL peta pada chapter-chapter sebelumnya.

Biaya Kinerja dan Cara Menekannya #

Setiap sematan menambah pemuatan: permintaan HTTP baru, dokumen yang diurai ulang, dan skrip yang berjalan di thread-nya sendiri. Event load halaman induk menunggu seluruh iframe tanpa lazy selesai, sehingga indikator pemuatan ikut memanjang. Mitigasinya telah kita pegang sepanjang section ini: sematan dibuat sedikit, ukuran dibuat tetap agar layout stabil, loading="lazy" untuk yang jauh dari layar, dan sandbox agar risikonya terkendali. Tabel berikut merangkum seluruh batas beserta jawabannya:

BatasDampakMitigasi
Same-origin policyskrip tidak menjangkau DOM lintas originrancang halaman agar tidak bergantung pada pembacaan dokumen sematan; komunikasi lewat API seperti postMessage
Header anti-embed (X-Frame-Options, frame-ancestors)dokumen menolak tampil; area kosongpakai URL embed resmi dari penyedia konten; sediakan tautan cadangan
Biaya pemuatan dokumen penuhhalaman lambat; event load tertundabatasi jumlah iframe, gunakan loading="lazy", tetapkan ukuran
Risiko kode pihak ketigaskrip sematan berjalan di browser pengunjungsandbox dengan token minimum

Contoh Lengkap dalam Satu File #

File penutup section ini menyatukan mitigasi tadi pada satu halaman artikel: widget cuaca dengan lazy, sandbox minimal, dan tautan cadangan:

<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Berita dan Cuaca</title>
</head>
<body>
  <h1>Suara Warung — Edisi Pekan Ini</h1>
  <article>
    <h2>Kunjungan Budi ke kebun bibit</h2>
    <p>Budi membagikan catatan kunjungannya ke kebun bibit di luar kota.</p>
  </article>
  <iframe src="www.example.com/widget/cuaca?kota=bandung" title="Prakiraan cuaca Bandung" width="360" height="200" loading="lazy" sandbox="allow-scripts"></iframe>
  <p>Widget gagal tampil? <a href="www.example.com/cuaca/bandung">Buka halaman cuaca secara langsung</a>.</p>
</body>
</html>

Output yang Dihasilkan:

text
Jendela browser menampilkan:
  - Judul "Suara Warung — Edisi Pekan Ini"
  - Artikel kunjungan Budi tampil lebih dulu
  - Widget cuaca 360x200 di akhir halaman, dimuat saat pengunjung mendekat
  - Tautan cadangan "Buka halaman cuaca secara langsung" di bawah widget

Mari kita bedah baris-baris pentingnya:

  1. Baris 10-13 (article): konten milik kita sendiri ditulis lebih dulu, sehingga artikel utama tidak menunggu widget.
  2. Baris 14 (loading="lazy"): widget berada di akhir halaman, sehingga pemuatannya ditunda sampai pengunjung mendekat.
  3. Baris 14 (sandbox="allow-scripts"): widget boleh menjalankan skripnya, tetapi tanpa origin asli, popup, formulir, dan navigasi halaman induk.
  4. Baris 15 (tautan cadangan): bila pemilik widget menolak di-embed atau widget gagal, pengunjung tetap menjangkau datanya.

Dengan chapter ini section Embedded Content menutup tirainya: kita dapat menyematkan, menamai, membatasi, dan memahami batas yang tidak dapat ditawar. Section berikutnya, SVG dan Graphics, membawa kita ke arah yang berbeda — menggambar grafik vektor langsung dari markup HTML sendiri, bukan dari dokumen lain.

Referensi resmi untuk pendalaman:

Berkas Sumber

Berkas pendukung halaman ini dapat diunduh dan dijalankan langsung sesuai penjelasan di atas.

contoh-batasan.html

Unduh berkas
html
<!doctype html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>Berita dan Cuaca</title>
</head>
<body>
  <h1>Suara Warung — Edisi Pekan Ini</h1>
  <article>
    <h2>Kunjungan Budi ke kebun bibit</h2>
    <p>Budi membagikan catatan kunjungannya ke kebun bibit di luar kota.</p>
  </article>
  <iframe src="www.example.com/widget/cuaca?kota=bandung" title="Prakiraan cuaca Bandung" width="360" height="200" loading="lazy" sandbox="allow-scripts"></iframe>
  <p>Widget gagal tampil? <a href="www.example.com/cuaca/bandung">Buka halaman cuaca secara langsung</a>.</p>
</body>
</html>