Come applicare CSS a iframe?


1017

Ho una semplice pagina che ha alcune sezioni iframe (per visualizzare i collegamenti RSS). Come posso applicare lo stesso formato CSS dalla pagina principale alla pagina visualizzata nell'iframe?


66
È possibile ma solo se il dominio dell'iframe è lo stesso del genitore
gawpertron,

13
gawpertron, solo per chiarire, stai dicendo che se uso i contenuti iFrame da qualche altro dominio che non controllo, non c'è modo per me di controllare il CSS per quel contenuto?
Ville M

Puoi elencare un link alla pagina in modo che potremmo solo essere in grado di visualizzare le nostre modifiche.

5
Il dominio, la porta e il protocollo devono essere gli stessi, non funzionano neanche con i sottodomini.
Lee Penkman,

Risposte:


434

Modifica: non funziona tra domini diversi a meno che non sia impostata l' intestazione CORS appropriata .

Ci sono due cose diverse qui: lo stile del blocco iframe e lo stile della pagina incorporato nell'iframe. Puoi impostare lo stile del blocco iframe nel solito modo:

<iframe name="iframe1" id="iframe1" src="empty.htm" 
        frameborder="0" border="0" cellspacing="0"
        style="border-style: none;width: 100%; height: 120px;"></iframe>

Lo stile della pagina incorporata nell'iframe deve essere impostato includendolo nella pagina figlio:

<link type="text/css" rel="Stylesheet" href="Style/simple.css" />

Oppure può essere caricato dalla pagina principale con Javascript:

var cssLink = document.createElement("link");
cssLink.href = "style.css"; 
cssLink.rel = "stylesheet"; 
cssLink.type = "text/css"; 
frames['iframe1'].document.head.appendChild(cssLink);

30
Nota, mi sembra che alcuni degli esempi pubblicati in precedenza non siano ora validi per HTML5. È possibile accedere al contenuto del telaio come segue: document.getElementById("myframe").contentDocument. Incorporare il CSS non sembra comunque funzionare per me.
Rehno Lindeque,

35
il link potrebbe apparire solo in HEAD
Knu

18
Ha funzionato per me solo quando l'ho fatto ...document.head.appendChild(cssLink)- Firefox e Safari.
Mojuba,

24
Funziona davvero tra domini? Non penso che sarebbe.
Simon East,

89
Solo così nessun altro deve testarlo per scoprirlo: corretto, non funziona tra domini. Immediatamente dopo aver eseguito i frame ['name'] si ottiene "Tentativo JavaScript non sicuro per accedere al frame con URL blah dal frame con URL blah. Domini, protocolli e porte devono corrispondere."
Kevin,

205

Ho riscontrato questo problema con Google Calendar . Volevo modellarlo su uno sfondo più scuro e cambiare carattere.

Fortunatamente, l'URL del codice di incorporamento non aveva restrizioni sull'accesso diretto, quindi utilizzando la funzione PHP file_get_contentsè possibile ottenere l'intero contenuto dalla pagina. Invece di chiamare l'URL di Google, è possibile chiamare un file php situato sul tuo server, ad es. google.php, che conterrà il contenuto originale con modifiche:

$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');

Aggiunta del percorso al foglio di stile:

$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);

(Questo posizionerà il tuo foglio di stile per ultimo appena prima del headtag di fine.)

Specifica l'URL di base dall'URL originale nel caso in cui css e js siano chiamati relativamente:

$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);

Il google.phpfile finale dovrebbe apparire così:

<?php
$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');
$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);
$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);
echo $content;

Quindi si modifica il iframecodice di incorporamento in:

<iframe src="http://www.yourwebsiteurl.com/google.php" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>

In bocca al lupo!


71
Puoi chiamarlo per definizione se vuoi. Ma non hai offerto alcuna soluzione migliore ... Questa soluzione non è un modo per danneggiare il servizio di Google o per ingannare le persone in modo da sfruttare le loro debolezze.
SequenceDigitale.com,

