5:等分,居中等页面布局​ 

等分

在说等分之前,先抛出一个问题,如下面的emmet代码,footer部分的导航有些页面是三个,有些页面是四个,我们要求的是不论是三个还是四个甚至于5个,都平分宽度。


footer.footer>ul.nav-links>li*3
footer.footer>ul.nav-links>li*4


float


如果采用float技术的话,那估计只有在ul上添加额外的class来设置li的百分比宽度了。


.nav-links li{
float:left;
width:25%;
}
.percent-half li{
width:50%;
}
.percent-third li{
width:33.333%;
}
...


这个太蛋疼了,高上大的移动端怎么能用这么老套的东西呢,所以不考虑。


table


也许这个技术会被很多人忘记,不过用在移动端确实不错,关键是没有兼容问题的。主要设置父元素的​​display: table;table-layout: fixed;width: 100%;​​​,然后设置子元素为​​display: table-cell;​​即可。


// table 等分
@mixin table-equal($children: li) {
display: table;
table-layout: fixed;
width: 100%;
$childrenEle: li div p a span strong;
@if index($childrenEle, $children) {
#{$children} {
display: table-cell;
}
}
@else {
.#{$children} {
display: table-cell;
}
}
}

.nav-links{
@include table-equal;
}


这个mixin内部定义了一个​​$childrenEle​​​元素选择器变量集合,如果传入的参数是其中的一个,那么直接使用元素选择器,否则就当class选择器使用,如默认的li解析后就是​​li{display: table-cell;}​​​,而如果传入children,则解析后就是​​.children{display: table-cell;}​​。下面的flex同样使用了该方法


注:在移动端​​display: table;​​同样也是个有利的神器,比起各种float什么的,这个技术还是可以单刀直入,直指问题核心


flex


flex技术是个好技术,不过最关键的还是其兼容问题,算起来它有三个版本,是有点乱哈哈。不过sandal的css3文件已经封装好了,所以只管调用,它会自动生成对应的兼容代码。


// flex 等分
@mixin flex-equal($children: li) {
@extend %display-flex;
$childrenEle: li div p a span strong;
@if index($childrenEle, $children) {
#{$children} {
@include flex(1);
}
}
@else {
.#{$children} {
@include flex(1);
}
}
}

.nav-links{
@include flex-equal;
}




水平垂直居中


以简单的弹窗为例:


<div class="overlay">
<section class="modal">
<div class="modal-bd">
<p>青,取之于蓝,而青于蓝;冰,水为之,而寒于水。故木受绳则直,金就砺则利,君子博学而日参省乎己,则知明而行无过矣。</p>
</div>
</section>
</div>


也许看到这个结构,很多人都会纳闷,因为大家看到更多的应该是:​​.overlay+section.modal​​,即蒙版与弹出内容是兄弟元素,而不是嵌套关系。这里先卖个关子,到modal实例的时候,再分析。


flex


样式写在父元素上


// flex center
// display:flex
%display-flex,%flex-display {
@include display-flex;
}

@mixin flex-center($direction: both) {
@extend %display-flex;
@if $direction == both {
@include justify-content(center);
@include align-items(center);
}
@else if $direction == x {
@include justify-content(center);
}
@else if $direction == y {
@include align-items(center);
}
}

.overlay{
z-index: 980;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,.8);
@include flex-center; // overlay调用
}
.modal{
background-color: #fff;
border-radius: 5px;
margin: 0 10px;
overflow: hidden;

.modal-bd{
padding: 15px;
}
}


关于flex的单个元素水平垂直居中,新语法直接父元素为flex,子元素设置margin为auto即可,因为移动端还在使用旧语法,所以暂不使用margin这个方法,而是设置父元素的水平及垂直都居中


translate


样式写在要居中的元素上。原理就是先绝对定位,left/top为50%,然后通过translate偏移-50%回去(translate偏移的百分比为自身宽高的百分比),比从前的margin-top/left设置负值偏移回去高级点,因为设置margin必须得知道自身元素的宽高,然后设置具体的数字,而translate不用管自身的宽高,直接50%就可以搞定


// translate 50%
@mixin translate-center($direction: both) {
position: absolute;
@if $direction == both {
top: 50%;
left: 50%;
@include translate(-50%, -50%);
}
@else if $direction == x {
left: 50%;
@include translate(-50%, 0);
}
@else if $direction == y {
top: 50%;
@include translate(0, -50%);
}
}

