iframe

Penyematan konten eksternal, sandboxing, dan pertimbangan sebelum menyematkan.

Daftar isi

Elemen iframe menyisipkan dokumen HTML lain ke dalam halaman, sehingga peta, pemutar media, atau halaman lampiran dapat tampil di dalam kotak tersendiri. Topik ini membahas atribut inti iframe, kewajiban mengisi title demi aksesibilitas, pemuatan lambat dengan loading, pengamanan melalui sandbox, penyisipan dokumen langsung dengan srcdoc, serta pertimbangan kapan penyematan tidak diperlukan. Setelah mengikuti topik ini, keputusan menyematkan atau sekadar bertaut dapat diambil dengan alasan yang jelas.

Menyematkan halaman dengan src#

Atribut src menyatakan alamat dokumen yang disematkan, dan browser membukanya sebagai konteks penelusuran bersarang (nested browsing context), yaitu dokumen lengkap dengan halaman dan riwayatnya sendiri di dalam sebuah kotak. Ukuran kotaknya ditetapkan oleh width dan height, karena tanpa keduanya iframe menggunakan ukuran bawaan yang jarang pas. Isi kotaknya dapat digulir terpisah dari halaman induknya, dan halaman induk tidak dapat membaca isi dokumen yang berasal dari situs lain karena aturan same-origin policy. Bingkai juga dapat digayai seperti elemen lain, misalnya lebarnya disesuaikan CSS halaman induk. Isi di dalam bingkai tetap tunduk pada gaya dari dokumen yang disematkan.

Atribut loading="lazy" menunda pengunduhan dokumen yang berada di luar layar hingga bingkainya mendekat ke area pandang. Halaman dengan beberapa sematan yang jauh di bawah menjadi lebih cepat tampil karena sematan yang belum terlihat tidak diunduh sama sekali. Nilai loading="eager" memuat sematan segera dan merupakan perilaku bawaan, sehingga atribut ini hanya perlu ditulis ketika pemuatan lambat diinginkan.

html Contoh: iframe dengan pemuatan lambat
<iframe src="lampiran.html" title="Pengumuman kelas" width="480" height="180"
  loading="lazy"></iframe>

title yang wajib diisi#

Atribut title pada iframe bukan pelengkap, melainkan kewajiban aksesibilitas. Pembaca layar (screen reader) mengumumkan keberadaan bingkai kepada pengguna, dan tanpa title bingkai diumumkan tanpa nama, sehingga pengguna tidak tahu isinya sebelum memasukinya. Judulnya mendeskripsikan isi dokumen yang disematkan, misalnya “Pengumuman kelas”, dan bukan kata iframe itu sendiri.

Jebakan yang paling sering ditemui adalah iframe peta atau pemutar yang ditempel tanpa title, biasanya karena kode sematannya disalin utuh dari layanan pihak ketiga. Salinan semacam itu boleh disunting, dan menambahkan title pada tag pembukanya tidak mengganggu layanan yang disematkan. Judul yang baik menyebut isi atau fungsinya, misalnya Peta lokasi acara, dan bukan kata Bingkai yang tidak membawa informasi apa pun. Kebiasaan yang baik adalah memeriksa setiap tag pembuka iframe segera setelah kode semat ditempel.

Mengamankan bingkai dengan sandbox#

Atribut sandbox memasang pagar pada dokumen yang disematkan dengan menolak sekumpulan kemampuan secara bawaan. Ditulis tanpa nilai, atribut ini menolak semuanya. Akibatnya skrip tidak berjalan, formulir tidak terkirim, dan jendela baru tidak terbuka. Dokumen juga diperlakukan berasal dari asal yang unik (opaque origin), sehingga aksesnya ke penyimpanan browser ditolak. Kemampuan dikembalikan satu per satu melalui token pada nilai atributnya.

TokenKemampuan yang dikembalikan
allow-scriptsMenjalankan skrip di dalam bingkai
allow-same-originMemulihkan asal dokumennya, termasuk akses penyimpanan
allow-formsMengirim formulir
allow-popupsMembuka jendela baru
allow-top-navigationMengarahkan ulang halaman induk

Dua token pertama menuntut kehati-hatian karena kombinasi keduanya membatalkan pengamanan itu sendiri.

Kombinasi berbahaya itu dapat dideteksi dari nilai atributnya. Skrip berikut memeriksa apakah suatu nilai sandbox memuat kedua token sekaligus, dan keluarannya menunjukkan nilai yang harus dihindari.