5
Vorrei uccidere per un modo per far funzionare questa soluzione con Google Documenti. Sta lanciando ogni sorta di errori javascript. "Uncaught TypeError: impossibile leggere la proprietà 'a' di undefined"
deweydb

1
Nevermind, ho capito, postato la soluzione qui: stackoverflow.com/questions/25395279/...
deweydb

9
@ChrisHoughton FYI, in pratica non lo è. Potrebbe, tuttavia, rendere inutile l'intero iframe (un motivo per utilizzare iframe, ad esempio, è per motivi di sicurezza, ad esempio con i pagamenti con carta, e se fai ciò che viene suggerito qui probabilmente ti causerai problemi).
alastair,

10
In questo modo ottieni sempre il calendario come utente non connesso. Con il normale iframe html l'utente vedrebbe il proprio calendario personale se fosse stato effettuato l'accesso a google, ma poiché il tuo codice PHP non è in grado di conoscere l'ID sessione di Google degli utenti, non può recuperare il proprio calendario personale.
bdsl,

72

Se il contenuto dell'iframe non è completamente sotto il tuo controllo o desideri accedere al contenuto da diverse pagine con stili diversi, puoi provare a manipolarlo utilizzando JavaScript.

var frm = frames['frame'].document;
var otherhead = frm.getElementsByTagName("head")[0];
var link = frm.createElement("link");
link.setAttribute("rel", "stylesheet");
link.setAttribute("type", "text/css");
link.setAttribute("href", "style.css");
otherhead.appendChild(link);

Tieni presente che, a seconda del browser utilizzato, questo potrebbe funzionare solo su pagine pubblicate dallo stesso dominio.


82
Vale la pena notare che la stessa politica di origine smetterà di funzionare se la pagina si trova su un dominio diverso.
ConroyP

2
Nella stessa linea di pensiero, ma più conciso: <iframe onload="this.contentDocument.body.style.overflow='hidden';" />
Protettore un

Anche Firefox è diventato CORS

59
var $head = $("#eFormIFrame").contents().find("head");

$head.append($("<link/>", {
    rel: "stylesheet",
    href: url,
    type: "text/css"
}));

@deweydb l'ho usato specificamente con un iframe interdominio. ma posso solo chiedere perdono!
Rami Sarieddine,

@ramie e l'hai testato su più browser? la maggior parte dei browser genera un errore di sicurezza.
Deweydb,

Ho già visto questa idea, ma ho aggiunto un link per archiviare il suo video davvero fantastico e professionale ... + su
J.Tural

29

Un iframe è gestito universalmente come una pagina HTML diversa dalla maggior parte dei browser. Se vuoi applicare lo stesso foglio di stile al contenuto dell'iframe, fai semplicemente riferimento alle pagine in esso utilizzate.


22
@hangry ma ... come?
A Child of God,

29

Ecco come applicare direttamente il codice CSS senza utilizzare <link>per caricare un foglio di stile aggiuntivo.

var head = jQuery("#iframe").contents().find("head");
var css = '<style type="text/css">' +
          '#banner{display:none}; ' +
          '</style>';
jQuery(head).append(css);

Questo nasconde il banner nella pagina iframe. Grazie per i vostri suggerimenti!


1
Questo ha bisogno di un iframe con l'id di iframe?
Jeremy,

1
@jmalais Basta sostituire #iframecon #<id>o anche iframeper selezionare tutti iframei messaggi
Zeb McCorkle

3
Questo non sembra funzionare per me. L'iframe che sto provando a modificare inoltre non ha la testa direttamente sotto di esso nella dom. Quindi questo significa che devo accedere alla testa all'interno del documento HTML o è qualcosa che la funzione di ricerca jquery dovrebbe essere in grado di fare da sola?
David A. francese,

1
Controllato la console e sembra che sia stato bloccato l'accesso ai contenuti iframe a causa di una mancata corrispondenza del dominio. Attualmente sto utilizzando Chrome e sto ospitando il mio ambiente di sviluppo locale.
David A. francese,

