CSS布局秘籍(2)-6脉神剑-LMLPHP

HTML系列:

CSS系列:

00、布局的6脉神剑


01、Flex弹性盒子(display:flex)

Flexbox(IE11)是 CSS 弹性盒子布局模块(Flexible Box Layout Module)的缩写,用于实现横向纵向的单向布局,在父元素(flex容器)上应用display: flex ,所有子元素(flex项)都将会按照 flex 进行布局。Flex是新一代的CSS排版布局系统,使用简单,不用担心float浮动布局的各种坑,推荐食用。

flex 布局需了解他的两根轴:

  • 主轴flex-direction 定义的方向,就是flex项排列的方向,默认横向排列,从左到右。
  • 交叉轴:垂直与主轴的方向。

CSS布局秘籍(2)-6脉神剑-LMLPHP


<style>
    .flex {
        display: flex;
        flex-flow: row wrap;
        align-items: stretch;
        justify-content: stretch;
    }
    /*注意这里,一般用子代选择器*/
    .flex>div {
        flex: 1 200px;
        background-color: #9be6bd;
        padding: 10px;
    }
    .flex>div:nth-child(even){                
        background-color: #eeb2cb;
    }
</style>
<div class="flex">
    <div><b> div1:</b>
        <p>Flexbox 是 CSS 弹性盒子布局模块(Flexible Box Layout Module)的缩写</p>
    </div>
    <div>div2:</div>
    <div>div3:</div>
    <div>div4:</div>
    <div>div5:</div>
</div>

CSS布局秘籍(2)-6脉神剑-LMLPHP

下面代码为基于flex的栅格布局(12格),可以自动等比例划分网格,比float浮动的栅格方便多了。

.row {
    display: flex;
}

.col {
    margin-left: 2.08333333%;
    margin-bottom: 1em;
    width: 6.25%;
    flex: 1 1 auto;
    background: rgb(255,150,150);
}

02、Grid网格布局(display:grid)

grid布局是一个二维布局系统,通过设置定义一个网格,然后子元素按照顺序排列网格,或者设置其行列网格坐标。一个gird网格通常具有许多的行(row)与 列(column),以及行与行、列与列之间的间隙,这个间隙一般被称为沟槽(gutter /ˈɡʌtər/水沟)。


.grid {
    display: grid;
    grid-template-columns: 200px max-content 100px auto 10%;
    grid-template-rows: 100px auto;
    /* 两行布局:行定义/列定义 */
    grid-template: minmax(100px,auto) 40px/ 200px 1fr 1fr;
    /* 两行三列命名布局,子元素需指定名称 grid-area */
    grid-template-areas: "head head right" "nav  main right";
    grid-auto-rows: 50px;
    /* 网格间隙距离 */
    row-gap: 5px;
    column-gap: 10px;
    grid-gap: 5px 10px;
}
.grid div:first-child{
    /* 跨2个格子,两种方式 */
    grid-column: 1/3;
    grid-column: 1 /span 2;
    /* 命名布局,指定命名格子 */
    grid-area: right;
}

🔸隐式网格

通过grid-template-columns grid-template-rowsgrid-template等显示申明创建的网格为显示网格,当子元素超出时会自动换行进行网格排列,这部分称为隐式网格,隐式网格的大小默认是auto(根据内容自适应),可以通过grid-auto-rowsgrid-auto-columns来设置隐式行列网格的尺寸大小。

🔸网格分割线

网格线是从头开始的,一般来说n行有n + 1根水平网格线,m列有m + 1根垂直网格线。设置子元素的网格坐标grid-row / grid-column时,用的坐标是基于网格线的,而不是格子。

CSS布局秘籍(2)-6脉神剑-LMLPHP

<style>
    .from {
        display: grid;
        grid-gap: 8px 5px;
        /* 设置行列网格 */
        grid-template-columns: repeat(2, 80px minmax(120px, 1fr));
        grid-template-rows: repeat(3, minmax(40px, auto));
        grid-auto-rows: minmax(40px, auto);
        /* 合并的写法 */
        grid-template: repeat(2, minmax(36px, auto)) / repeat(2, 80px minmax(180px, 1fr));
    }
    .from * {
        box-sizing: border-box;
        padding: 3px; margin: 0px;
        background-color: lightyellow;
    }
    .from label {
        display: flex; padding: 0 3px;
        align-items: center;
        justify-content: right;
    }
    .from>.form-cell {
        display: flex; padding: 0 10px;
        align-items: center;
    }
    .from>textarea {
        grid-column: 2/5;
        grid-column: 2/span 3;
        resize: none;
    }
</style>
<div class="from">
    <label for="">姓名:</label><input type="text">
    <label for="">籍贯:</label><input type="text">
    <label for="">性别:</label>
    <div class="form-cell">
        <input type="radio"><label for="">男</label>&nbsp;&nbsp;
        <input type="radio"><label for="">女</label>
    </div>
    <label for="">生日:</label><input type="date">
    <label for="">简介:</label><textarea name="" id="" cols="100" rows="5">1111</textarea>
