基于CSS3的自适应布局技术

最近在做uOS APP的布局,研究了一下CSS3自适应布局技术在IE10+中的应用,其他标准浏览器由于具有自动更新功能,只需兼容最近的几个版本就行了——因此我们可以用CSS3来提高工作效率。

前端HTML(结构)+CSS(表现)这部分,无非是两大问题,装饰与布局。装饰某个widget就算再难,我们也可以用图片搞定。布局就不是这回事了,别的不说,display:inline-block有3px BUG,定位布局与浮动布局相关的BUG也不在10以下,关键是用起来非常麻烦,需要许多额外的元素 。早些年够为著名的是圣杯布局,双飞翼布局,近一点的是960grids提倡的栏栅布局,但这些布局都很难与@media配合使用。而@media是面向移动设备响应式布局的利器。 @media无非是在CSS引入条件判定,让相同的几个元素在分支不同时,呈现不同的布局。另,已经的浮动布局,定位布局是无法解决多列等高问题,而浮动时要求出现浮动条的需要,这也是过去不能解决的。 这正是我提倡大胆试用CSS3属性的原因。

CSS3引入了新三种布局,grid布局,伸缩盒布局,多列布局。其中grid布局的文档繁文缛节,可用性不强,目前只有IE10实现了,未来是否完蛋或重来不可知,放弃。 多列布局是针对文本与行内元素的,是为了实现报纸那种布局,与我们这种多widget的富应用不符合,暂不起用。剩下就是伸缩盒布局,是我见过的最操蛋的规范,从2009发布到去年最终定下来,更弦换辙了三次。

Flexbox 规范时间表:

  • 2009年7月 工作草案 (display: box;)
  • 2011年3月 工作草案 (display: flexbox;)
  • 2011年11月 工作草案 (display: flexbox;)
  • 2012年3月 工作草案 (display: flexbox;)
  • 2012年6月 工作草案 (display: flex;)
  • 2012年9月 候选推荐 (display: flex;)

浏览器商为了自救,搞了个私有前缀,因此定义一个伸缩盒特别麻烦:

           div{
                display: -webkit-box;
                display: -moz-box;
                display: -o-box;
                display: -ms-flexbox;
                display: -webkit-flex;
                display: -moz-flex;
                display: -ms-flex;
                display: -o-flex;
                display: flex;
          }

因此我在定下第2个规范,CSS统一用less来写。less是一种动态的样式表语言,它为CSS增加变量,组合,函数,运算等语法,让CSS更便于编写,复用与维护。 有了less,上面那一坨东西可以封装成一个函数,用不着每次都写这么多让你狂抓的候选值。

.flexbox() {//定义
   // 2009 spec
   display: -webkit-box;
   display: -moz-box;
   display: -o-box;
   // tweener
   display: -ms-flexbox;
   // new spec
   display: -webkit-flex;
   display: -moz-flex;
   display: -ms-flex;
   display: -o-flex;
   display: flex;
 }
 div{
    .flexbox();//使用
 }

我已经把与伸缩盒相关的东西都封装为一个less库,大家可以到这里

当然想实现自适应布局,光是伸缩盒是不够的(伸缩盒本来就是一打东西,本文不是入门教程,想学可以看看这篇),还有box-sizing:border-box(防止设置padding 时撑开父元素), visibility(用它实现显示隐藏,因为CSS3的动画对display:none的元素不起作用)。不过本文也介绍一下如何使用table-cell实现垂直居中。本文涉及到伸缩盒的例子都用less,请自行编译。

布局1:多列布局

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <link href="hopeui.css" media="screen,projection" rel="stylesheet" title="www" type="text/css"/>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body id="apphopeui">
        <div>
            menu
        </div>
        <div>
            main
        </div>
    </body>
</html>
@import "flexbox.less";
html,body{
 height:100%;
 margin:0;
 padding:0;
}
#apphopeui{
 @color: pink;
 background-color: @color;
 height:100%;
 .flexbox();
 .menu{
 max-width:150px;
 min-width:150px;
 background:#c50000;
 .flex(1);
 }
 .main{
 background:#75cc00;
 .flex(1)
 }
}

index1

布局2: 多栏布局

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <link href="index2.css" media="screen,projection" rel="stylesheet" title="www" type="text/css"/>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body id="apphopeui">
        <header>

        </header>
        <main>
            这是三栏布局,上下两栏固定大小,中间的自适应,占满剩余空间<br/>
            safari 5.1.7(window平台支持的最高版本safari)不认main标签,需要你将它的display设置为block或一个伸缩容器

        </main>
        <footer>

        </footer>
    </body>
</html>
@import "flexbox.less";
html,body{
 height:100%;
 margin:0;
 padding:0;
}
#apphopeui{
 @value: 1 1 auto;
 .flexbox();
 .flex-direction(column);
 background:black;
 height:100%;
 header{
 min-height:100px;
 max-height: 100px;
 background:#e4247e;
 .flex(1);
 }
 main{
 background:#00C6E4;
 display:block;//fix safari 5.1.7
 .flex(1);//safari5.1.7 use .flex(1); other browser can use .flex(@value)
 }
 footer{
 min-height:100px;
 max-height: 100px;
 background:#a9ea00;
 .flex(1);
 }
}

index2

