分类目录归档:原创

用nginx测试AJAX接口

自从有了evernote后,好久没有更新这里了。打算日后把evernote记录的知识点陆续的搬上来。开始正题。

最近在做一个关于新闻推荐的内部项目,和之前的一些项目一样,也是富前端的应用,基本上都是后台提供数据接口,由前端这边完成页面的渲染。这次后台的接口多为json格式的。对比jsonp格式的数据,json格式只能用XHR的方式请求获取数据,在开发的时候就造成了跨域的问题。比如在开发时,页面的测试地址是htttp://localhost/page.html,而后台提供的接口地址是http://iread.ws.netease.com/article/reply,localhost和iread.ws.netease.com是两个不同的域,虽然高级的浏览器提供了XHR 2去解决跨域问题,但是老版本的IE不支持这个API,如果用XHR 2去实现的话,IE在开发时是没有办法测试到的,而且项目上线前还要将XHR 2改为XHR,这样就造成了不必要的工作量。最理想的解决办法就是在localhost做后台代理,将http://localhost/article/reply代理到http://iread.ws.netease.com/article/reply,这样我在请求数据接口的时候,只需要写相对路径就好了。比如在这个例子中,我直接请求/article/reply,在测试环境中就是请求http://localhost/article/reply,正式环境中变成请求http://iread.ws.netease.com/article/reply

做后台代理,最方便的就是用nginx了,只需要几行代码就能满足需求,配置的代码如下:

server {
	listen	*:80;

	location / {
		ssi	on;
		autoindex on;
		root  "/Users/Michael/制作/个性化新闻推荐/source";
		index  index.html index.htm;
	}

	location /article/reply {
		proxy_pass "http://iread.ws.netease.com/article/reply";
	}

}

这样我们请求http://localhost/article/reply的时候通过nginx的帮助就能从后台取到正确的数据了。但是问题又来了,http://iread.ws.netease.com/article/reply是一个需要cookie的接口,这就意味着nginx代理的时候需要将浏览器的cookie一同发送过去。浏览器向服务器发送cookie的时候,其实就是发送一个名为Cookie的request header。我的做法是打开浏览器,切换到firebug的“网络”选项卡,然后打开http://iread.ws.netease.com/article/reply,在“请求头信息”中将Cookie的值复制下来,然后加到nginx的配置节中,如下:

location /article/reply {
	proxy_pass "http://iread.ws.netease.com/article/reply";
	proxy_set_header Cookie 你刚才复制的内容;
}

白话Block Formatting Context

转载须写明出处,附带本文链接。关于文中的示例,用标准浏览器查看。

一,啥是Block Formatting Context

当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。

为了让我们有个感性的认识,举个不太合适的例子。你可以把一个页面想象成大的集装箱,这个集装箱里装的货物就是HTML元素。在现实生活中为了避免不同人的货物相互混淆,都是把货物打好包装再装入集装箱,这样的话无论你包装里面的货物怎么摆放,都不会影响到其他人的货物。那么这个包装就可以被想象成Block Formatting Context。

二,怎样才能形成Block Formatting Context

当一个HTML元素满足下面条件的任何一点,都可以产生Block Formatting Context

  • float的值不为none。
  • overflow的值不为visible。
  • display的值为table-cell, table-caption, inline-block中的任何一个。
  • position的值不为relative和static。

