前端基础 1 :CSS布局

一般而言,一个静态web页面的呈现需要通过html和css配合实现。html相当于页面的骨架,规定了文档的结构。css相当于皮肤,使得页面能够按一定的方式进行呈现。

  • HTML使用语义化的标签,规定了页面的结构:页面里面有什么元素,以及各个元素之间的关系。元素之间的关系包括在文档流中的先后关系,以及嵌套关系(DOM树中的父子)等等。
  • css规定了页面元素的呈现,如文字的对齐方式,字体,块的背景色等等。此外,css的一个重要作用是实现页面的布局。

目前,web页面的布局是通过css实现的。css实现页面的布局也有两种主要方式:

  • 传统布局:使用float属性以及position定位进行布局,局限性在于难以实现垂直居中等效果。
  • flex布局:一种简单灵活的布局方式,适合创建针对屏幕尺寸不同的设备的响应式页面,但是不适合于很复杂的布局。

本文使用百度前端学院的两个题目作为实例,简单描述这两种布局方式的使用,并对它们做一个简单的比较。



1. 传统布局


1.1 传统的布局要素

传统布局主要使用了两个要素:浮动(float)和定位(position)。

1.1.1 浮动

浮动的框可以向左或向右移动,直到它的外边缘碰到包含框或另一个浮动框的边框为止。由于浮动框不在文档的普通流中,所以文档的普通流中的块框表现得就像浮动框不存在一样。但是浮动框可能会覆盖住普通流中的框,布局的时候需要对普通流中的元素设置一定的外边距,避免被浮动的框盖住。
使用浮动的方法很简单,只需要在需要浮动的元素的css里面作如下设置:

float : left / right ;

浮动会带来一个副作用:因为浮动元素脱离了文档流,所以包围图片和文本的 div 不占据空间,导致无法撑开包含浮动的元素(如div)。解决该问题的一个方案是在包含浮动元素的元素最后面加上一个空的div,该div的clear属性设为"both"。

1.1.2 定位

定位的基本思想很简单,它允许你定义元素框相对于其正常位置应该出现的位置,或者相对于父元素、另一个元素甚至浏览器窗口本身的位置。

CSS 有三种基本的定位机制:普通流、浮动和绝对定位。除非专门指定,否则所有框都在普通流中定位。也就是说,普通流中的元素的位置由元素在 HTML 文档中的位置决定。

通过使用position属性,我们可以选择 4 种不同类型的定位:

  • static:元素框正常生成。块级元素生成一个矩形框,作为文档流的一部分,行内元素则会创建一个或多个行框,置于其父元素中。
  • relative:元素框偏移某个距离。元素仍保持其未定位前的形状,它原本所占的空间仍保留。
  • absolute:元素框从文档流完全删除,并相对于其包含块定位。包含块可能是文档中的另一个元素或者是初始包含块。元素原先在正常文档流中所占的空间会关闭,就好像元素原来不存在一样。元素定位后生成一个块级框,而不论原来它在正常流中生成何种类型的框。
  • fixed:元素框的表现类似于将 position 设置为 absolute,不过其包含块是视窗本身。

提示:相对定位实际上被看作普通流定位模型的一部分,因为元素的位置相对于它在普通流中的位置。
注意:行框和行内框不是一回事,行框的高度总是能包括它包含的所有行内框。


1.2 传统布局方式实例

1.2.1案例一

这是百度前端学院的一道题目:

任务描述

  • 使用 HTML 与 CSS 按照 示例图(点击查看) 实现三栏式布局。
  • 左右两栏宽度固定,中间一栏根据父元素宽度填充满,最外面的框应理解为浏览器。背景色为 #eee 区域的高度取决于三个子元素中最高的高度。
    任务注意事项
  • 尝试 position 和 float 的效果,思考它们的异同和应用场景。
  • 注意测试不同情况,尤其是极端情况下的效果。
  • 图片和文字内容请自行替换,尽可能体现团队的特色。
  • 调节浏览器宽度,固定宽度和自适应宽度的效果始终符合预期。
  • 改变中间一栏的内容长度,以确保在中间一栏较高和右边一栏较高时,父元素的高度始终为子元素中最高的高度。
  • 其他效果图中给出的标识均被正确地实现。

要实现的效果如图所示:


