css学习之:盒模型 与 布局

231 阅读8分钟

制作网页可以简单分为两步:

布局相当于整个页面的骨架,如何做到快速且结构合理?下面就此记录一些布局要点。

float流式布局

注意:不常用

float最常用方式:

一个float的block元素,其他inline内容会围绕它的宽高浮动

就好比:我们看到inline文本会相互排斥,其实是文本的宽高撑开了其他文本,比如设置line-height撑开其他文本,inline自身没有宽高

如下:文本环绕

image.png

如下:son1设置float:left,son2的block宽高不受son1影响了,但是son2文本还是会环绕

image.png

总结:float浮动之后,跟其他float按区域排列,被文本环绕。

  • float元素的宽高坍塌,不再排斥其他block元素的宽高,但是float的宽高会排斥所有文本inline行内元素,也即是说设置了float之后,就会无视所有block元素的空白宽高,直接贴到inline元素实体部分。

  • 跟position:absolute很相似,但是position:absolute会直接脱离文档流,无视所有其他inline和block。float只是无视block,没有无视inline文本。

利用float的这个特性,可以实现:

设置前一个元素为float,让block宽高可以重合,但是内容inline被float元素宽高撑开:

image.png

因为float布局后续如果复杂起来可能不好重写,建议复杂结构不用。

flex一维布局

flex一维布局的意思是,

它是在水平或者垂直方向上成一条直线把子元素排列,

如果设定可以换行,它也是像文本那样流动到下一行,所以是一维的。

flex一维布局,优点:用法简单,设置display即可。用法广泛,下面来看广泛在哪:

第一种布局(居中,居左右,平均分布)

image.png

如上图,flexbox弹性布局可以把整个content容器内的子元素堆放在中间、在左右、或者平均分布,使用#justify-content设置即可。

这里说的是row水平方向,垂直方向一样的效果,就是设置flex-direction为column就行。这里只说row方向。

然后,垂直方向可以放上面,中间,下面。只要有高度空间。

image.png

###第二种布局(真正的居中)

如果布局要更加灵活,比如一部分居左中,一部分居居中,一部分居右中 呢?

上面是分为3部分,那么就需要把子元素分成3份(可以是N份,根据需要),如下代码

image.png

使用id=app的容器给3个ul子元素布局,

        #app {
        margin-top: 100px;
        display: flex;
        }
        
        ul {
        flex: 1;
        
        display: flex;
        justify-content: center;
        
        border: 5px dashed red;
        }
        
        ul.center {
        flex: 0;
        border: 5px dashed black;
        }
        
        ul li a {
        white-space: nowrap;
        display: inline-block;
        font-size: initial;
        line-height: 80px;
        border: 1px solid blue;
        }

image.png

从上图可以看到,右边内容只要还没完全放不下,就不会把中间的挤出中间位置。

是因为设置了其他的放大比例为flex: 1;,而中间的放大比例为flex: 0;

也即是中间的内容只要左右还有位置,就不会被挤出居中的位置。

如果左边没有元素,那么给个看不见的同标签ul元素即可,方便统一选择器。

第三:如何把一部分子元素靠右、靠左

image.png

像上图左边的子元素,我们又可以设置为flex布局,层层套娃。

这里关键点在于,如果只是想要达到左右两个方向“浮动”布局,当然可以使用float设置,但是float之后,垂直方向的调整就不好搞了,如下图(我们要保留垂直方向这个能力):

image.png

所以,可以这样:

        ul.left {
            display: flex;
        }

        ul.left li:nth-of-type(2) {
            margin-left: auto;
        }

        ul.left li:nth-of-type(3) {
            margin-right: auto;
        }

flex中弹性布局,体现在用margin:auto直接可以设置子元素的浮动位置(垂直方向忽略即可):

image.png

因为这种方式的居中是按margin空间来算的,如果右边元素很宽,那么居中就不准确,所有才有上面第二种真正的居中。

所以,巧用margin!!!
总结下,flex弹性布局在于,对于宽高不固定的元素,可以很好的设置比例来使得元素按比例缩放。

虽然上面元素都是固定宽高的。

第四:实操:用flex来实现各种网站的布局

第一个案例

原图:右边一个按钮靠右,左边图标,中间区块,在缩小宽度后会下移:

image.png

我作出来的效果(忽略文字差异):

image.png

右边使用头部导航区块容器内的绝对定位,左侧两个区块使用flex并设置换行,伪代码如下:

    <div 定位锚点>
    
        <div flex布局>
            <ul></ul>
            <ul 自动换行></ul>
        </div>
        
        <div 绝对定位>右侧浮动</div>
        
    </div>

第二个案例

如下图:

image.png

可以看到,导航条被分为两边,两边内容居中。

这是我做出的效果:

image.png

直接一个ul作为flex容器,通过设置里头的li的margin来分区域:

        ul.center {
            display: flex;
            justify-content: center;
        }

        ul li:nth-of-type(1) {
            margin-left: auto;
        }

        ul li:nth-of-type(3) {
            margin-right: auto;
        }

        ul li:last-of-type {
            margin-right: auto;
        }