三,Block Formatting Context在生产中有什么作用

  1. Block Formatting Context可以阻止边距折叠(margin collapsing)。我们知道在一般情况下,两个上下相邻的盒子会折叠它们垂直方向接触到的边距,这种情况只会发生在同一个Block Formatting Context中。换句话说,在同一个布局环境中(Block Formatting Context)是边距折叠的必要条件。这也就是为什么浮动的元素和绝对定位元素不会发生边距折叠的原因(当然还有很多种情况也不会折叠)。

  2. Block Formatting Context可以包含内部元素的浮动。考虑一下下面的例子(请用标准浏览器查看):
    <!DOCTYPE html>
    <html>
    <head>
    	<title>Demo</title>
    	<style type="text/css">
    		html, body {
    			margin: 0;
    			padding: 0;
    		}
    		#red, #orange, #yellow, #green {
    			width: 100px;
    			height: 100px;
    			float: left;
    		}
    		#red {
    			background: red;
    		}
    		#orange {
    			background: orange;
    		}
    		#yellow {
    			background: yellow;
    		}
    		#green {
    			background: green;
    		}
    	</style>
    </head>
    <body>
    	<div id="c1">
    		<div id="red"></div>
    		<div id="orange"></div>
    	</div>
    	<div id="c2">
    		<div id="yellow"></div>
    		<div id="green"></div>
    	</div>
    </body>
    </html>

    在上面的代码本意是做一个两行两列的布局,但是由于#red, #orange, #yellow, #green这四个div同在一个布局环境中,即便通过#c1, #c2这两个div划分,浮动之后它们还会一个接着一个排列,并不会换行。我们要做的就是把这四个div两两划分到不同的布局环境之中,从而闭合浮动。通过上面的分析,让#c1形成新的Block Formatting Context就可以解决问题。

  3. Block Formatting Context可以阻止元素被浮动覆盖。请看示例:
    <!DOCTYPE html>
    <html>
    <head>
    	<title>Demo</title>
    	<style type="text/css">
    		html, body {
    			margin: 0;
    			padding: 0;
    		}
    		#left {
    			width: 100px;
    			height: 100px;
    			background: red;
    			float: left;
    		}
    		#right {
    			height: 200px;
    			background: yellow;
    		}
    	</style>
    </head>
    <body>
    	<div id="left"></div>
    	<div id="right"></div>
    </body>
    </html>

    在标准浏览器下可以看到,普通的#right元素被浮动的#left元素所覆盖了。要想避免这种情况,有一种方法就是让#right形成新的Block Formatting Context。但是这里一定要注意的是,浮动不会覆盖的只是Block Formatting Context的border-box。换句话说,形成Block Formatting Context元素的margin还是会被浮动所覆盖掉的。

如果想全面了解Block Formatting Context,请看CSS 101: Block Formatting Context这篇文章。

用CSS3做个好看的按钮(2)

转载须写明出处,附带本文链接。关于文中的示例,请用Firefox 3.6、Chrome 4.x、Safari 4.x查看。

点击查看演示

上一篇文章中提到了用CSS3的gradient做按钮,后来朋友指出HTML用的标签太多,趁着有空又仔细的看了下官方文档,上面说到Mozilla currently only supports CSS gradients as values of the background-image property, as well as within the shorthand background. You specify a gradient value instead of an image URL. 原来gradient是代替background-image的,那么就可以用gradient做遮罩,然后再用background-color设定按钮背景色,这样就可以去掉三个标签。代码如下:

.button {
	position: relative;
	width: 160px;
	height: 40px;
	line-height: 40px;
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	-moz-box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
	-webkit-box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
	box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
	
	background: -moz-linear-gradient(
		270deg,
		transparent,
		transparent 50%,
		rgba(0, 0, 0, .3) 50%				
	);
	background: -webkit-gradient(
		linear,
		left top,
		left bottom,
		from(transparent), 
		to(rgba(0, 0, 0, .3)),
		color-stop(.5 ,transparent),
		color-stop(.5 ,rgba(0, 0, 0, .3))
	);
}
.mask {			
	top: 1px;
	left: 1px;
	right: 1px;
	bottom: 1px;
	position: absolute;

	text-align: center;
	color: #FFF;
	text-decoration: none;
	
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	background: -moz-linear-gradient(
		270deg,
		rgba(117, 117, 117, .4),
		rgba(94, 94, 94, .4) 50%,
		transparent 50%
	);
	background: -webkit-gradient(
		linear,
		left top,
		left bottom,
		from(rgba(117, 117, 117, .4)), 
		to(transparent),
		color-stop(.5 ,rgba(94, 94, 94, .4)),
		color-stop(.5, transparent)
	);
	border: 1px solid rgba(255, 255, 255, .3);
	border-bottom-color: rgba(255, 255, 255, .1);
}

点击查看演示

用CSS3做个好看的按钮

转载须写明出处,附带本文链接。关于文中的示例,请用Firefox 3.6、Chrome 4.x、Safari 4.x查看。

在线观看演示

