web页面响应布局

原文 by zhangxinxu from http://www.zhangxinxu.com

 

我一直有一个想法就是把张鑫旭的所有文章弄到我的博客园上,但是想法一直存在,一直都在,行动越迟迟不肯配合,有那么一句话,没有行动的计划只会毁了你,亲,我不想给自己计划了,随心所遇吧,附一张图,激励我自己,也激励那些跟我一样的人。

固定布局就是个屎,我要投奔流体布局!如果你一直都是流体布局的,自己心里也默念三遍:流体布局就是个屎,我要投奔固定布局!如果你固定/流体布局兼修,自己心里也默念三遍:什么固定/流体布局都是屎,我要投奔时髦的响应布局!

看到张鑫旭这句话时,我就没放在心上,想着在响应布局早着呢,难维护,兼容又差,现在没想到,已经迫在眉睫,赶紧恶补下

以下内容你可以直接到张鑫旭的博客上看,顶部有博客链接,底部有具体本章链接,他本人写的简单易懂还实用并且幽默附有dome等等,我自己的纯属于练文采,做笔记用

响应式不句就是根据窗口的大小做相应的布局

 

应运而生的web页面响应布局

 

zxx的做法是在连入css的就把不同宽度的局部放在不同的css中

<link rel="stylesheet" type="text/css" href="normalScreen.css" media="screen and (max-width: 1024px)" />

<link rel="stylesheet" type="text/css" href="widthScreen.css" media="screen and (min-width: 1024px)" />

zxx的做法是在连入css的就把不同宽度的局部放在不同的css中
对与ie678不支持css3用js做了处理
if(!window.screenX)
{
    //ie6~8
    var oStyle=document.createElement('link');
    oStyle.rel='stylesheet';
    oStyle.type='text/css';
    if(screen.width>1024)
    {
        oStyle.href = "widthScreen.css";    
    } else {
        oStyle.href = "normalScreen.css";    
    }
    document.getElementsByTagName('head')[0].appendChild(oStyle);
}
View Code

伪类+js实现CSS3 media queries跨界准确判断

我们都知道,CSS3 media queries响应布局实现之利器。国外很多著名的前端站点,如css-tricks, smashingmagazinegazine等都采用了响应布局。

伪类(IE8+), js(getComputedStyle, IE9+)以及media queries(IE9+)都需要现代浏览器的支持。

media queries可以让设备在不同尺寸下应用不同的CSS样式、布局等。以适应手持设备、普屏显示器、宽屏显示器,以及未来冰箱上的联网显示器,汽车上的数码设备等。然后,仅仅通过CSS做布局可能无法应对所有的交互请求。

举个简单例子,我们打开浏览器可能处于非最大化状态,此时,如果作为普屏处理,加载的图片可能就是128*128的小尺寸图片。但是,当我们最大化以获得更好阅读体验的时候,需要使用更大尺寸的图片256*256, 使用media queries? 拜托,CSS只能改变外在的尺寸,你难道要2倍尺寸拉伸?显然,更合理的做法是加载256*256尺寸的中等尺寸图片。以目前的技术而言,估计除了使用JS修改图片src外,很难有其他更可用的方法了。

OK, 现在问题来了,如何让JS的修改与CSS布局改变同步呢?

CSS交互与JS交互同步问题

如何让CSS样式、布局改变的时候,同时准确触发JS的交互呢?

方法一、直接宽度/高度值匹配
何意?CSS3 media queries跨界触发一般都有一个宽度或高度值,或是color(很少使用)。例如,普屏图片宽度128*128,可能就是如下CSS:

@media screen and (max-width: 1024px) {
    img {
        width: 128px;
        height: 128px;
    }
} 

意思就是screen(屏幕)宽度不超过1024像素(max-width:1024px)的时候,图片宽度是128像素,高度也是128像素。

因此,我们可能通过浏览器窗口尺寸改变的resize事件中捕获浏览器窗口尺寸,与1024对比,如果小于则触发对应的普屏事件处理,大于,则宽屏处理。

window.addEventListener("resize", function() {
    // window.innerWidth IE9+浏览器支持
    if (window.innerWidth <= 1024) {
        // 普屏处理
    } else {
        //宽屏处理
    }
});

确实是简单高效的方法。但是,也是有不足的。

① 可维护性
一个载体所对应的数值是会经常变的。例如,小胖今天体重148斤,明天喝碧生源厕所来回几个小时,可能就只有145斤了。同样的,对于1024这个值,变 动的几率是很大的。变动其实没什么,麻烦的是下面的JS中的判断的数值与CSS中的限制是要一致的。也就是CSS宽度阈值改变,JS也要跟着变。显然,这 种高耦合增加了后期的维护成本。

② 宽度的计算与不确定性
window.innerWidth返回的是窗口内部宽度(不包括浏览器的框框),单位是像素。但是,width属性的单位并不固定。有些站点,可能使用em, %或最新的vw, rem, in等(完整单位参见之前“CSS长度值及时间、频率、角度单位”一文)。