js Memeriksa kombinasi token sandbox
// memeriksa kombinasi token sandbox yang melemahkan pengamanan
function periksaSandbox(nilai) {
  const token = nilai.trim().split(/\s+/).filter(Boolean);
  const lemah = token.includes("allow-scripts") && token.includes("allow-same-origin");
  return { token: token, lemah: lemah };
}

console.log(JSON.stringify(periksaSandbox("allow-scripts allow-same-origin")));
console.log(JSON.stringify(periksaSandbox("allow-scripts")));
console.log(JSON.stringify(periksaSandbox("")));
text Keluaran
{"token":["allow-scripts","allow-same-origin"],"lemah":true}
{"token":["allow-scripts"],"lemah":false}
{"token":[],"lemah":false}

Keluaran menegaskan bahwa nilai pertama adalah kombinasi yang melemahkan pengamanan, sedangkan dua nilai lainnya dapat digunakan sebagai pagar. Bagi dokumen yang hanya menampilkan teks dan gambar, sandbox="" tanpa token apa pun sudah cukup dan merupakan pilihan paling aman.

Demo perilaku sandbox#

Demo berikut memuat dokumen uji di dalam bingkai dengan tiga pilihan nilai sandbox yang dapat diganti. Pada pilihan tanpa atribut dan pilihan allow-scripts, skrip di dalam dokumen uji berjalan sejak dokumen dimuat dan tombolnya merespons klik. Pada pilihan sandbox="", teksnya tetap menyatakan skrip belum berjalan dan tombolnya mati, karena seluruh kemampuan sedang ditolak. Jalankan demo tersebut, ganti pilihannya satu per satu, kemudian amati perubahan teks di dalam bingkainya.