案例一示例图

实现此效果的代码如下:

<!doctype html>
<html>

<head>
<meta charset="utf-8">
<title>This is the title~~</title>
<style>
body
{
    margin:0;
    padding:0;
}

.container
{
    margin:20px;
    padding:20px;
    background-color:#eee;
    border:2px solid #999;
}

.left
{
    margin:0;
    padding:20px;
    background-color: white;
    border:2px solid #999;
    width:160px;
    float:left;
}

.right
{
    margin:0;
    padding:0 20px;
    background-color: white;
    border:2px solid #999;
    width:80px;
    float:right;
}

.middle
{
    margin:0 140px 0 220px;
    padding:20px;
    background-color: white;
    border:2px solid #999;
}

.img
{
    margin:0;
    float:left;
    text-align: center;
    background-color:gray;
    color:white;
    width:80px;
    height:80px;
}

.right-img
{
    margin:20px 0 20px 0;
    float:left;
    text-align: center;
    background-color:gray;
    color:white;
    width:80px;
    height:80px;
}

.left > p
{
    float:left;
    margin:0 20px;
}


.clear
{
    clear:both;
}

</style>
</head>

<body>
    <div class="container">
        <div class="left">
            <div class="img">
                <p>logo</p>
            </div>
            <p>队名</p>
            <div class="clear"></div>
        </div>

        <div class="right">
            <div class="right-img">
                <div>
                    <p>王尼玛的logo</p>
                </div>
            </div>
            <div class="right-img">
                <div>
                    <p>王尼玛的logo</p>
                </div>
            </div>
            <div class="right-img">
                <div>
                    <p>王尼玛的logo</p>
                </div>
            </div>
            <div class="right-img">
                <div>
                    <p>王尼玛的logo</p>
                </div>
            </div>
            <div class="clear"></div>
        </div>

        <div class="middle">
            <p>前端工程师的职责是制作标准优化的代码,并增加交互动态功能,开发JavaScript以及Flash模块,同时结合后台开发技术模拟整体效果,进行丰富互联网的Web开发,致力于通过技术改善用户体验。前端工程师,属于IT技术职业的一种,是近5年发展起来的职业,旧的体系将其定义为Web前端工程师,主要的技术包含:HTML、JavaScript、CSS。但IT技术属于变化比较快的领域,最近发生了很大的变革,新的体系下,前端工程师技术又增加了:nodejs、Hybrid App。Node.js是一个Javascript运行环境(runtime)。实际上它是对Google V8引擎进行了封装。V8引 擎执行Javascript的速度非常快,性能非常好。Node.js对一些特殊用例进行了优化,提供了替代的API,使得V8在非浏览器环境下运行得更好。Hybrid App(混合模式移动应用)是指介于web-app、native-app这两者之间的app,兼具“Native App良好用户交互体验的优势”和“Web App跨平台开发的优势”。主要采用JavaScript语言作为中间语言开发。因此,前端工程师所涵盖的职责范围,已经包含后端、跨平台等多种职能,不能简单地认为只是Web前端工程师。</p>
        </div>
        <div class="clear"></div>

    </div>
</body>

</html>

1.2.1案例二


这是百度前端学院的另一道题目,用绝对定位来实现布局。值得注意的是,绝对定位的位置值是相对于最近的已定位的祖先元素,而不一定是body本身。

任务描述

  • 实现如 示例图(点击打开) 的效果
  • 灰色元素水平垂直居中,有两个四分之一圆位于其左上角和右下角。
    任务注意事项
  • 思考不同情况下(如灰色高度是根据内容动态变化的)水平垂直居中的解决方案。
  • 动手试一试各种情况的组合,父元素和子元素分别取不同的 position 值。思考 position 属性各种取值的真正含义,尤其是 absolute 究竟是相对谁而言的。
  • 注意测试不同情况,尤其是极端情况下的效果。
  • 调节浏览器宽度,灰色元素始终水平居中。
  • 调节浏览器高度,灰色元素始终垂直居中。
  • 调节浏览器高度和宽度,黄色扇形的定位始终准确。

要实现的效果如图所示:


案例二示例图