而这些单位的宽度转换成px就需要计算,而这些单位很多是相对的,例如em是与字体大小相关的,如果网页的字体大小被用户手动改变(视力不佳用户,或是“Ctrl + 加号”的误操作),可能你之前按照12像素比例的宽度计算就会不准确。这就是宽度计算的不确定性。

可见,我们有必要寻求更佳的同步方法。什么呢,就通过CSS本身!

通过CSS本身?
比方说吧(虽然这个例子实用性不佳),我们通过media queries让图片宽度变成128像素,就可以通过检测图片应用的宽度判断当前设备状态。

当然,这里只是举例,其实这比上面1024px方法更搓,因为,牵扯到实际样式的CSS是会经常变动的,JS显然不能与之高耦合。

那该如何应用呢?很简单,应用在不会使用的元素,不会产生额外影响的CSS属性。例如在<head>标签上使用z-index属性(from Stephanie)。

@media screen and (min-width: 45em) {
    head {
        z-index: 2;
    }
}

难过 张鑫旭-鑫空间-鑫生活不过,根据Jeremy Keith的测试,Webkit浏览器貌似不支持,其返回的z-index值是auto, 不是数值2. 我那热乎乎的小心脏,瞬间冰冻,啊~~

应用在<body>标签上到是可以的,不过,由于body标签暴露在外,参与CSS布局,如何其设置了定位属性(relative, absolute等),z-index立马勃起,如果里面在层级复杂点,哦呵呵,兄弟你把妹的时间估计要陪代码咯!

不过,对于一般的页面(不是类似游戏页面,幻灯片页面的页面),只有某些艺高人才敢在body上增加定位属性(违背最小化影响原则 – part 7),因此,在body上设置z-index属性一般问题不大,但是,从可理解性上讲,z-index弱了点。因为,z-index值一般是数值。你说:

800~1024     z-index:1;
1024~1280     z-index:2;
1280~1440     z-index:3;
1440~1680     z-index:4; 

两个月后,你在看JS中,zIndex1, 2, 3, 4,你还记得对应的数值范围吗?别人经手你的代码,知道各个数值对应的含义吗?(别跟我扯注释~~)

因此,我们需要寻求更佳的方案。

方法二、body标签+伪类+content内容生成

因为每个页面都有body标签,在该标签上打标记便于整站通用。

这里的伪类指:after, :before亦可,因为,使用该CSS属性与实际用途冲突概率要比z-index属性小多了,更加安全。

content内容生成我专门写过一篇文章:“CSS content内容生成技术以及应用”,后来又结果伪类属性写了篇:“:after伪类+content内容生成经典应用”。您有兴趣可以看看。而这里,则是一个新的应用典型了。

使用content内容生成的最大好处在于,我们可以随意定义里面的内容(z-index只能数值),例如:

{ content: "普屏"; }

显然,这个描述性的文字是很泛的,概括性强,不会因为1024px变成980px而跟着变动,而且,含义明显,一目了然。

因此,上面的一番分析总结,body:after + content是相当好的一个方法。

我们唯一剩下的技术难点就是如何使用JS获取content的内容。当当当当,前几天的写的“获取元素CSS值之getComputedStyle方法熟悉”一文内容就派上用场了。

使用方法就是标题中的getComputedStyle:

var content = window.getComputedStyle(document.body, ":after").getPropertyValue("content");

然后,我们就可以根据content的具体内容,准确捕获media queries越界的瞬间,并作出相关的JS交互了!

if (content === "窄屏") {
    // ……
} else if (content === "普屏") {
    // ……
} else if (content === "宽屏") {
    // ……
}

CSS代码:
.demo img {
    width: 512px;
}
@media screen and (max-width: 1024px) {
    body:after {
        display: none;
        content: 'normalscreen';
    }
    .demo img {
        width: 256px;
    }
}
JS代码:
var oDemo = document.getElementById("dome"), oImage = null, screenTypeCache;    
var funImage = function() {
    var screenType = window.getComputedStyle(document.body, ":after").getPropertyValue("content");
    if (screenTypeCache !== screenType) {
        var src = "http://image.zhangxinxu.com/image/study/s/"+ (/normalscreen/.test(screenType)? "s256": "s512") +"/mm1.jpg";
        if (oImage === null) {
            oImage = document.createElement("img");
            oDemo.appendChild(oImage);
        }
        oImage.src = src;
        screenTypeCache = screenType;
    }
};
if (window.getComputedStyle) {
    window.addEventListener("resize", funImage);    
    funImage();
} else {
    oDemo.innerHTML = '<img src="http://image.zhangxinxu.com/image/emtion/litter-sad.png" /><p>对不起,您的浏览器目前还不支持该功能!</p>';
}
View Code

getComputedStyle返回的content值在某些浏览器下是带有引号的,因此,你不能使用===直接匹配,可以使用简单正则test方法(demo页面的方法),或是索引查找indexOf方法,或是字符分隔split方法等。

