Как применить CSS к iframe?
У меня есть простая страница, которая имеет несколько разделов iframe (для отображения ссылок RSS). Как применить тот же формат CSS с главной страницы к странице, отображаемой в iframe?
29 ответов
Редактировать: Это не работает кросс-домен, если не установлен соответствующий заголовок CORS.
Здесь есть две разные вещи: стиль блока iframe и стиль страницы, встроенной в iframe. Вы можете установить стиль блока iframe обычным способом:
<iframe name="iframe1" id="iframe1" src="empty.htm"
frameborder="0" border="0" cellspacing="0"
style="border-style: none;width: 100%; height: 120px;"></iframe>
Стиль страницы, встроенной в iframe, должен быть установлен путем включения его в дочернюю страницу:
<link type="text/css" rel="Stylesheet" href="Style/simple.css" />
Или его можно загрузить с родительской страницы с помощью Javascript:
var cssLink = document.createElement("link");
cssLink.href = "style.css";
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
frames['iframe1'].document.head.appendChild(cssLink);
Я столкнулся с этой проблемой в Календаре Google. Я хотел стилизовать его на более темном фоне и изменить шрифт.
К счастью, URL из встраиваемого кода не имеет ограничений на прямой доступ, поэтому с помощью функции PHP file_get_contents
можно получить весь контент со страницы. Вместо того, чтобы называть Google URL, можно вызвать php-файл, расположенный на вашем сервере, например. google.php
, который будет содержать оригинальный контент с изменениями:
$content = file_get_contents('https://www.google.com/calendar/embed?src=%23contacts%40group.v.calendar.google.com&ctz=America/Montreal');
Добавление пути к вашей таблице стилей:
$content = str_replace('</head>','<link rel="stylesheet" href="http://www.yourwebsiteurl.com/google.css" /></head>', $content);
(Это сделает вашу таблицу стилей последней перед head
конец тега.)
Укажите базовый URL-адрес из исходного URL-адреса в случае, если css и js называются относительно:
$content = str_replace('</title>','</title><base href="https://www.google.com/calendar/" />', $content);
Финал google.php
файл должен выглядеть так:
<?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;
Затем вы меняете iframe
вставлять код в:
<iframe src="http://www.yourwebsiteurl.com/google.php" style="border: 0" width="800" height="600" frameborder="0" scrolling="no"></iframe>
Удачи!
Если содержимое iframe не полностью находится под вашим контролем или вы хотите получить доступ к содержимому с разных страниц с разными стилями, вы можете попробовать манипулировать им с помощью 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);
Обратите внимание, что в зависимости от того, какой браузер вы используете, это может работать только на страницах, обслуживаемых из того же домена.
var $head = $("#eFormIFrame").contents().find("head");
$head.append($("<link/>", {
rel: "stylesheet",
href: url,
type: "text/css"
}));
Вот как применить код CSS напрямую без использования <link>
загрузить дополнительную таблицу стилей.
var head = jQuery("#iframe").contents().find("head");
var css = '<style type="text/css">' +
'#banner{display:none}; ' +
'</style>';
jQuery(head).append(css);
Это скрывает баннер на странице iframe. Спасибо вам за ваши предложения!
В большинстве браузеров iframe универсально обрабатывается как другая HTML-страница. Если вы хотите применить ту же таблицу стилей к содержимому iframe, просто ссылайтесь на нее со страниц, используемых там.
Если вы управляете страницей в iframe, как сказал Hangy, самый простой подход - создать общий CSS-файл с общими стилями, а затем просто дать ссылку на него со своих html-страниц.
В противном случае маловероятно, что вы сможете динамически изменять стиль страницы с внешней страницы в вашем фрейме. Это связано с тем, что браузеры ужесточили меры безопасности для межкадровых сценариев из-за возможного неправильного использования для подмены и других хаков.
Этот учебник может предоставить вам больше информации о скриптовых фреймах в целом. О межкадровом сценарии объясняются ограничения безопасности с точки зрения IE.
Выше с небольшим изменением работает:
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);
Отлично работает с ff3 и ie8 как минимум
Следующее сработало для меня.
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();
Расширение на вышеупомянутое решение jQuery, чтобы справиться с любыми задержками в загрузке содержимого кадра.
$('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();
});
Использование может попробовать это:
$('iframe').load( function() {
$('iframe').contents().find("head")
.append($("<style type='text/css'> .my-class{display:none;} </style>"));
});
Если вы хотите повторно использовать CSS и JavaScript с главной страницы, возможно, стоит подумать о замене <IFRAME>
с загруженным контентом Ajax. Это более оптимизировано для SEO, когда поисковые роботы могут выполнять JavaScript.
Это пример jQuery, который включает другую HTML-страницу в ваш документ. Это гораздо более дружественный SEO, чем iframe
, Чтобы убедиться, что боты не индексируют включенную страницу, просто добавьте ее, чтобы запретить в robots.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>
Вы также можете включить jQuery непосредственно из Google: http://code.google.com/apis/ajaxlibs/documentation/ - это означает необязательное автоматическое включение более новых версий и значительное увеличение скорости. Кроме того, это означает, что вы должны доверять им за то, что они предоставили вам только jQuery;)
Поскольку для одних и тех же доменов написано много ответов, я напишу, как это сделать в кросс-доменах.
Во-первых, вам нужно знать API сообщений. Нам нужен мессенджер для связи между двумя окнами.
Вот созданный мной мессенджер.
/**
* 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);
}
}
Использование этого в двух окнах для общения может решить вашу проблему.
В главных окнах
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
})
Затем получите событие от iframe.
В 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);
}
})
См. Подробное руководство по полному Javascript и iframe.
Моя компактная версия:
<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>
Однако иногда iframe
не готов к загрузке окна, поэтому необходимо использовать таймер.
Готовый код (с таймером):
<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>
... и ссылка JQuery:
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
Другие ответы здесь, кажется, используют ссылки jQuery и CSS.
Этот код использует ванильный JavaScript. Это создает новый <style>
элемент. Он устанавливает текстовое содержимое этого элемента как строку, содержащую новый CSS. И он добавляет этот элемент непосредственно в заголовок документа 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);
Когда вы говорите "doc.open()", это означает, что вы можете написать любой тег HTML внутри iframe, поэтому вы должны написать все основные теги для страницы HTML, и если вы хотите иметь ссылку CSS в вашей голове iframe, просто напишите iframe со ссылкой на CSS Я приведу вам пример:
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="/css/print.css"/></head><body><table id="' + gridId + 'Printable' + '" class="print" >' + out + '</table></body></html>');
doc.close();
Вы не сможете стилизовать содержимое iframe таким образом. Я бы предложил использовать серверные сценарии (PHP, ASP или Perl) или найти онлайн-сервис, который преобразует канал в код JavaScript. Единственный другой способ сделать это, если вы можете включить серверное включение.
Если у вас есть доступ к странице iframe и вы хотите, чтобы другой CSS применялся к ней только тогда, когда вы загружаете ее через iframe на своей странице, здесь я нашел решение для такого рода вещей.
это работает, даже если iframe загружает другой домен
проверить о postMessage()
план, отправьте css в iframe как сообщение
iframenode.postMessage('h2{color:red;}','*');
*
отправить это сообщение независимо от того, в каком домене оно находится в iframe
и получите сообщение в iframe и добавьте полученное сообщение (CSS) в заголовок документа.
код для добавления на страницу iframe
window.addEventListener('message',function(e){
if(e.data == 'send_user_details')
document.head.appendChild('<style>'+e.data+'</style>');
});
Вот как я делаю в производстве. Стоит иметь в виду, что если iframe принадлежит другому веб-сайту, он вызовет ошибку CORS и не будет работать.
var $iframe = document.querySelector(`iframe`);
var doc = $iframe.contentDocument;
var style = doc.createElement("style");
style.textContent = `*{display:none!important;}`;
doc.head.append(style);
В некоторых случаях вы также можете захотеть прикрепить
load
событие в iframe:
var $iframe = document.querySelector(`iframe`);
$iframe.addEventListener("load", function() {
var doc = $iframe.contentDocument;
var style = doc.createElement("style");
style.textContent = `*{display:none!important;}`;
doc.head.append(style);
});
Я нашел другое решение, чтобы поместить стиль в основной HTML, как это
<style id="iframestyle">
html {
color: white;
background: black;
}
</style>
<style>
html {
color: initial;
background: initial;
}
iframe {
border: none;
}
</style>
а затем в iframe сделать это (см. JS Onload)
<iframe onload="iframe.document.head.appendChild(ifstyle)" name="log" src="/upgrading.log"></iframe>
и в JS
<script>
ifstyle = document.getElementById('iframestyle')
iframe = top.frames["log"];
</script>
Возможно, это не лучшее решение, и, безусловно, его можно улучшить, но это еще один вариант, если вы хотите сохранить тег "style" в родительском окне.
Мы можем вставить тег стиля в iframe. Размещено также здесь...
<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>
Я думаю, что самый простой способ - это добавить еще один div, в том же месте, что и iframe, тогда
сделать его z-index
больше, чем контейнер iframe, так что вы можете просто оформить свой собственный div. Если вам нужно нажать на нее, просто используйте pointer-events:none
на ваш собственный div, так что iframe будет работать, если вам нужно нажать на него;)
Надеюсь, это кому-нибудь поможет;)
Здесь есть две вещи внутри домена
- Раздел iFrame
- Страница загружена внутри рамки
Итак, вы хотите оформить эти два раздела следующим образом:
1. Стиль для раздела iFrame
Это может стилизовать использование CSS с этим уважаемым id
или же class
название. Вы можете просто стилизовать его в родительских таблицах стилей.
<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. Стиль страницы, загруженной в iFrame
Эти стили могут быть загружены с родительской страницы с помощью Javascript
var cssFile = document.createElement("link")
cssFile.rel = "stylesheet";
cssFile.type = "text/css";
cssFile.href = "iFramePage.css";
затем установите этот CSS-файл в соответствующий раздел iFrame
//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);
Здесь вы также можете редактировать заголовок страницы внутри iFrame также
var $iFrameHead = $("#my_iFrame").contents().find("head");
$iFrameHead.append(
$("<link/>",{
rel: "stylesheet",
href: urlPath,
type: "text/css" }
));
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) установить ссылку iframe с помощью style
параметр, как:
http://your_site.com/target.php?style=a%7Bcolor%3Ared%7D
(последняя фраза a{color:red}
кодируется urlencode
функция.
2) установить страницу получателя target.php
как это:
<head>
..........
<style><? echo urldecode($_GET['style']);?> </style>
..........
Существует замечательный сценарий, который заменяет узел самой версией iframe. CodePen Demo
Примеры использования:
// 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">'
});
В качестве альтернативы вы можете использовать технологию CSS-in-JS, как показано ниже: lib:
https://github.com/cssobj/cssobj
Он может внедрить JS-объект как CSS в iframe, динамически
Начиная с HTML 5, изменение CSS фреймов является нарушением политики безопасности контента.
Вот хитрость, как вы все еще можете это сделать:
CSS начинается через 1 секунду. Если это не сработает, вам нужно увеличить таймер.
Ну, я следовал за этими шагами:
- Div с классом для проведения
iframe
- добавлять
iframe
кdiv
, - В файле CSS
divClass { width: 500px; height: 500px; }
divClass iframe { width: 100%; height: 100%; }
Это работает в IE 6. Должно работать в других браузерах, проверьте!