在网上看到了一篇文章Liquid & Color Adjustable CSS Buttons,感觉里面的那些按钮很漂亮,作者是用半透明的PNG图片当遮罩,来实现好看的按钮。可惜我对美工那些东西一窍不通,照着里面的教程做PNG图片,搞了很久才弄出来,汗。于是我就想,能不能用CSS3来实现类似的效果呢,那个图片有个渐变,然后加上半透明的效果。现在最新的WebKit和Gecko都支持渐变的背景,而半透明用opacity就搞定了。下面就开始动手,先从制作按钮的遮罩层开始。

既然是遮罩层,那么肯定是浮动在按钮上面的(绝对定位),这里用top、left、right、bottom来调整高度和宽度来遮住按钮,加上上面说的渐变和透明。我们将遮罩分为上下两个部分,上面的用渐变背景,下面的只要用纯色就可以了(其实用一个遮罩也可以实现,但是没有办法让遮罩的边框也渐变,所以用两个)。代码是这样的:

.mask-t, .mask-b {
	position: absolute;    
  -moz-box-sizing: border-box;
  -wekit-box-sizing: border-box;
  box-sizing: border-box;    
}
.mask-t {
	top: 1px;
	left: 1px;
  right: 1px;
  bottom: 50%;
  
	-moz-border-radius: 5px 5px 0 0;
	-webkit-border-radius: 5px 5px 0 0;
	border-radius: 5px 5px 0 0;  
  
	background: -moz-linear-gradient(270deg, 
    rgba(117, 117, 117, .4) 10%, 
    rgba(94, 94, 94, .4) 30%
  );
	background: -webkit-gradient(
		linear, 
		left top, 
		left bottom, 
		from(rgba(117, 117, 117, .4)), to(rgba(94, 94, 94, .4))
	);
    
  border: 1px solid rgba(255, 255, 255, .4);
  border-bottom: none;
}
.mask-b {
	top: 50%;
	left: 1px;
  right: 1px;
  bottom: 0;
  
	-moz-border-radius: 0 0 5px 5px;
	-webkit-border-radius: 0 0 5px 5px;
	border-radius: 0 0 5px 5px 0 0;  
  
  background: rgba(0, 0, 0, .3);
    
  border: 1px solid rgba(255, 255, 255, .3);
  border-top: none;
}

其实我也不是完全明白CSS3的gradient怎么用,怕讲错,所以这里就不解释了。做这个的时候,我是按照官方文档上的例子改的。

  1. Gecko的:https://developer.mozilla.org/index.php?title=en/CSS/-moz-linear-gradient
  2. WebKit的:http://webkit.org/blog/175/introducing-css-gradients/

OK,遮罩层已经做好了,接下来做按钮。按钮这个层要给遮罩提供定位,而且要设置按钮的大小、颜色,为了美观,我们给它加上圆角和阴影,这也是CSS3的内容。下面是代码:

.button {
	position: relative;
	background: red;
	width: 160px;
	height: 40px;
	line-height: 40px;
	
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	
	-moz-box-shadow:0 1px 3px rgba(0, 0, 0, .5);
	-webkit-box-shadow:0 1px 3px rgba(0, 0, 0, .5);
	box-shadow:0 1px 3px rgba(0, 0, 0, .5);
}

改变.button的background就可以给按钮换颜色了。注意按钮的border-radius要设置成和遮罩层的一样,我试图给按钮加上overflow: hidden然后去掉遮罩的border-radius,尽管这样,遮罩的四个角还是会显示出来,为什么会这样还请高手指点。接下来,就是按钮的文字部分了,这个层要处在遮罩层的上方以便清楚的显示出文字。和遮罩层一样,设置绝对定位,高宽都设为100%,由于我们的文字层在文档流里处在遮罩层的后面,所以就不用再设z-index了。代码如下:

.text {
	position: absolute;
	width: 100%;
	height: 100%;
	top: 0;
	left: 0;
	text-align: center;
	color: #FFF;
	text-decoration: none;
}

到这里,我们的按钮就做好了。这个按钮的优点是不用图片,减少了HTTP连接数,当然也减少了流量。缺点是,这个按钮现在还没什么用,因为IE到目前为止不支持CSS3,虽然有滤镜,但不如用图片来得快。在这里祝愿IE被早日淘汰。

在线观看演示

终极攻略——元素垂直居中

转载须写明出处,附带本文链接。文中提到的居中,如没有特别说明,均指垂直居中。