实现此效果的代码如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Task1-4 demo</title>
    <style>
    body
    {
        margin:0;
        padding:0;
    }
    .parent
    {
        margin:-100px 0 0 -200px;
        padding:0;
        width:400px;
        height:200px;
        background-color:lightgray;
        border:2px solid gray;
        position:absolute;
        left:50%;
        top:50%;
    }
    .left
    {
    margin:0;
    padding:0;
    width:50px;
    height:50px;
    background-color:yellow;
    border:2px solid yellow;
    border-bottom-right-radius:50px; 
    position:absolute;
    top:0;
    left:0;
    }

    .right
    {
    margin:0;
    padding:0;
    width:50px;
    height:50px;
    background-color:yellow;
    border:2px solid yellow;
    border-top-left-radius:50px; 
    position:absolute;
    top:150px;
    left:350px;
    }

    </style>
</head>

<body>
    <div class="parent">
        <div class="left"></div>
        <div class="right"></div>
    </div>
</body>

</html>

2. flex布局


2.1 flex布局要素

因为Flexbox是整个模块,而不是一个属性,它涉及很多东西,包括其整个组属性。他们当中一部分是容器(父元素,称为“伸缩容器”),另一部分是子元素(称为“伸缩项目”)。

常规布局是基于块和内联流方向,而Flex布局是基于flex-flow流。请看看来自w3c规范中的这张图,解释了flex布局的主要思想。


一个完整的Flexbox指南

根据伸缩项目排列方式不同,主轴和侧轴方向也有所变化


一个完整的Flexbox指南

基本上,伸缩项目是沿着主轴(main axis),从主轴起点(main-start)到主轴终点(main-end)或者沿着侧轴(cross axis),从侧轴起点(cross-start)到侧轴终点(cross-end)排列。
主轴(main axis):伸缩容器的主轴,伸缩项目主要沿着这条轴进行排列布局。小心,它不一定是水平的;这主要取决于“justify-content”属性(详细见下文)。
主轴起点(main-start)和主轴终点(main-end):伸缩项目放置在伸缩容器内从主轴起点(main-start)向主轴终点(main-start)方向。
主轴尺寸(main size):伸缩项目在主轴方向的宽度或高度就是主轴的尺寸。伸缩项目主要的大小属性要么是宽度,要么是高度属性,由哪一个对着主轴方向决定。
侧轴(cross axis):垂直于主轴称为侧轴。它的方向主要取决于主轴方向。
侧轴起点(cross-start)和侧轴终点(cross-end):伸缩行的配置从容器的侧轴起点边开始,往侧轴终点边结束。
侧轴尺寸(cross size):伸缩项目的在侧轴方向的宽度或高度就是项目的侧轴长度,伸缩项目的侧轴长度属性是「width」或「height」属性,由哪一个对着侧轴方向决定。

2.2 flex布局语法

分伸缩容器和伸缩项目两部分进行介绍。