</div>

CSS布局秘籍(2)-6脉神剑-LMLPHP

🔸区域网格命名

用“名字”来划分并指定区域,用法类似网格线序号,用来做页面布局更轻松、可读性好。

  • 区域字符命名,行内空格分割列,行间引号分割。两行三列:grid-template-areas: "head head right" "nav main right";
  • 相同命名的格子自动合并单元格,且必须为一个相邻的矩形。
  • 所有名字只能出现在一个连续的区域,不能在不同的位置出现。
  • 使用.符号,让一个格子留空,就是空着,啥也不干。
<style>
    .page{
        display: grid;
        /*定义2列、3行*/
        grid-template-areas: "header header" "left right" "footer footer"; /*图1布局*/
        grid-template-areas: "left header" "left right" "footer right"; /*图2布局*/
        grid-template-rows: 40px 1fr 40px;
        grid-template-columns: minmax(100px,200px) auto;
        height: 300px; margin: 10px;
    }
    .page>.header{grid-area: header;}
    .page>.left{grid-area: left;background-color: lemonchiffon;            }
    .page>.right{grid-area: right;background-color: rgb(170, 236, 238);            }
    .page>.footer{grid-area: footer;}
    .page>div{background-color: aquamarine;padding: 10px;            }
</style>
<div class="page">
    <div class="header">header</div>
    <div class="left">left</div>
    <div class="right">right</div>
    <div class="footer">footer</div>
</div>

» 调整命名即可实现不同的布局:

CSS布局秘籍(2)-6脉神剑-LMLPHPCSS布局秘籍(2)-6脉神剑-LMLPHP


03、float浮动布局

float 属性让素左右浮动起来,元素从正常布局流 (normal flow) 中移除,会浮动到父容器的左侧或右侧。会改变元素本身和跟随他后面的(不管层级、类型)其他正常流布局元素的行为,它后面的正常布局的元素围绕该浮动元素,并填满其右侧(或左侧)的空间。因为float脱离了文档流,正常流的元素就会和他重叠,但元素的content内容不重叠,就会产生环绕效果。

<div>
    <img src="/res/qq-128.png" width="80" style="float:left">
    <img src="/res/vedio.png" width="80" style="float:right">
    <p style="background-color:#0001;">所有元素都是一个盒子Box,盒子Box是页面布局的基本单位,盒子的不同类型决定了他的布局方式。一个页面由各种盒子的组合、嵌套形成。</p>
</div>

CSS布局秘籍(2)-6脉神剑-LMLPHP

flexgrid网格布局问世之前,float是实现页面布局的重要手段,他也存在一些惨无人道的问题,可以参考上一章节BFC部分内容。

下面的示例代码就是典型的传统基于float浮动实现的栅格布局,把列等分为12份,并穷举创建横跨2-12列的样式类,代码量多,点都不优雅。

body {
    width: 90%;
    max-width: 980px;
    margin: 0 auto;
}
*{box-sizing: border-box;}
/* row用来清除row之间的浮动影响 */
.row {
    clear: both;
}
.col {
    float: left;
    margin-left: 2.08333333%;
    width: 6.25%;
}
.col.span2 { width: calc((6.25%*2) + 2.08333333%); }
.col.span3 { width: calc((6.25%*3) + (2.08333333%*2)); }
.col.span4 { width: calc((6.25%*4) + (2.08333333%*3)); }
/*...*/
.col.span12 { width: calc((6.25%*12) + (2.08333333%*11)); }
/* 用来作为空列的偏移*/
.offset-by-one {
    margin-left: calc(6.25% + (2.08333333%*2));
}

» float表单:

<style>
    .form-float *{ box-sizing: border-box; }
    .form-float>.row{
        clear: both;    padding: 5px 0;
    }
    .form-float>.row>.col{
        float: left;
        background-color: antiquewhite; padding: 5px; 
    }
    .form-float>.row>.col.lab{
        width: 15%;
        text-align: right;
    }
    .form-float>.row>.col.span1{ width: 35%; }
    .form-float>.row>.col.span2{ width: 85%; }
    .clear{ clear: both; } 
</style>
<form class="form-float">
    <div class="row" id="r1">            
        <label for="" class="col lab" id="l1">姓名:</label>    <input type="text" class="col span1" value="杜牧">
        <label for="" class="col lab">籍贯:</label><input type="text" class="col span1" value="唐">
    </div>
    <div class="row">
        <label for="" class="col lab">性别:</label>
        <div class="col span1">
            <input type="radio"><label for="">男</label>&nbsp;&nbsp;
            <input type="radio"><label for="">女</label>
        </div>
        <label for="" class="col lab">生日:</label><input type="date" class="col span1">
    </div>
    <div class="row">
        <label for="" class="col lab">简介:</label>
        <textarea name="" id="" cols="100" rows="5" class="col span2">停车坐爱枫林晚,霜叶红于二月花</textarea>
    </div>
