王鹏飞

Blog

Tutorial

About

CSS📚开源

布局

当你构建一个组件或者页面时,有多种布局方式可供选择,本节内容是各种布局的一个概览。

假设你是一个开发者,此时一个设计专业的同事递给你一份新的网站设计稿让你开发。这份设计稿有很多有趣的布局和组件,有二维布局,也有非常灵活可流动的布局。你怎么去选择最好的css布局方式呢?

CSS为我们提供了多种布局方式,有水平轴布局,垂直轴布局或者水平和竖直混合布局。选择一个正确的布局方式往往很困难,通常你需要多个布局方式去解决问题。为了解决这些,在接下来的几个模块,你将会学习css的布局机制。

二.display属性

display属性做了两件事。第一件事是他决定一个盒子是否表现为inline或者block

.my-element {
    display: inline
}

inline元素被称为行内元素,行内元素就像一段语句中的一个单词。它们在行内方向上紧挨着彼此。像<span><strong>元素就是典型的行内元素,它们在<p>(段落,<p>是一个block元素,后面将会介绍block元素)中都是紧挨着彼此的。它们同样拥有周围的空间,即paddingbordermargin属性都是有效的。

css布局

你无法设置行内元素的widthheight属性。block层级的margin和padding将会被周围的元素忽略(这句话的英文原文是Any block level margin and padding will be ignored by the surrounding elements,我不清楚这样翻译是否合适)。

block元素,即块元素,它们并不是紧挨着其他元素的。它们在页面中会自动生成新的一行。块元素在行内方向上会扩展尺寸,因此它们会占据水平方向100%宽度。块元素任意方向的边距将不会被忽略。

.my-element {
    display: block;
}

display属性还可以决定元素的子元素的行为。例如设置display: flex,使元素盒子成为一个block层级的盒子(块元素),并且将子元素变成flex项目(item)。这会启用flex属性,flex属性可以用来控制子元素的布局方式(对其、排序、流动)。

二.flex和Grid

flex(弹性布局)和grid(格子布局)是为多个元素创建布局规则的两种主要布局机制。它们有很多共同点,但是却是被设计出来去解决不同的布局问题的。

在后面的章节内容,我将会更详细的介绍弹性布局和格子布局的内容。但是目前我们仅大致看下这两种布局方式,了解它们的功能。

首先明确两个概念:

  • flex/grid盒子(简称盒子):display属性设置为flex或者grid的元素被称为盒子。
  • flex/grid项目(简称项目):flex/grid盒子元素的直接子元素,不包含孙子元素。

弹性布局

.my-element {
    display: flex;
}

弹性布局主要用于一维布局。布局方向是单轴的,可以是水平方向或者竖直方向。默认情况下,弹性布局会在内联方向上(水平方向)排列元素,flex项目会紧挨着彼此,并且会在块方向上(竖直方向)被拉伸,所以项目与盒子高度相同。

flex项目会保持同轴排列,在超过flex盒子范围时,并不会换行,而是被自动压缩宽度排列。可以通过align-itemsjustify-contentflex-wrap改变这一默认行为。

你也可以通过flex属性设置flex项目如何压缩、拉伸尺寸。

.my-element {
    flex: 1 0 auto;
}

flex属性是flex-growflex-shrinkflex-basis三个属性的混合写法。你可以将上面的例子改写为:

.my-element {
    flex-grow: 1;
    flex-shrink: 0;
    flex-basis: auto;    
}

开发人员提供这些低级规则,以提示浏览器当视口尺寸发生变化时如何布局元素。这使得弹性布局非常适合设计响应式网页。

格子布局

.my-element {
    display: grid;
}

格子布局(Grid)与弹性布局(flex)非常相似,但是格子布局是为多轴布局而设计的。

格子布局引入了一些新的布局基础规则,例如repeat()minmax()函数。还有一个fr单位,用来描述分配剩余空间的弹性系数。你可以创建一个12列,每列之间有一个空白间距的布局。

.my-element {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 1rem;
}

你还可以通过格子布局设置二维布局。我们可以设置第一个grid项目占据两行三列的空间。

.my-element :first-child {
    grid-row: 1/3;
    grid-column: 1/4;
}

通过grid-rowgrid-column属性设置盒子中第一个元素水平占据空间从第一列到第四列,竖直占据空间从第一行到第三行。

flow布局

如果不使用弹性布局和格子布局,你的元素将会显示为正常文档流。还有一些布局方式可以在正常文档流中改变元素的行为和位置。

inline-block

前面提到过,内联元素的块方向上的边距(margin和padding)将会被周围的元素忽略。通过设置inline-block,可以使内联元素的块方向上的边距不会被忽略。

p span {
    display: inline-block;
}

使用inline-block可以让一个盒子拥有块元素的一些特性,但是仍然在处于内联文档流中,与其他元素紧挨着。

p span {
    margin-top: 0.5rem;
}

Floats

如果一个段落中有一张图片,但是你想让文字环绕在图片周围,就像杂志一样。你可以使用floats特征去完成这种效果:

img {
    float: left;
    margin-right: 1em;
}

float属性指示元素朝着指定方向流动。例子中的图片被指示朝着左侧流动,并且允许它的姐妹元素环绕着它。你可以设置float属性为leftrightinherit等值。

注意:当你使用float属性,你要记住所有在float元素后的元素的布局都会被调整。为了防止这种情况,你可以清除float效果,可以通过设置float元素后面的元素clear: both属性值,也可以通过为float元素的父元素添加display: flow-root属性值。

多列布局

如果有一个很长的列表,你可以通过column-count设置列表的列数,通过column-gap设置列表的列间距。

.countries {
    column-count: 2;
    column-gap: 1em;
}

上面的例子,会自动将列表分成两列,并且在列之间添加一个空白间距。

也可以通过设置column-width,然后通过列表宽度,自动划分列数。

.countries {
    width: 100%;
    column-width: 260px;
    column-gap: 1em;
}

position

position属性会改变元素在正常文档流中的表现和它与其他元素之间的关系。可用的属性值由staticrelativeabsolutefixedsticky。默认值为static

  • static:该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。

  • relative: 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative对table-row, table-column, table-cell, table-caption 元素无效。

  • absolute:元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非 static定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。

  • fixed:元素会被移出正常文档流,并不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed属性会创建新的层叠上下文。当元素祖先的transform,perspective或filter属性非 none 时,容器由视口改为该祖先。

  • sticky:元素根据正常文档流进行定位,然后相对它的最近滚动祖先(nearest scrolling ancestor)和containing block(最近块级祖先nearest block-level ancestor),包括table-related元素,基于top、right、bottom和left的值进行偏移。偏移值不会影响任何其他元素的位置。

可以在这里获得更详细的内容。

(完)

007 尺寸单位
009 flex布局

留言(0


发表评论

邮箱地址不会被公开。*表示必填项