当然,这样是按相等的margin区域来平均分布的。

第四个案例

来做一个简单的整体页面布局,我随机打开一个网站:

image.png

这个网页布局,顶上导航条是跟下面内容面板区域分开的。

而且导航条宽度固定,使用fixed即可,这个导航条明显是左右浮动布局:

image.png

关键代码如下:

        <div class="container">
            <div class="header">
                <div class="center">
                    <ul class="left">
                        <li class="noted">Diego</li>
                    </ul>
                    <ul class="right">
                        <li>Jayla</li>
                    </ul>
                </div>
            </div>

            <div class="main">
                <div class="content">
                    <br>
                </div>
                <div class="box">
                    <div></div>
                    <div></div>
                    <div></div>
                </div>
            </div>
        </div>

给container容器设置min-height高度为适应屏幕高度100vh,min-width宽度为最大元素的宽度:

        .container {
            min-height: 100vh;
            min-width: 900px;
            background-color: #e1e1e1;
        }
        
        .header {
            position: fixed;
            left: 0;
            right: 0;
            top: 0;
            display: block;
            height: 52px;
            background-color: rgba(249, 249, 249, 0.5);
        }

        .center {
            width: 900px;
            margin: 0 auto;
        }

        ul.left {
            float: left;
        }

        ul.right {
            float: right;
        }
        
        .main {
            display: flex;
            overflow: auto;
            justify-content: center;
            margin-top: 52px;
        }
  • 这里指出float浮动的一个特点,子元素设置float之后,
  • 宽高将不占用兄弟元素的宽高空间,只排斥文本内容空间
  • 同时,子元素也不会撑开父元素的宽高边框,自由溢出父元素区域。
  • float子元素想要撑开父元素的宽高,则在父元素加上overflow溢出能够滚动,auto或scroll。
  • 另一种清除float父元素高度坍塌的办法是 parent:after { display: block; clear :both ;}
  • inline和inline-block无法清除左右浮动! overflow会存在滚动,所以还是用after最好。

给右边区块 加上媒体查询@media 判断,如果宽度太小,就改为隐藏:

image.png

如上图,当宽度变小后,自动收缩右边区块,使用按钮点击来展示/隐藏。

        @media screen  and (  max-width: 670px ) {

            .main a.nav-btn {
                visibility: visible;
            }
        }
    let mediaQuery = window.matchMedia("(min-width: 671px)");
    mediaQuery.addEventListener("change", e => {
        mediaMatch(e);
    });

    function mediaMatch(mediaQuery) {
        if (mediaQuery.matches) {
            right.style.visibility = "visible";
        } else {
            right.style.visibility = "hidden";
        }
    }

image.png

如上图,加上隐藏头部导航和图标上移下移功能

    let beforeScrollTop = htmlElem.scrollTop;
    document.addEventListener("scroll", e => {
        let delta = htmlElem.scrollTop - beforeScrollTop;
        beforeScrollTop = htmlElem.scrollTop;
        
        if (delta === 0) {
            return false;
        } else if (delta > 0) {
            headerElem.style.top = "-52px";
        } else {
            headerElem.style.top = "0";
        }
    });
    
    //transition: top 1s; 动画效果

grid二维布局(除非布局复杂且以后结构相对不变,否则不建议)

具体就是把一个区域划分为行列网格,然后通过设置一个个区块占网格里的哪些部分,来标记好这些区域后,样式就可以应用到具体区块上。

略。

一些问题和技巧记录:

tips:外边距合并问题 --跟清除浮动类似

  • 1、父元素边框和子元素边框之间没有任何元素和内容,那么子元素的外边距会贴着父元素传到外面
  • 还有上下兄弟元素直接没有阻挡,那么外边距会相互渗透合并
  • 解决办法:
  • 1、给子元素套个容器,容器设置overflow:hidden之类,容器就会把子元素外边距包进去。
  • overflow不好的地方:多了一层标签
  • 2、给贴合的边距设置1px的透明边框或者1px padding,也不好,多了1px
  • 3、使用before、after设置content:“1”,block,fontsize设为0。同时清除浮动和边距合并问题。
/* 清除浮动 和外边距合并 */
    .clear-after::after {
        content: "1"; /* 不能为空 */
        display: block;
        font-size: 0;
        clear: both;
    }

    .clear-before::before {
        content: "1"; /* 不能为空 */
        display: block;
        font-size: 0;
        clear: both;
    }

tips:水平居中问题

  • 1、凡是内盒子宽度固定,使用margin: 0 auto;
    <div class="parent">
        <div class="box">sss
        </div>
    </div>
    
       .box {
       
            width: 100px;
            margin: 0 auto;
        }
  • 2、内盒子宽度不固定,把外盒子变成flex布局(或者直接加上 外盒子{text-align: center;}
        .parent {
            display: flex;
            justify-content: center;
        }
  • 3、内盒子宽度不固定,不想给外盒子加属性,使用margin: 0 auto;加上 display: table;
.box {
    outline: 2px dashed blue;
    margin: 0 auto;
    display: table;
}