</form>
<div class="clear"></div>

CSS布局秘籍(2)-6脉神剑-LMLPHP

🔸清除浮动

脱离正常的文档流,并不会占据正常文档流的位置,如果一个父元素下面都是浮动元素,或正常元素高度低,则会导致父元素的高度坍塌。从而使得后面的正常元素布局出现不希望的情况,常见三种清除方法:

/* 恢复父元素上的BFC */
.parent {
    overflow: hidden;
}

/* 在父元素上使用清除clearfix:clear + 伪元素::after实现,附加一个空的块元素并清除 */
.clearfix::after {
    content: "";
    display: block;
    clear: both;
}


04、position定位

position 可精准设置盒子的位置,正常布局流中,元素的position默认值为 static。使用其它值可实现元素不同的定位,结合偏移top, bottom, left, right使用,如果不设置偏移,则元素还是原来的位置。

<style>
    .btn-top{
        display: block;
        font-size: 30px; font-weight: bold;
        width: 50px; height: 50px; line-height: 50px;
        border-radius: 50%;  opacity: 0.5;
        text-align: center; text-decoration: none;
        background-color: #eeb2cb;
        /* 定位 */
        position: fixed;
        bottom: 10px; right: 10px;
    }
    .btn-top:hover{
        opacity: 1; background-color: coral;
    }
</style>
<a href="#" class="btn-top" title="回到顶部">🔝</a>

CSS布局秘籍(2)-6脉神剑-LMLPHP


05、表格布局(display:table)

table 表格布局 和<table>元素类似,实现一个行列工整的布局表格。表格的布局可以用在非表格内容上,使用display: tabletable-rowtable-cell和相关属性在非表元素上,可用于表单form的内容布局(好像并不好用-不能跨行?)。

» 表格布局-表单

<style>
    .form-table {
        display: table;
        width: 100%; border: 1px solid lightgray;
    }
    .form-table .trow {
        display: table-row;
        background-color: linen;
    }
    .form-table .trow>label{
        display: table-cell;
        width: 100px; line-height: 40px;
        text-align: right;
    }
    .form-table .trow>input,.form-table textarea{
        display: table-cell;
        width: 90%;
    }
</style>
<div class="form-table">
    <div class="trow">
        <label for="" id="l1">姓名:</label><input type="text" value="杜牧">
        <label for="">籍贯:</label><input type="text" value="唐">
    </div>
    <div class="trow">
        <label for="">性别:</label>
        <div>
            <input type="radio"><label for="">男</label>&nbsp;&nbsp;
            <input type="radio"><label for="">女</label>
        </div>
        <label for="">生日:</label><input type="date">
    </div </div>
<div class="trow">
    <label for="">简介:</label>
    <textarea name="" id="" rows="4" colspan="3">不知道怎么实现跨行</textarea>
</div>
</div>

CSS布局秘籍(2)-6脉神剑-LMLPHP


06、column-count多列布局

多列布局是一种把内容按列排序的布局方式,通过 column-count 设置列的数量,使用 column-width 设置列宽,两者可都设置或只设置任意一个即可。跟flex布局有点像,不过他们的元素跨行(截断)分配方式不一样,column-count更合适文档排版(类似报纸的排版)。

column-count对容器里面内容的列拆分是自动进行的,容易造成一个内容部分被折断(跨列显示了),可以通过break-inside 对特定内容进行换行方式设置。

<style>
    .mulcol{
        column-count: 2;
        column-width: auto;
        column-gap: 15px;
        column-rule: 4px double red;
        background-color: antiquewhite;
        padding: 8px 10px;
    }
    .article{
        background-color: limegreen;
        break-inside: avoid;
        /* 设置旧属性page-break-inside 增强兼容性*/
        page-break-inside: avoid;
    }
</style>
<div class="mulcol">
    <div class="article">            
        <h2>山行</h2>
        <p>远上寒山石径斜,白云深处有人家。停车左爱枫林晚,霜叶红于二月花。</p>
    </div>
    <div class="article"> 
        <h2>望庐山瀑布</h2>
        <img width="200px" src="http://n.sinaimg.cn/translate/166/w991h775/20181129/5biI-hpevhcm3526810.jpg" alt="">
        <p>日照香炉生紫烟,遥看瀑布挂前川。飞流直下三千尺,疑是银河落九天。</p>
    </div>
</div>

» 没有加break-inside的效果,文章块被折断

CSS布局秘籍(2)-6脉神剑-LMLPHP CSS布局秘籍(2)-6脉神剑-LMLPHP


11-08 10:41