DOMException non rilevata: bloccato un frame con origine mi dà questo errore
priyanka patel

26

Se controlli la pagina nell'iframe, come ha detto hangy, l'approccio più semplice è quello di creare un file CSS condiviso con stili comuni, quindi collegalo ad esso dalle tue pagine html.

Altrimenti è improbabile che tu possa cambiare in modo dinamico lo stile di una pagina da una pagina esterna nel tuo iframe. Questo perché i browser hanno rafforzato la sicurezza dello scripting dom cross frame a causa di un possibile uso improprio di spoofing e altri hack.

Questo tutorial può fornirti maggiori informazioni sugli script iframe in generale. Informazioni sullo scripting cross frame spiega le restrizioni di sicurezza dal punto di vista di IE.


19

Quanto sopra con un piccolo cambiamento funziona:

var cssLink = document.createElement("link") 
cssLink.href = "pFstylesEditor.css"; 
cssLink.rel = "stylesheet"; 
cssLink.type = "text/css"; 

//Instead of this
//frames['frame1'].document.body.appendChild(cssLink);
//Do this

var doc=document.getElementById("edit").contentWindow.document;

//If you are doing any dynamic writing do that first
doc.open();
doc.write(myData);
doc.close();

//Then append child
doc.body.appendChild(cssLink);

Funziona bene con ff3 e ie8 almeno


7
Che cos'è myData e da dove viene
Tigran,

1
@Tigran è perdynamic data
Akash

13

Se vuoi riutilizzare CSS e JavaScript dalla pagina principale, forse dovresti prendere in considerazione la sostituzione <IFRAME>con un contenuto caricato Ajax. Questo è più SEO friendly ora quando i robot di ricerca sono in grado di eseguire JavaScript.

Questo è un esempio di jQuery che include un'altra pagina HTML nel documento. Questo è molto più SEO friendly di iframe. Per essere sicuro che i bot non indicizzino la pagina inclusa, basta aggiungerla per non consentirerobots.txt

<html>
  <header>
    <script src="/js/jquery.js" type="text/javascript"></script>
  </header>
  <body>
    <div id='include-from-outside'></div>
    <script type='text/javascript'>
      $('#include-from-outside').load('http://example.com/included.html');
    </script> 
  </body>
</html>

Potresti anche includere jQuery direttamente da Google: http://code.google.com/apis/ajaxlibs/documentation/ - questo significa inclusione automatica opzionale delle versioni più recenti e un significativo aumento della velocità. Inoltre, significa che devi fidarti di loro per averti consegnato solo jQuery;)


1
Si noti che questa soluzione non funziona se il contenuto della pagina è dinamico in alcun modo.
Nickdnk,

12

Quanto segue ha funzionato per me.

var iframe = top.frames[name].document;
var css = '' +
          '<style type="text/css">' +
          'body{margin:0;padding:0;background:transparent}' +
          '</style>';
iframe.open();
iframe.write(css);
iframe.close();

1
Errore:Uncaught TypeError: Cannot read property 'open' of undefined
KingRider,

10

Espandere la soluzione jQuery sopra per far fronte a eventuali ritardi nel caricamento dei contenuti del frame.

$('iframe').each(function(){
    function injectCSS(){
        $iframe.contents().find('head').append(
            $('<link/>', { rel: 'stylesheet', href: 'iframe.css', type: 'text/css' })
        );
    }

    var $iframe = $(this);
    $iframe.on('load', injectCSS);
    injectCSS();
});

1
"$ This" deve essere un "$ (this)" per funzionare. Bello quando lo fa :)
h.coates

9

La mia versione compatta :

<script type="text/javascript">
$(window).load(function () {
    var frame = $('iframe').get(0);
    if (frame != null) {
        var frmHead = $(frame).contents().find('head');
        if (frmHead != null) {
            frmHead.append($('style, link[rel=stylesheet]').clone()); // clone existing css link
            //frmHead.append($("<link/>", { rel: "stylesheet", href: "/styles/style.css", type: "text/css" })); // or create css link yourself
        }
    }   
});
</script>