有的同学看到题目就会想:我把父元素设成display: table-cell; vertical-align: middle不就行了吗?很不幸,IE6下没有display: table-cell这个玩意,所以本攻略中一概不讨论上述方式实现的居中。本攻略中,要垂直居中的元素分以下三种情况:

  1. 块级元素
  2. 不可替换(non-replaced)的行元素
  3. 可替换(replaced)的行元素

如果上面说的概念不是很清楚,请参考一下w3的文档。

一,块级元素垂直居中。

因为是未知高度的块元素,通常来说没有办法用绝对定位的方式使它居中。最好的办法是把它变成行内块元素(display: inline-block),这样的话就变成了类似第三种情况:可替换的行元素垂直居中

二,不可替换的行元素垂直居中。

这种情况恐怕是最简单的了,比如:

<div style="height: 300px;line-height: 300px;">
  <span>我要垂直居中啊。</span>
</div>

只要把div的行高(line-height)设成高度(height)一样就可以了,span会自动补白(leading),占满div的高度,以达到垂直居中对齐的效果。这个方法对一行里有多个non-replaced inline elements的情况也是适用的。这里要注意,如果内容太长导致换行的话,这个方法就不适用了,碰到这种情况可以先把元素变为display: inline-block,然后再参考第三种情况:可替换的行元素垂直居中

三,可替换的行元素垂直居中。

如果出现这种情况:

<div style="height: 300px;line-height: 300px;">
  <span>我要垂直居中啊。</span>
  <span>我也要垂直居中。</span>
  <input type="text" />
</div>

上面的代码中,前两个span是不可替换元素,后面的input是可替换元素。在标准浏览器下看,一切正常,可是换到IE6下,情况就不同了,你会发现,这三个元素全都跑到上面去了。这是一个IE6的BUG,简单的说,如果一行中有某些可替换元素,那么IE6会把这一行上面的补白(half-leading)给去掉。如果你打算深入研究,请看http://www.positioniseverything.net/explorer/lineheightbug.html

方法一:

在上述情况下,如果你要兼容IE6,就不得不使用HACK,IE的CSS下面有个特殊的属性writing-mode,它可以改变流的书写方向,我们就用它来做这种垂直居中的事情。拿上面的例子来说,先给input加个容器(用行内元素,这样不会改变FF下的布局):

<div style="height: 300px;line-height: 300px;">
  <span>我要垂直居中啊。</span>
  <span>我也要垂直居中。</span>
  <span class="tmp"><input type="text" /></span>
</div>

然后针对IE6写HACK:

<!--[if IE 6]>
<style type="text/css">
  div .tmp {
    /* 这里的height要和外层容器的行高一致,
       如果内容只有一行的话,可以直接用height: 100% */
    height: 100%;
    writing-mode: tb-rl;
    text-align: center;
    vertical-align: middle;
  }
</style>
<![endif]-->

方法二:

这种居中方案,可以说是万能的。如果方法一可以解决问题,请尽量不要用此方法,毕竟增加了一个没有意义的空标签是很不爽的。

请看如下代码:

<div style="height: 400px;">
  <img src="http://www.xxxxxx.com/摄影作品1.jpg" alt="" />
</div>

上面的img元素是可替换元素,它有固有的高度和宽度(由图片大小决定)。就目前的布局来说,vertical-align对它还不能起到居中对齐的作用,因为它没有占满父级div所有的高度。有的同学就说了:好办,我给img来个line-height。这样是不行的,因为它是可替换元素。难道没有办法了吗?有的,我们知道一行在屏幕上实际占有的高度,是由这行里最高的行级元素决定的(还有多种决定因素),而其它比较矮的行元素通过设置vertical-align: middle就会在这行里垂直居中对齐。通过上一点分析,我们就在img的后面加上一个空的行级元素,让它占满div的高度。这个任务交给inline-block级别的元素完成,因为它可以设高度,而且又是行布局。完整代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
	<title>垂直居中</title>
	<style type="text/css">
	#container {		
		border: 1px solid black;
		text-align: center;
		height: 500px;
	}
	#container b {
		display: inline-block;
		height: 100%;
		vertical-align: middle;
	}
	</style>
</head>
<body>
	<div id="container">
	  <img src="http://img1.cache.netease.com/img09/logo/logo.gif" alt="logo" />
	  <b></b>
	</div>
</body>
</html>

这种方法也适合一行中同时出现non-replaced elements和replaced elements的情况。