Kode sumber demo
<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <title>Demo perilaku sandbox</title>
  <style>
    body { font-family: sans-serif; max-width: 36rem; margin: 0 auto; padding: 0 1rem; color: #222222; }
    fieldset { margin: 0 0 0.75rem; border: 1px solid #bbbbbb; border-radius: 4px; }
    legend { font-weight: 600; }
    label { margin-right: 0.75rem; }
    iframe { border: 1px solid #999999; border-radius: 4px; width: 100%; height: 120px; }
  </style>
</head>
<body>
  <p>Pilih nilai atribut <code>sandbox</code>, lalu amati dokumen uji yang dimuat ulang.</p>
  <fieldset>
    <legend>Nilai sandbox</legend>
    <label><input type="radio" name="sb" value="tanpa" checked> tanpa atribut</label>
    <label><input type="radio" name="sb" value="penuh"> sandbox=""</label>
    <label><input type="radio" name="sb" value="scripts"> allow-scripts</label>
  </fieldset>

  <iframe id="bingkai" title="Dokumen uji di dalam bingkai"></iframe>

  <script>
    // tag "script" dipecah menjadi dua potong string agar tidak menutup
    // skrip halaman induknya lebih awal
    const isi =
      "<p id='status'>skrip belum berjalan</p>" +
      "<button id='tombol' type='button'>Jalankan skrip</button>" +
      "<scr" + "ipt>" +
      "const status = document.getElementById('status');" +
      "status.textContent = 'skrip berjalan sejak dokumen dimuat';" +
      "document.getElementById('tombol').addEventListener('click', () => {" +
      "  status.textContent = 'skrip merespons klik tombol';" +
      "});" +
      "<\/scr" + "ipt>";

    function muat() {
      const nilai = document.querySelector("input[name=sb]:checked").value;
      const lama = document.getElementById("bingkai");
      const baru = document.createElement("iframe");
      baru.id = "bingkai";
      baru.title = "Dokumen uji di dalam bingkai";
      if (nilai === "penuh") {
        baru.setAttribute("sandbox", "");
      } else if (nilai === "scripts") {
        baru.setAttribute("sandbox", "allow-scripts");
      }
      baru.srcdoc = isi;
      lama.replaceWith(baru);
    }

    document.querySelectorAll("input[name=sb]").forEach((r) => {
      r.addEventListener("change", muat);
    });

    muat();
  </script>
</body>
</html>

Pada kode demonya, dokumen uji ditulis sebagai string srcdoc, dan bingkainya dibuat ulang setiap pilihan berganti agar keadaan dokumen selalu dimulai dari awal. Penulisan tag script dipecah menjadi dua potong string agar tidak menutup skrip halaman induknya lebih awal, yaitu teknik kecil yang lazim ditemui pada kode yang menyusun HTML sebagai string. Dengan sandbox="", tombolnya tetap tampil tetapi tidak merespons apa pun, dan keadaan itulah yang dialami skrip pihak ketiga ketika pagarnya ditutup. Pembatasan itu tidak menghapus isi dokumen, melainkan kemampuannya, sehingga gambar dan teksnya tetap tampil.

Dokumen langsung dengan srcdoc#

Atribut srcdoc mengisi bingkai dengan dokumen yang ditulis langsung sebagai nilai atribut, tanpa mengunduh berkas apa pun. Isinya berupa dokumen HTML dalam satu string, dan tanda kutip di dalamnya menggunakan bentuk yang tidak bertabrakan dengan tanda kutip atribut. Pasangan srcdoc dan sandbox sering digunakan bersama untuk menampilkan potongan HTML yang tidak sepenuhnya dipercaya, misalnya pratinjau komentar, dengan seluruh kemampuannya ditolak lebih dahulu.

html Contoh: iframe dengan srcdoc
<iframe srcdoc="<p><strong>Perhatian:</strong> libur mulai hari Jumat.</p>"
  title="Catatan singkat" width="480" height="80" sandbox=""></iframe>

Bila atribut src dan srcdoc sama-sama ada, srcdoc yang digunakan, sehingga dokumen unduhan hanya berperan sebagai cadangan bagi browser lama yang tidak mendukung srcdoc. Tanda kutip di dalam potongan HTML menggunakan bentuk yang berbeda dari tanda kutip atributnya, dan kedua bentuk kutip itu sah dalam HTML. Untuk dokumen yang isinya berubah-ubah, srcdoc diperbarui melalui skrip dengan menetapkan properti srcdoc pada elemen bingkainya, dan browser memuat ulang dokumen tersebut. Karena isinya menyatu dengan atribut, srcdoc cocok untuk dokumen pendek, sedangkan dokumen panjang lebih nyaman ditulis sebagai berkas tersendiri dan disematkan lewat src.

Kapan penyematan tidak diperlukan#

Menyematkan dokumen selalu menambah biaya, berupa permintaan jaringan tambahan, markup yang lebih sulit dipelihara, dan risiko aksesibilitas karena pengguna harus berpindah konteks untuk melewati bingkai. Penyematan pihak ketiga juga menyerahkan sebagian halaman kepada pihak lain, lengkap dengan skrip dan pengukuran yang menyertainya, sehingga privasi dan kecepatan halaman ikut dipengaruhi. Pertimbangan sebelum menyematkan karenanya diarahkan pada pertanyaan fungsional, yaitu apakah kontennya memang perlu tampil bersamaan dengan halaman induknya.

SituasiPilihan yang tepat
Dokumen dapat dibaca berdiri sendiriTautan biasa dengan a dan href
Kutipan pendek dari halaman lainElemen blockquote beserta atribut cite
Peta atau pemutar yang memang interaktififrame dengan title dan sandbox
Pratinjau HTML yang tidak sepenuhnya dipercayaiframe dengan srcdoc dan sandbox

Tautan biasa sudah cukup untuk dokumen yang tidak memerlukan interaksi di dalam halaman, misalnya pengumuman yang dapat dibuka tersendiri. Penyematan baru layak ketika kontennya benar-benar menjadi bagian dari halaman, seperti peta pada halaman lokasi atau pemutar pada halaman rekaman. Untuk layanan pihak ketiga, alamat sematannya ditulis sebagaimana diberikan penyedianya, misalnya https://peta.example/embed/lokasi, dan tetap disertai title serta sandbox.

Contoh berkas utuh#

Contoh utuh berikut memuat dua berkas dalam satu folder, yaitu berita.html sebagai halaman yang disematkan dan sematan.html sebagai halaman induknya. Buka sematan.html di browser, dan dua bingkai akan tampil, satu berisi lampiran pengumuman yang dimuat lambat, satu lagi berisi dokumen srcdoc yang dibungkus sandbox.

html berita.html
<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <title>Pengumuman kelas</title>
  <style>
    body { font-family: sans-serif; margin: 1rem; color: #222222; }
    h1 { font-size: 1.1rem; }
    li { margin: 0.25rem 0; }
  </style>
</head>
<body>
  <h1>Pengumuman kelas</h1>
  <ul>
    <li>Jadwal piket minggu ini dipimpin oleh Ali.</li>
    <li>Ujian matematika digeser ke hari Kamis.</li>
    <li>Iuran kelas dikumpulkan sebelum hari Jumat.</li>
  </ul>
</body>
</html>

berita.html hanyalah halaman biasa tanpa persiapan khusus untuk penyematan. Halaman apa pun dapat disematkan, dan yang menentukan perilaku bingkainya adalah halaman induk yang menyematkannya.

html sematan.html
<!DOCTYPE html>
<html lang="id">
<head>
  <meta charset="utf-8">
  <title>Contoh penyematan iframe</title>
  <style>
    body { font-family: sans-serif; max-width: 40rem; margin: 0 auto; padding: 0 1rem; }
    iframe { border: 1px solid #bbbbbb; border-radius: 4px; }
  </style>
</head>
<body>
  <h1>Contoh penyematan iframe</h1>

  <h2>Halaman lampiran</h2>
  <iframe src="berita.html" title="Pengumuman kelas" width="480" height="180"
    loading="lazy"></iframe>

  <h2>Dokumen srcdoc</h2>
  <iframe
    srcdoc="<p><strong>Perhatian:</strong> libur mulai hari Jumat.</p>"
    title="Catatan singkat" width="480" height="80" sandbox=""></iframe>
</body>
</html>

Halaman induk menetapkan title, width, dan height pada setiap bingkainya, karena ukuran dan nama bingkai ditentukan oleh halaman yang menyematkan, bukan oleh halaman yang disematkan. Berkas berita.html juga dapat dibuka langsung untuk memastikan halamannya layak berdiri sendiri, karena sematan yang baik selalu menampilkan dokumen yang utuh tanpa kotaknya. Gulir halaman induknya untuk mengamati loading="lazy" bekerja, yaitu berkas lampiran baru diunduh ketika bingkainya mendekat ke area pandang. Dokumen srcdoc menggunakan sandbox="" yang menolak segalanya, dan karena tidak ada skrip di dalamnya, pembatasan itu tidak mengubah apa pun.

Kesalahan umum#

Menyematkan tanpa title. Bingkai diumumkan tanpa nama kepada pengguna pembaca layar, sehingga isinya menjadi tebak-tebakan. Isi title dengan deskripsi singkat dokumen yang disematkan pada setiap tag pembuka iframe.

Menyalin kode semat tanpa membaca atributnya. Kode sematan pihak ketiga sering datang tanpa sandbox dan tanpa title, lengkap dengan skrip yang tidak diperlukan. Baca atributnya, tambahkan title, dan timbang nilai sandbox sesuai kebutuhan konten yang disematkan.

Menggabungkan allow-scripts dan allow-same-origin begitu saja. Pada dokumen yang berasal dari asal yang sama, kombinasi ini memungkinkan dokumen bingkai membuka pagarnya sendiri. Berikan kedua token hanya kepada konten yang benar-benar dipercaya, atau pisahkan dokumennya ke asal yang berbeda.

Menyematkan dokumen yang cukup ditautkan. Setiap sematan menambah permintaan jaringan dan memotong alur baca, sedangkan tautan biasa melayani dokumen yang dapat dibuka tersendiri. Simpan iframe untuk konten yang memang perlu tampil bersamaan dengan halaman induknya.

Mengatur ukuran bingkai dari dokumen yang disematkan. Ukuran bingkai ditetapkan halaman induknya melalui width dan height, sehingga pengaturan serupa di dalam dokumen yang disematkan tidak mengubah kotaknya. Tentukan ukurannya pada tag iframe, dan biarkan dokumen di dalamnya mengisi ruang yang diberikan.

Ringkasan#

  • iframe membuka dokumen lain sebagai konteks penelusuran bersarang, dengan src atau srcdoc sebagai sumbernya dan width serta height sebagai ukurannya.
  • Atribut title wajib diisi karena menjadi nama bingkai bagi pembaca layar, dan loading="lazy" menunda pemuatan sematan yang belum terlihat.
  • Atribut sandbox menolak kemampuan bingkai secara bawaan, token mengembalikannya satu per satu, dan kombinasi allow-scripts dengan allow-same-origin membatalkan pagar itu sendiri.
  • Penyematan dipertimbangkan berdasarkan fungsinya, karena dokumen yang dapat berdiri sendiri lebih tepat ditautkan daripada disematkan.

Referensi#