.overlay{
z-index: 980;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0,0,0,.8);
}
.modal{
@include translate-center; // modal调用
background-color: #fff;
border-radius: 5px;
width:300px;
overflow: hidden;

.modal-bd{
padding: 15px;
}
}


上面的flex和translate两个mixin都可以实现单独的水平居中或垂直居中,传入相应的x或y即可。不论是flex还是translate水平垂直居中都有两个很好的优势即无需借助额外的空标签,也无需知道子元素的具体宽高,这比从前的一些方法强多了




左右两端对齐


对于左右两端对齐,以前使用最多的可能就是float,position了,现在同样可以采用flex来搞定


// justify
@mixin justify($extend: true) {
@if $extend {
@extend %justify;
}
@else {
@extend %display-flex;
@include justify-content(space-between);
}
}
%justify {
@include justify(false);
}

.justify{
@include justify;
}




总结


如果你开始做移动端,那么flex和transform这两大属性有必要熟练运用,运用好了能解决很多问题。一般来说flex可以用来实现一些布局,再也不用动不动就float了;而transform中的rotate及translate则可以实现一些旋转及位移移动,旋转可以搞定图标的一些变化,而位移移动则可以实现居中,位移动画等。

具体页面代码如下:

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8">

<meta name="robots" content="noindex">

<meta content="width=device-width, initial-scale=1, user-scalable=no, minimal-ui" name="viewport">

<meta name="apple-mobile-web-app-capable" content="yes">

<meta name="apple-mobile-web-app-status-bar-style" content="black">

<meta content="telphone=no" name="format-detection">

<title>等分</title>

<style id="jsbin-css">

.clearfix:before,.clearfix:after{content:"";display:table;}

.clearfix:after{clear:both;}

html,body{height:100%;}

html{font-family:"Helvetica Neue",Helvetica,STHeiTi,Arial,sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%;font-size:62.5%;}

body{margin:0;font-size:1.4rem;line-height:1.5;color:#333;background-color:#fff;}

article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block;}

audio,canvas,progress,video{display:inline-block;vertical-align:baseline;}

audio:not([controls]){display:none;height:0;}

[hidden],template{display:none;}

a{background:transparent;text-decoration:none;-webkit-tap-highlight-color:transparent;color:#08c;}

a:active{outline:0;}

a:active{color:#069;}

abbr[title]{border-bottom:1px dotted;}

b,strong{font-weight:bold;}

dfn{font-style:italic;}

mark{background:#ff0;color:#000;}

small{font-size:80%;}

sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline;}

sup{top:-0.5em;}

sub{bottom:-0.25em;}

img{border:0;vertical-align:middle;}

svg:not(:root){overflow:hidden;}

hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0;}

pre{overflow:auto;white-space:pre;white-space:pre-wrap;word-wrap:break-word;}

code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em;}

button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0;}

button{overflow:visible;}

button,select{text-transform:none;}

button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer;}

button[disabled],html input[disabled]{cursor:default;}

button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0;}

input{line-height:normal;}

input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0;}

input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto;}

input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box;}

input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none;}

fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:0.35em 0.625em 0.75em;}

legend{border:0;padding:0;}

textarea{overflow:auto;resize:vertical;}

optgroup{font-weight:bold;}

table{border-collapse:collapse;border-spacing:0;}

td,th{padding:0;}

html,button,input,select,textarea{font-family:"Helvetica Neue",Helvetica,STHeiTi,Arial,sans-serif;}

h1,h2,h3,h4,h5,h6,p,figure,form,blockquote{margin:0;}

ul,ol,li,dl,dd{margin:0;padding:0;}

ul,ol{list-style:none outside none;}

h1,h2,h3{line-height:2;font-weight:normal;}

h1{font-size:1.8rem;}

h2{font-size:1.6rem;}

h3{font-size:1.4rem;}