if (content === "normalscreen") {}

if (/normalscreen/.test(content)) {}

百闻不如一见

您可以狠狠地点击这里:伪类+js与media queries跨界demo

热门:响应图片(Responsive Images)技术简介

Cookie + Server实现

使用noscript标签创建响应图片

首先是HTML部分:

<span class="img-placeholder"></span>
<noscript data-mobilesrc="small.jpg" data-fullsrc="big.jpg" data-alttext="your alt text" class="responsivize">
   <img src="big.jpg">
</noscript>

首先是HTML部分:

<span class="img-placeholder"></span>
<noscript data-mobilesrc="small.jpg" data-fullsrc="big.jpg" data-alttext="your alt text" class="responsivize">
   <img src="big.jpg">
</noscript>

上面代码中,类名为img-placeholderspan标签是用来占位子和插入图片的。<noscript>中的图片默认调用的是大图地址,在JavaScript被禁用的时候会显示。

下面要做的就是使用JavaScript判别当前显示设备是mobile类别还是desktop类别:

var responsiveImageTag = {
    replaceInitialImages:function() {
        var platform = "desktop";
        var responsiveImages = $$(".responsivize");
        var i,
            noOfresponsiveImages = responsiveImages.length;
        //当前显示器设备宽度测试
        if(screen.width <= 767){ 
                //767px, 比 ipad 小的都认为是 mobile
          platform = "mobile";
        }
        
       //set initial source element on image
       for(i = 0; i < noOfresponsiveImages; i = i + 1 ){
       var noScriptElem = $(responsiveImages[i]);

既然知道了设备类别,我们就可以根据这个类别分别载入对应尺寸的图片了。对应设备尺寸图片地址以通过HTML5自定义属性data-定义在了<noscript>上,因此,我们就有代码(紧接上面):

    var img = window.document.createElement("img");
       img.alt = noScriptElem.attr("data-alttext");
       if(platform === "mobile"){
          img.src = noScriptElem.attr("data-mobilesrc");
       }else{
          img.src = noScriptElem.attr("data-fullsrc");
       }
       img.className = "responsive";

然后,把图片以DOM的形式插入到上面用来占位的span标签元素内,于是就大功告成!

       noScriptElem.prev().append(img);   
       noScriptElem.hide();
     }
   }
};

Jeremy Keith提出了另外一种响应图片技术,可以算是一种图片加载优化技术。

如下:
无论是小屏幕的手机,还是大屏幕的桌面设备,默认img链接的图片都是小图(如下)。

然后页面载入完毕后,如果显示器宽度超过一个限制,则src地址切换成大图地址。

其中,有个比较关键的就是,如果显示器宽度大于某个值,小图的高宽尺寸是要被放大的,也就是说小图会被拉伸显示。这种尺寸的控制借助于CSS3:

@media screen and (min-width: 50em) {
    .photo {
        width: 500px;
        height: 375px;
    }
}

于是乎,我们会看到,页面载入后的模糊图片:

但是,这种模糊效果是暂时的,因为页面loaded完毕后,我们会根据宽度范围再次修改imgsrc地址,而载入清晰图片。

我记得以前百度图片浏览就是这种效果滴。

这种图片响应实现的好处在于提高了页面的性能,虽然看上去好像比值加载大尺寸图片多了差不多20K。

根据作者的示例,大图的地址使用HTML5 data-自定义属性藏匿:

<img src="seed.jpg" alt="刺刺的种子" data-fullsrc="seed-large.jpg"> 

翻译:web响应设计,乏味

不要让响应设计的格栅和规则限制你设计的火花与灵感。把枯燥干掉,带来精彩。

设计优先,响应其次,网站灵魂与个性是关键。

响应设计的例子

Food Sense是个很好的例子,编辑风格的设计,仍然有个性和感觉。当你改变宽度的时候会看到一些令人惊讶的和明智的处理。

Naomi Atkinson Design
虽然我几乎写了一整段有关如何单栏式布局不应该算作响应设计,然而Naomi Aktinson Design证明我错了。进一步的调查揭示了它很多聪明的设计选择,无论是在全尺寸和较小的尺寸。

Forefathers Group
要说个性!Forefathers设计公司的家伙们肯定带来了。你可以耗费数小时来细致小心地查看他们是如何让网站在不同宽度下都非常美丽地工作的。真是做得很赞啊,伙计们!

1,应运而生的web页面响应布局 本文地址:http://www.zhangxinxu.com/wordpress/?p=1937

2,伪类+js实现CSS3 media queries跨界准确判断 本文地址:http://www.zhangxinxu.com/wordpress/?p=2387

3,热门:响应图片(Responsive Images)技术简介 本文地址:http://www.zhangxinxu.com/wordpress/?p=2204

4,翻译:web响应设计,乏味! 本文地址:http://www.zhangxinxu.com/wordpress/?p=1983 

哈哈,好开心,终于弄完了

posted @ 2013-06-07 16:08  前端之路  阅读(498)  评论(0编辑  收藏  举报