布局3: 三栏三列布局

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <link href="index3.css" media="screen,projection" rel="stylesheet" title="www" type="text/css"/>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    </head>
    <body id="apphopeui">
        <header>

        </header>
        <main>
            <div></div>
            <div>  这是三栏三列布局,上下两栏固定大小,中间的自适应,占满剩余空间;
            safari 5.1.7(window平台支持的最高版本safari)不认main标签,需要你将它的display设置为block或一个伸缩容器
            <br/>
            白色部分,如果不设置overflow属性,以当我们收窄浏览器时,里面的文本会溢出;设置为overflow:hidden时,所有浏览器都能达到预期效果;
            设置overflow:auto 时,只有safari5.1.7失败
            </div>
            <div>

            </div>

        </main>
        <footer>

        </footer>
    </body>
</html>
@import "flexbox.less";
html,body{
 height:100%;
 margin:0;
 padding:0;
}
#apphopeui{
 .flexbox();
 .flex-direction(column);
 background: pink;
 height:100%;
 header{
 .flex(1);
 .fixed-height(100px);
 background:#e4247e;
 }
 main{
 .flexbox();
 height:99%;// fix safari 5.1.7
 background:blue;
 .flex(1);
 >:nth-child(1){
 .flex(1);
 .fixed-width(200px);
 background:#b9b9b9;
 }
 >:nth-child(2){
 .flex(1);
 background:#4D99E0;
 overflow-y: auto;
 }
 >:nth-child(3){
 .flex(1);
 .fixed-width(200px);
 background:#b9b9b9;
 }
 }
 footer{
 .flex(1);
 .fixed-height(100px);
 background:#a9ea00;
 }
}

index3

布局4: 基于table-cell的多个元素垂直居中

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <style>
            .aaa, .bbb{
                width:300px;
                height:300px;
                background: red;
                display:table-cell;
                text-align: center;
                vertical-align: middle;
            }
            .aaa div, .bbb div{
                margin: 0 auto;
                width:60px;
                height:60px;
                background: greenyellow;
            }
            .aaa div{
                float: left;
            }
            .aaa div{
                float: left;
            }
        </style>
    </head>
    <body>
        <h3>多元素垂直居中</h3>
        <div>
            <div>11111</div>
            <div>22222</div>
            <div>33333</div>
        </div>
        <div>
            <div>aaaaa</div>
            <div>bbbbb</div>
            <div>ccccc</div>
        </div>
        <p>第一个用于做放多个按钮的容器</p>

    </body>
</html>

index4

布局5: 基于伸缩盒的多个元素垂直居中

table-cell有个缺点是,它的overflow样式不起作用,因此子元素会一直撑大父元素。想出现滚动条,就要用到伸缩盒。

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
       <link href="index5.css" media="screen,projection" rel="stylesheet" title="www" type="text/css"/>
    </head>
    <body>
        <h3>多元素垂直居中</h3>
        <div>
            <div>11111</div>
            <div>22222</div>
            <div>33333</div>
        </div>

        <p>第一个用于做放多个按钮的容器</p>
    </body>
</html>
@import "flexbox.less";
html,body{
 height:100%;
 margin:0;
 padding:0;
}
.aaa{
 width:400px;
 height:400px;
 .flexbox();
 .align-items(center);
 .justify-content(space-around);
 background:#e4247e;
 div{
 .flex(1);
 // margin: 0 auto; //don't set it ,otherwise safari5.1.7 crash
 width:100px;
 max-width:100px;
 height:40px;
 border:1px solid black;
 background: #00C6E4;
 }
}

index5

布局6: 多列等高并出现水平滚动条

 

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <link href="index6.css" media="screen,projection" rel="stylesheet" title="www" type="text/css"/>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

    </head>
    <body>
        <div id="apphopeui">
            <header>xxx</header>
            <main>yyy</main>
            <footer>zzz</footer>
        </div>

    </body>
</html>
@import "flexbox.less";
html,body{
 height:100%;
 margin:0;
 padding:0;
}
#apphopeui{
 width:50%;
 height:100%;
 .flexbox();
 .box-sizing(border-box);
 border:10px solid #b7b7b7;
 overflow-x:auto;
 overflow-y: hidden;
 @value: 1 1 auto;//IE get the height of v-scrollbar into the total height;
 header{
 .flex(@value);
 .fixed-width(150px);
 background:#4D99E0;
 }
 main{
 .flex(@value);
 .fixed-width(150px);
 background:#75CC00;
 display:block;//fix safari 5.1.7
 }
 footer{
 .flex(@value);
 .fixed-width(450px);
 background:#E49800;
 }
}

index6

布局7,伸缩盒里出现垂直滚动条

<!DOCTYPE html>
<html>
    <head>
        <title>by 司徒正美</title>
        <link href="index7.css" media="screen,projection" rel="stylesheet" title="www" type="text/css"/>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">

        <style>

        </style>
    </head>
    <body>
        <header>Header</header>
        <ul>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
            <li>Item</li>
        </ul>
        <footer>Footer</footer>
    </body>
</html>
@import "flexbox.less";
html { height: 100%; }
body {
 .flexbox();
 .flex-direction(column);
 .box-sizing(border-box);
 padding: 20px;
 height: 100%;
 background: #ccc;
}
 header, footer {
 .flex(@flexvalue);
 .fixed-height(80px);
 background: #b3b3b3;
 }
ul {
 .flex(1);
 list-style: none;
 margin: 0;
 padding: 0;
 background: hsl(200,100%,90%);
 height:0;//fix opera 12.16
 overflow: auto;

}
li { padding: 20px; }
li:nth-child(odd) { background: hsl(200,100%,85%); }

index7

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值