input::-moz-placeholder,textarea::-moz-placeholder{color:#ccc;}

input:-ms-input-placeholder,textarea:-ms-input-placeholder{color:#ccc;}

input::-webkit-input-placeholder,textarea::-webkit-input-placeholder{color:#ccc;}

*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}

.demo{line-height:44px;margin-bottom:20px;text-align:center;background-color:#0078e7;color:#fff;}

.flex-equal,.flex-center,.justify{display:-webkit-box;display:-ms-flexbox;display:-webkit-flex;display:flex;}

.flex-equal li{-webkit-box-flex:1;-ms-flex:1;-webkit-flex:1;flex:1;}

.table-equal{display:table;table-layout:fixed;width:100%;}

.table-equal li{display:table-cell;}

.demo-center{border:1px solid #ccc;margin:20px;height:200px;}

.demo-center .children{background:#0078e7;color:#fff;width:150px;line-height:5;text-align:center;}

.flex-center{-webkit-box-pack:center;-ms-flex-pack:center;-webkit-justify-content:center;justify-content:center;-webkit-box-align:center;-ms-flex-align:center;-webkit-align-items:center;align-items:center;}

.translate-center{position:relative;}

.translate-center .children{position:absolute;top:50%;left:50%;-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);}

.justify{-webkit-box-pack:justify;-ms-flex-pack:justify;-webkit-justify-content:space-between;justify-content:space-between;padding:0 10px;background:#0078e7;color:#fff;line-height:32px;}

</style>

</head>

<body>

<h2>flex等分</h2>

<ul class="flex-equal demo">

<li>手机</li>

<li>联系人</li>

<li>信息</li>

<li>主屏</li>

</ul>


<ul class="flex-equal demo">

<li>手机</li>

<li>联系人</li>

<li>信息</li>

</ul>

<h2>table等分</h2>

<ul class="table-equal demo">

<li>手机</li>

<li>联系人</li>

<li>信息</li>

<li>主屏</li>

</ul>

<ul class="table-equal demo">

<li>手机</li>

<li>联系人</li>

<li>信息</li>

</ul>

<h2>flex居中</h2>

<div class="flex-center demo-center">

<div class="children">子元素水平垂直居中</div>

</div>

<h2>translate居中</h2>

<div class="translate-center demo-center">

<div class="children">子元素水平垂直居中</div>

</div>

<h2>两端对齐</h2>

<div class="justify"><h2>左边对齐</h2><span>右边对齐</span></div>

</body>

</html>

6:切入切出动画

transition动画

先定义要运动的元素在视觉范围之外,以左方向进入为例,同时定义transition:

.demo{
@include translate3D(-2000px, 0, 0);
-webkit-transition: -webkit-transform 0.3s ease-in-out;
transition: transform 0.3s ease-in-out;
}

从进入视觉范围来说,不论方向从上下还是左右,最终都归于0,所以进入的时候添加class ​​translate-in​​​,而离开的时候去掉​​translate-in​​即可

.translate-in{
@include translate3D(0, 0, 0);
}

animation动画

先定义要运动的元素在视觉范围之外,同样以左方向为例:

.demo{
@include translate3D(-2000px, 0, 0);
}

再定义keyframes:

// 从左向右方向进入动画
@mixin left-in($startX: -2000px, $endX: 0) {
@include keyframes(left-in) {
0% {
@include translate3d($startX, 0, 0);
}
100% {
@include translate3d($endX, 0, 0);
}
}
.left-in {
@include animation-name(left-in);
@extend %animated;
}
}

// 从右向左方向消失动画
@mixin left-out($startX: 0, $endX: -2000px) {
@include keyframes(left-out) {
0% {
@include translate3d($startX, 0, 0);
}
100% {
@include translate3d($endX, 0, 0);
}
}
.left-out {
@include animation-name(left-out);
@extend %animated;
}
}

调用上面定义的keyframes,元素进入视觉范围添加class ​​left-in​​​,元素离开视觉范围则替换​​left-in​​​为​​left-out​​​,动画结束后调用animationend事件,删除​​left-out​

@include left-in;
@include left-out;

解析后的css为:

.left-in, .left-out {
-webkit-animation-duration: 1s;
animation-duration: 1s;
-webkit-animation-fill-mode: both;
animation-fill-mode: both;
}

@-webkit-keyframes left-in {
0% {
-webkit-transform: translate3d(-2000px, 0, 0);
}

100% {
-webkit-transform: translate3d(0, 0, 0);
}
}
@keyframes left-in {
0% {
transform: translate3d(-2000px, 0, 0);
}

100% {
transform: translate3d(0, 0, 0);
}
}
.left-in {
-webkit-animation-name: left-in;
animation-name: left-in;
}

@-webkit-keyframes left-out {
0% {
-webkit-transform: translate3d(0, 0, 0);
}

100% {
-webkit-transform: translate3d(-2000px, 0, 0);
}
}
@keyframes left-out {
0% {
transform: translate3d(0, 0, 0);
}

100% {
transform: translate3d(-2000px, 0, 0);
}
}
.left-out {
-webkit-animation-name