<iframe>元素会创建包含另外一个文档的内联框架(即行内框架);
一、align 属性(不赞成)
align属性规定iframe相对于周围元素的水平和垂直对齐方式,因为iframe元素是行内元素,即不会在页面上插入新行,这意味着文本和其他元素可以围绕在其周围,所以align属性可以规定iframe相对于周围元素的对齐方式;
二、frameborder属性
frameborder属性规定是否显示iframe周围的边框,但出于实用性方面的原因,最好不用设置该属性,而使用CSS来设置边框,是否显示边框:1(yes),0(no);
<html>
<body>
<iframe src ="/index.html" width="400" height="300" frameborder="0">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
三、height 属性
规定 iframe 的高度;
<html>
<body>
<iframe src ="/index.html" width="400px" height="500px">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
四、marginheight 属性
规定 iframe 的顶部和底部的空白边距,以像素计;
<html>
<body>
<iframe src ="/example/html/demo_iframe.html" marginheight="50px"
width="400px" height="300px">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
五、marginwidth 属性
规定 iframe 的左边和右边的空白边距,以像素计;
<html>
<body>
<iframe src ="/example/html/demo_iframe.html" marginwidth="50px"
width="400px" height="300px">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
六、name 属性
规定 iframe 的名称,iframe 元素的 name 属性用于在 JavaScript 中引用元素,或者作为链接的目标;
<html>
<body>
<iframe src="/example/html/demo_iframe.html" name="iframe_a">
<p>Your browser does not support iframes.</p>
</iframe>
<a href="http://www.w3school.com.cn" target="iframe_a">W3School.com.cn</a>
</body>
</html>
七、sandbox属性
如果被规定为空字符串(sandbox=""),sandbox 属性将会启用一系列对行内框架中内容的额外限制,sandbox 属性的值既可以是一个空字符串(应用所有的限制),也可以是空格分隔的预定义值列表(将移除特定的限制);
- "":应用以下所有的限制;
- allow-same-origin:允许 iframe 内容被视为与包含文档有相同的来源;
- allow-top-navigation:允许 iframe 内容从包含文档导航(加载)内容;
- allow-forms:允许表单提交;
- allow-scripts:允许脚本执行;
<!DOCTYPE html>
<html>
<body>
<iframe src="/demo/demo_iframe_sandbox.html" sandbox="">
<p>Your browser does not support iframes.</p>
</iframe>
<p>"获得日期和时间" 按钮会在行内框架中运行一段脚本。</p>
<p>由于 sandbox 属性被设置为空字符串 (""),行内框架的内容不允许运行脚本。</p>
<p>如果向 sandbox 属性添加 "allow-scripts",则允许运行 JavaScript。</p>
<p><b>注释:</b>IE 9 以及更早的版本不支持 sandbox 属性,Opera 12 以及更早的版本也不支持该属性。</p>
</body>
</html>
八、scrolling 属性
规定是否在 iframe 中显示滚动条,默认地,如果内容超出了 iframe,滚动条就会出现在 iframe 中;
- auto:在需要的情况下出现滚动条(默认值);
- yes:始终显示滚动条(即使不需要);
- no:从不显示滚动条(即使需要);
<html>
<body>
<h3>iframe 中始终显示滚动条:</h3>
<iframe src ="/index.html" width="200" height="200" scrolling="yes">
<p>Your browser does not support iframes.</p>
</iframe>
<h3>iframe 中从不显示滚动条:</h3>
<iframe src ="/index.html" width="200" height="200" scrolling="no">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
九、seamless 属性
属于逻辑属性,当设置该属性后,它规定了 <iframe> 看上去像是包含文档的一部分(无边框或滚动条);
<!DOCTYPE html>
<html>
<body>
<p>这是一个段落。</p>
<iframe src="/demo/demo_iframe.html" seamless></iframe>
<p><b>注释:</b>Opera、Chrome 以及 Safari 支持 seamless 属性。</p>
</body>
</html>
十、src 属性
规定在 iframe 中显示的文档的 URL;
- 绝对 URL:指向其他站点(比如 src="www.example.com/index.html");
- 相对 URL:指向站点内的文件(比如 src="index.html");
<html>
<body>
<iframe src ="/index.html">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
十一、srcdoc 属性
规定页面的 HTML 内容显示在行内框架中,该属性与 sandbox 和 seamless 属性一同使用,如果浏览器不支持 srcdoc 属性,则相应地会显示在 src 属性(若已设置)中规定的文件;
<!DOCTYPE html>
<html>
<body>
<iframe srcdoc="<p>Hello world!</p>" src="/demo/demo_iframe_srcdoc.html">
<p>Your browser does not support iframes.</p>
</iframe>
<p><b>注释:</b>所有主流浏览器都支持 srcdoc 属性,除了 Internet Explorer。</p>
</body>
</html>
十二、width 属性
规定 iframe 的宽度;
<html>
<body>
<iframe src ="/index.html" width="400px" height="300px">
<p>Your browser does not support iframes.</p>
</iframe>
</body>
</html>
十三、iframe的基本特性
通常使用Iframe最基本的特性,就是能自由操作iframe和父框架的内容(DOM),但前提条件是同域,如果跨域顶多只能实现页面跳转window.location.href;
A:<iframe id="mainIframe" name="mainIframe" src="/main.html" frameborder="0" scrolling="auto" ></iframe>
B:<iframe id="mainIframe" name="mainIframe" src="http://www.baidu.com" frameborder="0" scrolling="auto" ></iframe>
使用A时,因为同域,父页面可以对子页面进行改写,反之亦然;
使用B时,不同域,父页面没有权限改动子页面,但可以实现页面的跳转;
十四、获取iframe里的内容
iframe.contentWindow:获取iframe的window对象;
iframe.contentDocument:获取iframe的document对象;
这两个API只是DOM节点提供的方式(即getELement系列对象)
var iframe = document.getElementById("iframe1");
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
console.log("window",iwindow);//获取iframe的window对象
console.log("document",idoc); //获取iframe的document
console.log("html",idoc.documentElement);//获取iframe的html
console.log("head",idoc.head); //获取head
console.log("body",idoc.body); //获取body
<iframe src ="/index.html" id="ifr1" name="ifr1" scrolling="yes">
<p>Your browser does not support iframes.</p>
</iframe>
<script type="text/javascript">
console.log(window.frames['ifr1'].window);
console.dir(document.getElementById("ifr1").contentWindow);
</script>
十五、在iframe中获取父级内容
在同域下,子iframe同样也能操作父页面内容,在iframe中,可以通过在window上挂载的几个API进行获取;
window.parent:获取上一级的window对象,如果还是iframe则是该iframe的window对象;
window.top:获取最顶级容器的window对象,即打开页面的文档;
window.self:返回自身window的引用,可以理解为window===window.self;
十六、iframe的轮询
之前的网页可以使用iframe实现异步发送请求;
ajax的长轮询是在ajax的readyState=4时再次执行原函数,这里使用iframe也是一样,异步创建iframe,然后reload,和后台协商好,看后台返回的信息放在哪,然后获取里面的信息即可,这里是直接放在body里;
var iframeCon = docuemnt.querySelector('#container'),text; //传递的信息
var iframe = document.createElement('iframe'),
iframe.id = "frame",
iframe.style = "display:none;",
iframe.name="polling",
iframe.src="target.html";
iframeCon.appendChild(iframe);
iframe.onload= function(){
var iloc = iframe.contentWindow.location,
idoc = iframe.contentDocument;
setTimeout(function(){
text = idoc.getElementsByTagName('body')[0].textContent;
console.log(text);
iloc.reload(); //刷新页面,再次获取信息,并且会触发onload函数
},2000);
}
十七、自适应iframe之蜜汁广告
通常使用iframe在页面引入广告,因为广告一般是与页面内容不相关的,如果使用div在页面中嵌套,会造成网页内容的紊乱,而且这样势必需要引入额外的css和js,极大的降低了网页的安全性,因此需要使用iframe来插入广告,我们可以将iframe理解为一个沙盒,里面的内容能够被top window完全控制,而且主页的css样式是不会入侵iframe里面的样式,这些都给iframe的广告命运埋下伏笔,默认情况下,iframe是不适合做展示信息的,需要对其进行decorate;
自适应iframe
第一步:默认情况下,iframe会自带滚动条,不会全屏,如果想自适应iframe,需要去掉滚动条;
<iframe src="./iframe1.html" id="iframe1" scrolling="no"></iframe>
第二步:设置iframe的高为body的高;
var iwindow = iframe.contentWindow;
var idoc = iwindow.document;
iframe.height = idoc.body.offsetHeight;
此外,还可以添加其他的装饰属性:
1)allowtransparency:true or false,是否允许iframe设置为透明,默认为false;
2)allowfullscreen:true or false,是否允许iframe全屏,默认为false;
// 样式可以直接写在内联样式里面,也可以在css里面定义,不过对于广告iframe来说,样式写在属性中,是best pratice;
<iframe id="google_ads_frame2" name="google_ads_frame2" width="160" height="600" frameborder="0" src="target.html" marginwidth="0" marginheight="0" vspace="0" hspace="0" allowtransparency="true" scrolling="no" allowfullscreen="true"></iframe>
十八、iframe安全性探索
iframe出现安全性有两个方面,一是你的网页被别人iframe;二是你iframe别人的网页;当你的网页被别人iframe时,可能容易被钓鱼网站利用,为了防止页面被一些不法分子利用,我们需要做好安全性措施;
防嵌套网页
比如clickhacking就是使用iframe来拦截click事件,因为iframe享受着click的最优先权,当有人在伪造的主页中进行点击的话,如果点在iframe上,则会默认是在操作iframe的页面,所以钓鱼网站就是使用这个技术,通过诱导用户进行点击,比如设计一个“妹妹寂寞了”等之类的网页,诱导用户点击,但实际结果,看到的不是“妹妹”,而是被恶意微博吸粉,所以为了防止网站被钓鱼,可以使用window.top来防止网页被iframe;
//iframe2.html
// 限定你的网页不能嵌套在任意网页内
if(window != window.top){
window.top.location.href = correctURL;
}
这段代码的主要用途是限定你的网页不能嵌套在任意网页内。如果你想引用同域的框架的话,可以判断域名。
// 如果想引用同域的框架的话,可以判断域名,如果不同域的话,上述内容会报错
if (top.location.host != window.location.host) {
top.location.href = window.location.href;
}
所以,这里可以使用try...catch...进行错误捕获。如果发生错误,则说明不同域,表示你的页面被盗用了。可能有些浏览器这样写是不会报错,所以需要降级处理。
这时候再进行跳转即可.
// 使用try...catch...进行错误捕获,如果发生错误,则说明不同域,表示页面被盗用了
try{
top.location.hostname; //检测是否出错
//如果没有出错,则降级处理
if (top.location.hostname != window.location.hostname) {
top.location.href =window.location.href;
}
} catch(e){
top.location.href = window.location.href;
}
X-Frame-Options
X-Frame-Options是一个相应头,主要是描述服务器的网页资源的iframe权限,其实就是将前端js对iframe的把控权交给服务器来进行处理:
- X-Frame-Options: DENY:拒绝任何iframe的嵌套请求;
- X-Frame-Options: SAMEORIGIN:只允许同源请求,例如网页为 foo.com/123.php,則 foo.com 底下的所有网页可以嵌入此网页,但是 foo.com 以外的网页不能嵌入;
- X-Frame-Options: ALLOW-FROM http://s3131212.com:只允许指定网页的iframe请求,不过兼容性较差,Chrome不支持;
//js
if(window != window.top){
window.top.location.href = window.location.href;
} //等价于
X-Frame-Options: DENY //js
if (top.location.hostname != window.location.hostname) {
top.location.href =window.location.href;
} //等价于
X-Frame-Options: SAMEORIGIN</pre>
X-Frame-Options属性是对页面的iframe进行的一个主要限制,不过涉及iframe的header可不止这一个,另外还有一个Content Security Policy,他同样也可以对iframe进行限制,而且他应该是未来网页安全防护的主流;
CSP之页面防护
和X-Frames-Options一样,都需要在服务端设置好相关的Header,CSP能够极大的防止页面被XSS攻击,而且可以制定js,css,img等相关资源的origin,防止被恶意注入,不过兼容性不好;
使用主要是在后端服务器上配置,在前端可以观察Response Header里是否有这样一个Header:
Content-Security-Policy: default-src 'self'
通常我们可以在CSP后配置各种指定资源路径,有
- default-src,
- script-src,
- style-src,
- img-src,
- connect-src,
- font-src,
- object-src,
- media-src,
- sandbox,
- child-src,
- ...
如果未指定的话,会默认使用default-src规定的加载策略,默认配置就是同域: default-src "self";这里还和iframe有一点瓜葛的就是child-src 和 sandbox,child-src就是用来指定iframe的有效加载路径,其实和X-Frame-Options中配置allow-origin是一个道理,不过allow-origin没有得到厂商的支持,而sandbox其实就和iframe的sandbox属性是一样的,他可以规定来源能够带有什么权限;
Content-Security-Policy: child-src 'self' http://example.com; sandbox allow-forms allow-same-origin</pre>
此时iframe的src就只能加载同域和example.com页面,最后再补充一点:使用CSP能够很好的防止XSS攻击,原理就是CSP会默认escape掉内联样式和脚本以及eval执行,可以使用srcipt-src进行降低限制;
Content-Security-Policy: script-src 'unsafe-inline'
当然我们面临的安全总量还有一个,就是当iframe别人的页面时,我们需要对其进行安全设限,虽然跨域时iframe的安全性会大很多,但是互联网没有安全的地方,H5提供的新属性sandbox可以很好的解决这个问题;
sandbox
sandbox就是用来给指定的iframe设置一个沙盒模型来限制iframe的更多权限,sandbox是H5的一个新属性;
// 这样就可以对iframe页面进行一系列的限制
<iframe sandbox src="..."></iframe>
可以进行如下操作:
- script脚本不能执行;
- 不能发送ajax请求;
- 不能使用本地存储,即localStorage,cookie等;
- 不能创建新的弹窗和window;
- 不能发送表单;
- 不能加载额外插件比如flash等;
常用的配置项有:
配置 | 效果 |
---|---|
allow-forms | 允许进行提交表单 |
allow-scripts | 运行执行脚本 |
allow-same-origin | 允许同域请求,比如ajax,storage |
allow-top-navigation | 允许iframe能够主导window.top进行页面跳转 |
allow-popups | 允许iframe中弹出新窗口,比如,window.open,target="_blank" |
allow-pointer-lock | 在iframe中可以锁定鼠标,主要和鼠标锁定有关 |
// 这样可以保证js脚本的执行,但是禁止iframe里的javascript执行top.location = self.location
<iframe sandbox="allow-forms allow-same-origin allow-scripts" src="..."></iframe>
resolve iframe跨域
iframe就是一个隔离沙盒,相当于我们在一个页面内可以操控很多个标签页一样,如果踩坑的童鞋应该知道,iframe也可以解决跨域;
iframe可以解决二级域名跨域的情况,即主域相同而子域不同的情况,在两个不同子域下(某一方使用iframe嵌套在另一方):
// 两个文件中分别加上document.domain = ‘foo.com’,指定相同的主域
// 然后,两个文档就可以进行交互了
http: //www.foo.com/a.html
http: //script.foo.com/b.html
//b.html是以iframe的形式嵌套在a.html中
//www.foo.com上的a.html
document.domain = 'foo.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://script.foo.com/b.html';
ifr.style.display = 'none';
document.body.appendChild(ifr);
ifr.onload = function(){
var doc = ifr.contentDocument || ifr.contentWindow.document;
// 在这里操纵b.html
alert(doc.getElementsByTagName("h1")[0].childNodes[0].nodeValue);
};
//script.foo.com上的b.html
document.domain = 'foo.com';
默认情况下document.domain 是指window.location.hostname, 你可以手动更改,但是最多只能设置为主域名,通常,主域名就是指不带www的hostname, 比如: foo.com , baidu.com , 如果带上www或者其他的前缀,就是二级域名或者多级域名,通过上述设置,相同的domain之后,就可以进行同域的相关操作;
H5的CDM跨域与iframe
如果设置的iframe域名和top window域名完全不同,则可以使用CDM(cross document messaging)进行跨域消息的传递;
发送消息:使用postmessage方法;
接收消息:监听message事件;
postmessage
该方法挂载到window对象上,即使用window.postmessage()调用,该方法接受两个参数:postMessage(message, targetOrigin)
- message:就是传递给iframe的内容,通常是string,如果想传object对象也可以,但如果有条件,可以使用JSON.stringify进行转化,这样保证不会出bug;
- targetOrigin:接受你传递消息的域名,可以设置绝对路径,也可以设置"*"或者"/", *表示任意域名都行,"/"表示只能传递给同域域名;
<iframe src="http://tuhao.com" name="sendMessage"></iframe>
//当前脚本
let ifr = window.frames['sendMessage'];
//使用iframe的window向iframe发送message。
ifr.postmessage('give u a message', "http://tuhao.com");
//tuhao.com的脚本
window.addEventListener('message', receiver, false);
function receiver(e) {
if (e.origin == 'http://tuhao.com') {
if (e.data == 'give u a message') {
e.source.postMessage('received', e.origin); //向原网页返回信息
} else {
alert(e.data);
}
}
}
当targetOrigin接收到message消息之后,,会触发message事件,message提供的event对象上有3个重要的属性,data,origin,source:
data:postMessage传递进来的值;
origin:发送消息的文档所在的域;
source:发送消息文档的window对象的代理,如果是来自同一个域,则该对象就是window,可以使用其所有方法,如果是不同的域,则window只能调用postMessage()方法返回信息
十九、<frameset>和<iframe>的区别
- iframe 和 frameset 都用于html页面的框架布局;
- <iframe>:iframe 是个内联框架,是在页面里生成个内部框架;
<frameset >:frameset 定义一个框架集,包含多个子框架,每个框架都有独立的文档;
<html>
<frameset cols="25%,50%,25%">
<frame src="frame_a.htm" />
<frame src="frame_b.htm" />
<frame src="frame_c.htm" />
</frameset>
</html>
- frame不能脱离frameSet单独使用,iframe可以;
- frame不能放在body中:
// 如下可以正常显示
<!--<body>-->
<frameset rows="50%,*">
<frame name="frame1" src="test1.htm"/>
<frame name="frame2" src="test2.htm"/>
</frameset>
<!--<body>-->
// 如下不能正常显示:
<body>
<frameset rows="50%,*">
<frame name="frame1" src="test1.htm"/>
<frame name="frame2" src="test2.htm"/>
</frameset>
<body>
- 嵌套在frameSet中的iframe必须放在body中:
// 如下可以正常显示:
<body>
<frameset>
<iframe name="frame1" src="test1.htm"/>
<iframe name="frame2" src="test2.htm"/>
</frameset>
</body>
// 如下不能正常显示:
<!--<body>-->
<frameset>
<iframe name="frame1" src="test1.htm"/>
<iframe name="frame2" src="test2.htm"/>
</frameset>
<!--</body>-->
- 不嵌套在frameSet中的iframe可以随意使用;
// 如下均可以正常显示:
<body>
<iframe name="frame1" src="test1.htm"/>
<iframe name="frame2" src="test2.htm"/>
</body>
<!--<body>-->
<iframe name="frame1" src="test1.htm"/>
<iframe name="frame2" src="test2.htm"/>
<!--</body>-->
- frame的高度只能通过frameSet控制,iframe可以自己控制,不能通过frameSet控制,如:
<!--<body>-->
<frameset rows="50%,*">
<frame name="frame1" src="test1.htm"/>
<frame name="frame2" src="test2.htm"/>
</frameset>
<!--</body>-->
<body>
<frameset>
<iframe height="30%" name="frame1" src="test1.htm"/>
<iframe height="100" name="frame2" src="test2.htm"/>
</frameset>
</body>
如果在同一个页面使用了两个以上的iframe:
IE中可以正常显示,在firefox中只能显示出第一个,使用两个以上的frame在IE和firefox中均可正常显示;frame与iframe两者可以实现的功能基本相同,不过Iframe比frame具有更多的灵活性, frame是整个页面的框架,iframe是内嵌的网页元素,也可以说是内嵌的框架 :
iframe标记又叫浮动帧标记,可以用它将一个HTML文档嵌入在一个HTML中显示,它和frame标记的最大区别是在网页中嵌入的<iframe></iframe>所包含的内容与整个页面是一个整体,而<frame></frame>所包含的内容是一个独立的个体,是可以独立显示的,另外,应用iframe还可以在同一个页面中多次显示同一内容,而不必重复这段内容的代码;iframe 可以放到表格里面,frame 则不行;
<table>
<tr>
<td><iframe id="" src=""></iframe></td><td></td>
</tr>
</table>
frame必须在frameset里,而frameset不能与body元素共存,也就说有frameset元素的文档只能是一个框架集,不能有别的东西;
iframe放在网页的什么地方都行,但是frame只能放到上下左右四个方向;
iframe是活动帧,而frame是非活动帧:
// iframe使用方法如下
<iframe scr="sourcefile" frameborder=0 width="width" height="height"></iframe>
iframe用起来更灵活,不需要frame那么多讲究,而且放的位置也可以自己设, iframe是内嵌的,不过也有不好的地方,就是位置在不同的浏览器和分辨率下有可能不同,有时会把本来好好的页面搞得变形;
iframe可以加在网页中任何一个地方,而frame通常做框架页,iframe是一个网页中的子框架,两网页间是父子关系,frame是框架,由多个并列的网页构成;
iframe是浮动的,就像是浮动面板,而frame是固定的,只能四个方向上的;
<iframe>是被嵌入在网页的元素,而<frame>用于组成一个页面的多个框架,iframe更利于版面的设计,frame一条直一条竖的不美观,frame的那一条线也可以去掉的呦!只不过,iframe更方便对其进行数据的交换吧!
iframe可以放置到你想放的任意位置,控制起来比frame方便;iframe是内部帧,可以嵌在一个页面里面,设置内部帧的属性可以使得整体看上去像是一个完整的页面,而不是由多个页面组成,frame有frame的好处,比如更多网站,上面放广告条,左边放菜单,右边放内容,这样上边和左边的内容都可不动,只刷新右边页面的内容,选择iframe还是frame完全看自己的需求;
用iframe比用frame少一个文件(frameSet),但支持frame的浏览器比较多;
iframe可以放在表格里,然后ifame设置成width=100%,height=100%,这样就可以只需修改表格的宽度和高度,有利于排版 ;
其实frame是一个控件,使用方法和Panle相同;
frame是把网页分成多个页面的页面。它要有一个框架集页面frameset,iframe是一个浮动的框架,就是在你的页面里再加上一个页面;
<frame>用来把页面横着或竖着切开,<iframe>用来在页面中插入一个矩形的小窗口;
frame一般用来设置页面布局,将整个页面分成规则的几块,每一块里面包含一个新页面,iframe用来在页面的任何地方插入一个新的页面,因此,frame用来控制页面格式,比如一本书,左边是章节目录,右边是正文,正文很长,看的时候要拖动,但又不想目录也被拖动得看不到了,因此最好将页面用frame分成规则的2页,一左一右;而iframe则更灵活,不要求将整个页面划分,可以在页面任何地方用iframe嵌入新的页面;
<frame>用于全页面;
<iframe>只用于局部;