2.1.1 伸缩容器属性

  • display:flex | inline-flex(还可以取none/block/inline等值,此时用途就不是flex布局
    这个是用来定义伸缩容器,是内联还是块取决于设置的值。这个时候,他的所有子元素将变成flex文档流,称为伸缩项目。

  • flex-direction:row | row-reverse | column | column-reverse
    这个主要用来创建主轴,从而定义了伸缩项目放置在伸缩容器的方向。

  • row(默认值):在“ltr”排版方式下从左向右排列;在“rtl”排版方式下从右向左排列。

  • row-reverse:与row排列方向相反,在“ltr”排版方式下从右向左排列;在“rtl”排版方式下从左向右排列。

  • column:类似 于row,不过是从上到下排列

  • column-reverse:类似于row-reverse,不过是从下到上排列。

  • flex-wrap: nowrap | wrap | wrap-reverse
    这个主要用来定义伸缩容器里是单行还是多行显示,侧轴的方向决定了新行堆放的方向。

  • nowrap(默认值):伸缩容器单行显示,“ltr”排版下,伸缩项目从左到右排列;“rtl”排版上伸缩项目从右向左排列。

  • wrap:伸缩容器多行显示,“ltr”排版下,伸缩项目从左到右排列;“rtl”排版上伸缩项目从右向左排列。

  • wrap-reverse:伸缩容器多行显示,“ltr”排版下,伸缩项目从右向左排列;“rtl”排版下,伸缩项目从左到右排列。(和wrap相反)

  • flex-flow:这个是“flex-direction”和“flex-wrap”属性的缩写版本。同时定义了伸缩容器的主轴和侧轴。其默认值为“row nowrap”。

  • justify-content:flex-start | flex-end | center | space-between | space-around
    这个是用来定义伸缩项目沿着主轴线的对齐方式。当一行上的所有伸缩项目都不能伸缩或可伸缩但是已经达到其最大长度时,这一属性才会对多余的空间进行分配。当项目溢出某一行时,这一属性也会在项目的对齐上施加一些控制。

  • flex-start(默认值):伸缩项目向一行的起始位置靠齐。

  • flex-end:伸缩项目向一行的结束位置靠齐。

  • center:伸缩项目向一行的中间位置靠齐。

  • space-between:伸缩项目会平均地分布在行里。第一个伸缩项目一行中的最开始位置,最后一个伸缩项目在一行中最终点位置。

  • space-around:伸缩项目会平均地分布在行里,两端保留一半的空间。

一个完整的Flexbox指南
  • align-items: flex-start | flex-end | center | baseline | stretch
    这个主要用来定义伸缩项目可以在伸缩容器的当前行的侧轴上对齐方式。可以把他想像成侧轴(垂直于主轴)的“justify-content”。
  • flex-start:伸缩项目在侧轴起点边的外边距紧靠住该行在侧轴起始的边。
  • flex-end:伸缩项目在侧轴终点边的外边距靠住该行在侧轴终点的边 。
  • center:伸缩项目的外边距盒在该行的侧轴上居中放置。
  • baseline:伸缩项目根据他们的基线对齐。
  • stretch(默认值):伸缩项目拉伸填充整个伸缩容器。此值会使项目的外边距盒的尺寸在遵照「min/max-width/height」属性的限制下尽可能接近所在行的尺寸。
一个完整的Flexbox指南
  • align-content: flex-start | flex-end | center | space-between | space-around | stretch
    这个属性主要用来调准伸缩行在伸缩容器里的对齐方式。类似于伸缩项目在主轴上使用“justify-content”一样。请注意本属性在只有一行的伸缩容器上没有效果。
  • flex-start:各行向伸缩容器的起点位置堆叠。
  • flex-end:各行向伸缩容器的结束位置堆叠。
  • center:各行向伸缩容器的中间位置堆叠。
  • space-between:各行在伸缩容器中平均分布。
  • space-around:各行在伸缩容器中平均分布,在两边各有一半的空间。
    stretch(默认值):各行将会伸展以占用剩余的空间。
一个完整的Flexbox指南

2.2.2 伸缩项目属性

注意:float、clear和vertical-align在伸缩项目上没有效果。

  • order:<integer>
    默认情况下,伸缩项目是按照文档流出现先后顺序排列。然而,“order”属性可以控制伸缩项目在他们的伸缩容器出现的顺序。

  • flex-grow:<number> (默认值为: 0)
    根据需要用来定义伸缩项目的扩展能力。它接受一个不带单位的值做为一个比例。主要用来决定伸缩容器剩余空间按比例应扩展多少空间。如果所有伸缩项目的“flex-grow”设置了“1”,那么每个伸缩项目将设置为一个大小相等的剩余空间。如果你给其中一个伸缩项目设置了“flex-grow”值为“2”,那么这个伸缩项目所占的剩余空间是其他伸缩项目所占剩余空间的两倍。
    负值同样生效。

  • **flex-shrink **:<number> (默认值为: 1)
    根据需要用来定义伸缩项目收缩的能力。负值同样生效。

  • flex-basis:<length> | auto (默认值为: auto)
    这个用来设置伸缩基准值,剩余的空间按比率进行伸缩。负值不合法。

  • flex: none | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
    这是“flex-grow”、“flex-shrink”和“flex-basis”三个属性的缩写。其中第二个和第三个参数(flex-shrink、flex-basis)是可选参数。默认值为“0 1 auto”。

  • align-self:auto | flex-start | flex-end | center | baseline | stretch
    用来在单独的伸缩项目上覆写默认的对齐方式。属性值的介绍请参阅“align-items”的属性值。


2.3 flex布局实例

这是百度前端学院的一道题目:

任务目的
学习如何flex进行布局,学习如何根据屏幕宽度调整布局策略。
任务描述
需要实现的效果如效果图(点击打开)所示,调整浏览器宽度查看响应式效果,红色的文字是说明,不需要写在 HTML 中。
任务注意事项

  • 只需要完成HTML,CSS代码编写,不需要写JavaScript
  • 屏幕宽度小于 640px 时,调整 Flexbox 的属性以实现第四个元素移动到最前面的效果,而不要改动第一个元素的边框颜色与高度实现效果图。
  • 思考 Flexbox 布局和网格布局的异同,以及分别适用于什么样的场景。可以搜索一下别人的结论,不过要保持思辨的态度,不可直接接受别人的观点。
  • HTML 及 CSS 代码结构清晰、规范

要实现的效果如图所示:


flex布局效果图

实现此效果的代码如下:

<!DOCTYPE html>
<html>

<head>
<title>Flex布局</title>
<meta charset="utf-8">
<style>
body
{
  margin:0;
  padding:0;
}

div#container
{
  margin:0;
  padding:20px;
  display:flex;
  flex-direction: row;
  flex-wrap:wrap;
  align-content: space-between;
}

div#box1 { width:150px; height:120px; border: 1px solid #f00;}

div#box2 { width:150px; height: 100px; border: 1px solid #f00; }

div#box3 { width:150px; height:40px; border: 1px solid #f00; }

div#box4 {width:150px; height:200px;border: 1px solid #00f; }

@media all and (min-width: 640px)/*针对大屏幕设备(宽度大于640px)的样式*/
{
div#container
{
  justify-content:space-between;
  align-items:center;
}
}

@media all and (max-width: 640px)/*针对小屏幕设备(宽度小于640px)的样式*/
{
    div#container
    {
        justify-content:space-between;
        align-items:flex-start;
    }
    div#box1 { order:2; }
    div#box2 { order:3; }
    div#box3 { order:4; }
    div#box4 { order:1;}
}
</style>
</head>

<body>
  <div id="container">
    <div id="box1"></div>
    <div id="box2"></div>
    <div id="box3"></div>
    <div id="box4"></div>
  </div>
</body>
</html>


3. 两种布局方式的比较

Flexbox布局(Flexible Box)模块旨在提供一个更加有效的方式制定、调整和分布一个容器里的项目布局,即使他们的大小是未知或者是动态的。(这里我们称为Flex)。Flex布局主要思想是让容器有能力让其子项目能够改变其宽度、高度(甚至顺序),以最佳方式填充可用空间(主要是为了适应所有类型的显示设备和屏幕大小)。Flex容器会使子项目(伸缩项目)扩展来填满可用空间,或缩小他们以防止溢出容器。最重要的是,Flexbox布局方向不可预知,他不像常规的布局(块就是从上到下,内联就从左到右)。而那些常规的适合页面布局,但对于支持大型或者杂的应用程序(特别是当他涉及到取向改变、缩放、拉伸和收缩等)就缺乏灵活性。
注:Flexbox布局最适合应用程序的组件和小规模的布局,而网格布局更适合那些更大规模的布局。



附录:参考教程

  1. <a href="http://www.w3cplus.com/css3/a-guide-to-flexbox.html">一个完整的Flexbox指南</a>
  2. <a href="http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html">Flex 布局教程:语法篇</a>
  3. <a href="http://www.ruanyifeng.com/blog/2015/07/flex-examples.html">Flex 布局教程:实例篇</a>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容

  • 问答题47 /72 常见浏览器兼容性问题与解决方案? 参考答案 (1)浏览器兼容问题一:不同浏览器的标签默认的外补...
    _Yfling阅读 13,725评论 1 92
  • H5移动端知识点总结 阅读目录 移动开发基本知识点 calc基本用法 box-sizing的理解及使用 理解dis...
    Mx勇阅读 4,389评论 0 26
  • 移动开发基本知识点 一.使用rem作为单位 html { font-size: 100px; } @media(m...
    横冲直撞666阅读 3,452评论 0 6
  • flex布局基础知识 main axis(主轴): Flex容器的主轴主要用来配置Flex项目。它不一定是水平,这...
    前端小兵阅读 486评论 0 1
  • 选择qi:是表达式 标签选择器 类选择器 属性选择器 继承属性: color,font,text-align,li...
    love2013阅读 2,301评论 0 11