Tuttavia, a volte iframenon è pronto per la finestra caricata, quindi è necessario utilizzare un timer .

Codice pronto all'uso (con timer):

<script type="text/javascript">
var frameListener;
$(window).load(function () {
    frameListener = setInterval("frameLoaded()", 50);
});
function frameLoaded() {
    var frame = $('iframe').get(0);
    if (frame != null) {
        var frmHead = $(frame).contents().find('head');
        if (frmHead != null) {
            clearInterval(frameListener); // stop the listener
            frmHead.append($('style, link[rel=stylesheet]').clone()); // clone existing css link
            //frmHead.append($("<link/>", { rel: "stylesheet", href: "/styles/style.css", type: "text/css" })); // or create css link yourself
        }
    }
}
</script>

... e collegamento jQuery:

<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>

8

Altre risposte qui sembrano usare i collegamenti jQuery e CSS.

Questo codice utilizza JavaScript vaniglia. Crea un nuovo <style>elemento. Imposta il contenuto del testo di quell'elemento come una stringa contenente il nuovo CSS. E aggiunge quell'elemento direttamente alla testa del documento iframe.

var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
  '.some-class-name {' +
  '  some-style-name: some-value;' +
  '}' 
;
iframe.contentDocument.head.appendChild(style);

7

Quando dici "doc.open ()" significa che puoi scrivere qualunque tag HTML all'interno dell'iframe, quindi dovresti scrivere tutti i tag di base per la pagina HTML e se vuoi avere un collegamento CSS nella tua testa iframe scrivi semplicemente un iframe con link CSS al suo interno. Ti faccio un esempio:

doc.open();

doc.write('<!DOCTYPE html><html><head><meta charset="utf-8"/><meta http-quiv="Content-Type" content="text/html; charset=utf-8"/><title>Print Frame</title><link rel="stylesheet" type="text/css" href="https://stackoverflow.com/css/print.css"/></head><body><table id="' + gridId + 'Printable' + '" class="print" >' + out + '</table></body></html>');

doc.close();

7

l'uso può provare questo:

$('iframe').load( function() {
     $('iframe').contents().find("head")
     .append($("<style type='text/css'>  .my-class{display:none;}  </style>"));
  });

3
Se il tuo iframe proviene da origini diverse, il meccanismo CORS non consentirà questa soluzione.
Mr. Anderson,

Cosa succede se iframe-url è CORS abilitato per tutte le posizioni?
adrhc,

6

Non sarai in grado di dare uno stile ai contenuti dell'iframe in questo modo. Il mio suggerimento sarebbe di utilizzare gli script lato server (PHP, ASP o uno script Perl) o di trovare un servizio online che convertirà un feed in codice JavaScript. L'unico altro modo per farlo sarebbe se fosse possibile includere un lato server.


29
Attento quando dici che qualcosa non può essere fatto, quando in realtà è solo difficile
Lathan,

4

Nel caso in cui tu abbia accesso alla pagina iframe e desideri che un CSS diverso si applichi ad esso solo quando lo carichi tramite iframe sulla tua pagina, qui ho trovato una soluzione per questo tipo di cose

funziona anche se iframe sta caricando un dominio diverso

controllare postMessage()

piano è, inviare il CSS a iframe come un messaggio simile

iframenode.postMessage('h2{color:red;}','*');

* è inviare questo messaggio indipendentemente dal dominio in iframe

e ricevi il messaggio in iframe e aggiungi il messaggio ricevuto (CSS) all'intestazione del documento.

codice da aggiungere nella pagina iframe

window.addEventListener('message',function(e){

    if(e.data == 'send_user_details')
    document.head.appendChild('<style>'+e.data+'</style>');

});

4

Poiché molte risposte sono scritte per gli stessi domini, scriverò come farlo in più domini.

Innanzitutto, devi conoscere l' API Post Message . Abbiamo bisogno di un messaggero per comunicare tra due finestre.

Ecco un messenger che ho creato.

/**
 * Creates a messenger between two windows
 *  which have two different domains
 */
class CrossMessenger {

    /**
     * 
     * @param {object} otherWindow - window object of the other
     * @param {string} targetDomain - domain of the other window
     * @param {object} eventHandlers - all the event names and handlers
     */
    constructor(otherWindow, targetDomain, eventHandlers = {}) {
        this.otherWindow = otherWindow;
        this.targetDomain = targetDomain;
        this.eventHandlers = eventHandlers;

        window.addEventListener("message", (e) => this.receive.call(this, e));
    }

    post(event, data) {

        try {
            // data obj should have event name
            var json = JSON.stringify({
                event,
                data
            });
            this.otherWindow.postMessage(json, this.targetDomain);

        } catch (e) {}
    }

    receive(e) {
        var json;
        try {
            json = JSON.parse(e.data ? e.data : "{}");
        } catch (e) {
            return;
        }
        var eventName = json.event,
            data = json.data;

        if (e.origin !== this.targetDomain)
            return;

        if (typeof this.eventHandlers[eventName] === "function") 
            this.eventHandlers[eventName](data);
    }

}

Usarlo in due finestre per comunicare può risolvere il tuo problema.

Nelle finestre principali,

var msger = new CrossMessenger(iframe.contentWindow, "https://iframe.s.domain");

var cssContent = Array.prototype.map.call(yourCSSElement.sheet.cssRules, css_text).join('\n');
msger.post("cssContent", {
   css: cssContent
})

Quindi, ricevi l'evento dall'Iframe.

Nell'Iframe:

var msger = new CrossMessenger(window.parent, "https://parent.window.domain", {
    cssContent: (data) => {
        var cssElem = document.createElement("style");
        cssElem.innerHTML = data.css;
        document.head.appendChild(cssElem);
    }
})

Vedi il tutorial completo su Javascript e Iframe per maggiori dettagli.


3

Ho trovato un'altra soluzione per mettere lo stile nel html principale in questo modo

<style id="iframestyle">
    html {
        color: white;
        background: black;
    }
</style>
<style>
    html {
        color: initial;
        background: initial;
    }
    iframe {
        border: none;
    }
</style>

e quindi in iframe fai questo (vedi js onload)

<iframe  onload="iframe.document.head.appendChild(ifstyle)" name="log" src="/upgrading.log"></iframe>

e in js

<script>
    ifstyle = document.getElementById('iframestyle')
    iframe = top.frames["log"];
</script>

Potrebbe non essere la soluzione migliore e certamente può essere migliorata, ma è un'altra opzione se si desidera mantenere un tag "style" nella finestra principale


3

Qui, ci sono due cose all'interno del dominio

  1. Sezione iFrame
  2. Pagina caricata all'interno dell'iFrame

Quindi vuoi dare uno stile a queste due sezioni come segue,

1. Stile per la sezione iFrame

Può modellare usando CSS con quel rispettato ido classnome. Puoi semplicemente disegnarlo nei fogli di stile dei tuoi genitori.

<style>
#my_iFrame{
height: 300px;
width: 100%;
position:absolute;
top:0;
left:0;
border: 1px black solid;
}
</style>

<iframe name='iframe1' id="my_iFrame" src="#" cellspacing="0"></iframe>

2. Stile della pagina caricata all'interno dell'iFrame

Questi stili possono essere caricati dalla pagina principale con l'aiuto di Javascript

var cssFile  = document.createElement("link") 
cssFile.rel  = "stylesheet"; 
cssFile.type = "text/css"; 
cssFile.href = "iFramePage.css"; 

quindi imposta quel file CSS sulla sezione iFrame rispettata

//to Load in the Body Part
frames['my_iFrame'].document.body.appendChild(cssFile); 
//to Load in the Head Part
frames['my_iFrame'].document.head.appendChild(cssFile);

Qui, puoi modificare la parte principale della pagina all'interno dell'iFrame usando anche questo modo

var $iFrameHead = $("#my_iFrame").contents().find("head");
$iFrameHead.append(
   $("<link/>",{ 
      rel: "stylesheet", 
      href: urlPath, 
      type: "text/css" }
     ));

2

Possiamo inserire tag di stile in iframe. Inserito anche qui ...

<style type="text/css" id="cssID">
.className
{
    background-color: red;
}
</style>

<iframe id="iFrameID"></iframe>

<script type="text/javascript">
    $(function () {
        $("#iFrameID").contents().find("head")[0].appendChild(cssID);
        //Or $("#iFrameID").contents().find("head")[0].appendChild($('#cssID')[0]);
    });
</script>

1
Questo non funziona Sembra inserire correttamente il tag di stile ma non contiene contenuti e ID.
darylknight,

2

var link1 = document.createElement('link');
    link1.type = 'text/css';
    link1.rel = 'stylesheet';
    link1.href = "../../assets/css/normalize.css";
window.frames['richTextField'].document.body.appendChild(link1);


1
Ho controllato questa risposta molte volte che cosa è richTextFieldqui?
Kirankumar Dafda,

1
è il nome iframe
Jeeva

Non ci ho provato, ma immagino che non lo farà perché è contro la sandbox
Jeeva il

1

Penso che il modo più semplice sia quello di aggiungere un altro div, nello stesso posto dell'iframe, quindi

rendilo z-indexpiù grande del contenitore iframe, così puoi facilmente modellare il tuo div. Se è necessario fare clic su di esso, basta usare pointer-events:noneil proprio div, quindi l'iframe funzionerebbe nel caso in cui sia necessario fare clic su di esso;)

Spero che possa aiutare qualcuno;)


1

Esiste uno script meraviglioso che sostituisce un nodo con una versione iframe di se stesso. Demo CodePen

inserisci qui la descrizione dell'immagine

Esempi di utilizzo:

// Single node
var component = document.querySelector('.component');
var iframe = iframify(component);

// Collection of nodes
var components = document.querySelectorAll('.component');
var iframes = Array.prototype.map.call(components, function (component) {
  return iframify(component, {});
});

// With options
var component = document.querySelector('.component');
var iframe = iframify(component, {
  headExtra: '<style>.component { color: red; }</style>',
  metaViewport: '<meta name="viewport" content="width=device-width">'
});

1
Perché vorresti farlo ?!
Dylan Watson,


0

Questo è solo un concetto, ma non implementarlo senza controlli di sicurezza e filtri! Altrimenti gli script potrebbero hackerare il tuo sito!

Risposta: se controlli il sito di destinazione, puoi impostare lo script del destinatario come:

1) imposta il link iframe con il styleparametro, come:

http://your_site.com/target.php?color=red

(l'ultima frase è a{color:red} codificata dalla urlencodefunzione.

2) impostare la pagina del destinatario in target.phpquesto modo:

<head>
..........
$col = FILTER_VAR(SANITIZE_STRING, $_GET['color']);
<style>.xyz{color: <?php echo (in_array( $col, ['red','yellow','green'])?  $col : "black") ;?> } </style>
..........

3
Attenzione: questa è l'iniezione al suo meglio.
kano,

1
sì, NON farlo, tranne per il fatto che vuoi un carico di bot di pen test e script kiddies sul tuo server =) ...
exside,

1
Ho aggiornato la risposta ora, con l'aggiunta di un avviso di sicurezza
T.Todua

-18

Bene, ho seguito questi passaggi:

  1. Div con una classe da tenere iframe
  2. Aggiungi iframea div.
  3. Nel file CSS,
divClass { width: 500px; height: 500px; }
divClass iframe { width: 100%; height: 100%; }

Funziona in IE 6. Dovrebbe funzionare in altri browser, controlla!


9
bisogno di controllare il div all'interno di iframe, questo non lo fa
MSD
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.