学习层叠样式表(CSS,cascading style sheets)最好的方法,就是无论三七二十一,直接上手写代码。css
Tim Berners-Lee 在 1990 年发明了 HTML,当时是为了规范科研文档的格式。HTML 是一种简单的标记语言,为文本赋予了基本的结构和意义,好比标题、列表、定义等。这些文档一般没有什么装饰性的元素,能够方便地经过计算机来检索,而人类可使用文本终端、Web 浏览器,或者必要时使用屏幕阅读器来阅读它们。html
CSS1 是在 1996 年末成为 W3C 推荐标准的,当时只包含字体、颜色和外边距等基本的属性。CSS2 在 1998 年成为推荐标准,增长了浮动和定位等高级特性,此外还有子选择符、相邻选择符和通用选择符等新选择符。git
相比之下,CSS3 则采用了彻底不一样的模式。实际上不存在所谓的 CSS3 规范,由于 CSS3 指的是一系列级别独立的模块。若是规范模块是对以前 CSS 概念的改进,那就从 3 级(level 3)开始命名。若是不是改进,而是一种全新的技术,那就从 1 级(level 1)开始命名。github
若是但愿根据浏览器是否支持某个 CSS 特性来提供彻底不一样的样式,那么能够选择 @supports 块。这个特殊的代码块称为条件规则,它会检测括号中的声明,而且仅在浏览器支持该声明的状况下,才会应用块中的规则:算法
@supports (display: grid) {
/* 在支持网格布局的浏览器中要应用的规则 */
}
复制代码
条件规则的问题是其自身也很新,只能将它应用于新的浏览器中,由于旧版本浏览器不支持。浏览器
语义化标记意味着在正确的地方使用正确的元素,从而获得有意义的文档。语义明确的元素有:网络
h1
、h2
等p
、ul
、ol
和 dl
strong
和 em
blockquote
和 cite
pre
和 code
time
、figcaption
和 caption
HTML5 新增了一批结构化元素:app
section
header
footer
nav
article
aside
main
<b>
和 <div>
能够算是幸存的表现性标记了,它们在排版上会分别显示为粗体(bold)和斜体(italic)。这两个元素与 <strong>
和 <em>
的区别在于,它们没有任何强调本身所包含内容的意味。多数状况下,应该选择 <strong>
或 <em>
,由于它们是用来强调及重点强调内容的语义正确的选择。ide
微格式是一组标准的命名约定和和标记模式,可用于表示特定的数据类型。微格式的命名约定是基于 vCard 和 iCalendar 等已有的数据格式制定的。好比下面的联系人信息就是以 hCard 格式标记的:布局
<section class="h-card">
<p>
<a class="u-url p-name" href="http://andybudd.com/">Andy Budd</a>
<span class="p-org">Clearleft Ltd</span>
<a class="u-email" href="mailto:info@andybudd.com">info@andybudd.com</a>
</p>
<p class="p-adr">
<span class="p-locality">Brighton</span>
<span class="p-country-name">England</span>
</p>
</section>
复制代码
微数据是跟 HTML5 一块儿,做为给 HTML 添加结构化数据的另外一种方式而推出的。它的目标与微格式很是接近,但在把微数据嵌入内容方面则有所不一样。下面是微数据标记联系人信息:
<section itemscope itemtype="http://schema.org/Person">
<p><a itemprop="name" href="http://thatemil.com/">Emil Bojoklund</a></p>
<p itemprop="affiliation" itemscope itemtype="http://schema.org/Organization">
<span itemprop="name">inUse Experience AB</span>
<a itemprop="email" href="mailto:emil@thatemil.com">emil@thatemil.com</a>
</p>
<p itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
<span class="addressLocality">Malm?</span>,
<span class="addressCountry">Sweden</span>
</p>
</section>
复制代码
有效且结构良好的文档是添加样式的基础。
类型选择符用于选择特定类型的元素。类型选择符有时候也被称为元素选择符。
p {
color: black;
}
复制代码
后代选择符用于选择某个或某组元素的后代。
blockquate p {
padding-left: 2em;
}
复制代码
要想更精确地选择目标元素,可使用 ID 选择符(#
)和类选择符(.
)。
#intro {
font-weight: bold;
}
.date-posted {
color: #ccc;
}
复制代码
与后代选择符会选择一个元素的全部后代不一样,子选择符(>
)只选择一个元素的直接后代,也就是子元素。
#nav > li {
background: url(folder.png) no-repeat left top;
padding-left: 20px;
}
复制代码
<ul id="nav">
<li>Home</li>
<li>
Services
<ul>
<li>Design</li>
<li>...</li>
</ul>
</li>
<li>Contact Us</li>
</ul>
复制代码
上面嵌套的 <ul>
下的 <li>
的样式不会受到影响。
相邻同辈选择符(+
)能够选择位于某个元素后面,并与该元素拥有共同父元素的元素。
h2 + p {
font-size: 1.4em;
font-weight: bold;
color: #777;
}
复制代码
通常同辈选择符(~
)能够选择位于某个元素后面的全部该元素拥有共同父元素的元素。
h2 ~ p {
font-size: 1.4em;
font-weight: bold;
color: #777;
}
复制代码
相邻同辈选择符和通常同辈选择符都不会选择前面的同辈元素。
通用选择符(*
)能够匹配任何元素。
* {
margin: 0;
padding: 0;
}
复制代码
事实上,这样写可能带来不少意想不到的后果,特别是会影响 <button>
、<select>
等表单元素。若是想重设样式,最好仍是像下面这样明确指定元素:
h1,
h2,
h3,
h4,
h5,
h6,
ul,
ol,
li,
dl,
p {
margin: 0;
padding: 0;
}
复制代码
属性选择符基于元素是否有某个属性或者属性是否有某个值来选择元素。
abbr[title] {
border-bottom: 1px dotted #999;
}
input[type='submit'] {
cursor: pointer;
}
/* 匹配以某些字符开头的属性值 */
a[href^='http:'] {
}
/* 匹配以某些字符结尾的属性值 */
img[src$='.jpg'] {
}
/* 匹配包含某些字符的属性值 */
a[href*='/about/'] {
}
/* 匹配以空格分隔的字符串中的属性值 */
a[rel~='next'] {
}
复制代码
有时候咱们想选择的页面区域不是经过元素来表示的,而咱们也不想为此给页面添加额外的标记。CSS 为这种状况提供了一些特殊选择符,叫伪元素。
.chapter::before {
content: '“';
font-size: 10em;
}
.chapter p::first-letter {
float: left;
font-size: 3em;
}
复制代码
有时候咱们想基于文档结构之外的情形来为页面添加样式,好比基于超链接或表单元素的状态。这时候就可使用伪类选择符。
a:visited {
color: green;
}
.comment:target {
background: #fffec4;
}
/* 结构化伪类 */
tr:nth-child(odd) {
background: yellow;
}
/* 表单伪类 */
input:required {
outline: 2px solid #000;
}
复制代码
伪元素使用双冒号(::
)语法,伪类使用单冒号(:
)语法。
层叠机制的原理是为规则赋予不一样的重要程度。最重要的是做者样式表,其次是用户样式表,最后是浏览器的默认样式表。在此基础上,规则再按选择符的特殊性排序。
为了给用户更高的优先权,CSS 容许用户使用 !important
覆盖任何规则。
p {
font-size: 1.5em !important;
color: #666 !important;
}
复制代码
为了量化规则的特殊性,每种选择符都对应着一个数值。一条规则的特殊性就表示为其每一个选择符的累加数值。但这里的累加计算使用的并不是咱们熟悉的十进制加法,而是基于位置累加,以保证 10 个以上类选择符累加的特殊性不会大于等于 1 个 ID 选择符的特殊性。这是为了不 ID 这种高特殊性选择符被一堆低特殊性选择符(如类型选择符)的累加值所覆盖。若是某条规则中用到的选择符不足 10 个,为简单起见,也可使用十进制来计算其特殊性。
任何选择符的特殊性都对应于以下 4 个级别,即 a、b、c、d:
下面是特殊性计算举例:
选择符 | 特殊性 | 十进制特殊性 |
---|---|---|
style="" |
1,0,0,0 | 1000 |
#wrapper #content {} |
0,2,0,0 | 200 |
#content .datePosted {} |
0,1,1,0 | 110 |
div#content {} |
0,1,0,1 | 101 |
#content {} |
0,1,0,0 | 100 |
p.comment .datePosted {} |
0,0,2,1 | 21 |
p.comment {} |
0,0,1,1 | 11 |
div p {} |
0,0,0,2 | 2 |
p {} |
0,0,0,1 | 1 |
通用选择符(*
)的特殊性为 0。
若是两条规则特殊性相等,则优先应用后定义的规则。
有些属性,像颜色或字体大小,会被应用它们的元素的后代所继承。继承是颇有用的机制,有了它就能够避免给一个元素的全部后代重复应用相同的样式。
继承的属性值没有任何特殊性,连 0 都说不上。通用选择符的特殊性为 0,但仍然优先于继承的属性。
浮动、定位和盒模型是学习 CSS 须要掌握的几个最重要的概念。
页面中的全部元素都被看做一个矩形盒子,这个盒子包含元素的内容、内边距、边框和外边距。内边距(padding)是内容区周围的空间。给元素应用的背景会做用于元素内容和内边距。边框(border)会在内边距外侧增长一条框线,这条框线能够是实线、虚线或点划线。边框的外侧是外边距(margin),外边距是围绕在盒子可见部分以外的透明区域,用于在页面中控制元素之间的距离。
对元素盒子而言,内边距、边框和外边距不是必需的,所以它们的默认值都为 0。
默认状况下,元素盒子的 width
和 height
属性指的是内容盒子,也就是元素可渲染内容区的宽度和高度。这时候添加边框和内边距并不会影响内容盒子的大小,但会致使整个元素盒子变大。经过修改 box-sizing
属性能够改变计算盒子大小的方式。box-sizing
的默认值为 content-box
,若是吧 box-sizing
修改成 border-box
,那么 width
和 height
属性的值将会包含内边距和边框。
p
、h1
、article
等元素属于块级元素,会显示为块级盒子,strong
、span
、time
等元素属于行内元素,会显示为行内盒子。
块级盒子会沿垂直方向堆叠,盒子在垂直方向上的间距由它们的上、下外边距决定。
行内盒子是沿文本流水平排列的,也会随文本换行而换行。它们之间的水平间距能够经过水平方向的内边距、边框和外边距来调节。但行内盒子的高度不受其垂直方向上的内边距、边框和外边距的影响。此外,给行内盒子明确设置高度和宽度也不会起做用。
由一行文本造成的水平盒子叫行盒子(line box),而行盒子的高度由所包含的行内盒子决定。修改行盒子大小的惟一途径就是修改行高(line-height
),或者给它内部的行内盒子设置水平方向的边框、内边距或外边距。
垂直方向上的两个外边距相遇时,会折叠成一个外边距,折叠后外边距的高度等于二者中较大的那一个高度,这种机制叫作外边距折叠。
行内盒子、浮动盒子或绝对定位盒子的外边距不会折叠。
把一个元素的 display
属性设置为 relative
,该元素仍然会待在原来的地方。不管是否位移,相对定位的元素仍然会在文档流中占用初始的空间。
绝对定位则会把元素拿出文档流,所以也就不会在占用原来的空间。
要阻止行盒子环绕在浮动盒子外面,须要给包含行盒子的元素应用 clear
属性。clear
属性的值有 left
、right
、both
和 none
,用于指定盒子的哪一侧不该该紧挨着浮动盒子。不少人认为 clear
属性只是简单地删除几个用于抵消前面浮动元素的标记,事实却没有这么简单。清除一个元素时,浏览器会在这个元素上方添加足够大的外边距,从而将元素的上边沿垂直向下推移到浮动元素下方。所以,若是你给「已清除的」元素添加外边距,那么除非你的值超过浏览器自动添加的值,不然不会看到什么效果。
当元素在页面上水平或垂直排布时,他们之间如何相互影响,CSS 有几套不一样的规则,其中有一套规则叫作格式化上下文(formatting content)。前面咱们已经介绍了行内格式化上下文(inline formatting context)的一些规则。好比,垂直外边距对于行内盒子没有影响。相似的,有的规则适用于块级盒子的叠放,好比前面介绍的外边距折叠。
此外,有些规则规定了页面必须自动包含突出的浮动元素(不然浮动元素中的内容可能会跑到可滚动区域以外),并且全部块级盒子的左边界默认与包含块的左边界对齐(若是文字顺序是从右向左,那么与包含块的右边界对齐)。这组规则就是块级格式化上下文(block formatting context)。
还有些规则容许元素创建本身内部的块级格式化上下文,包括:
display
属性值设置为 inline-block
或 table-cell
之类的元素,能够为内容建立相似块级的上下文;float
属性值不是 none
的元素;overflow
属性值不是 visible
的元素。当一个元素具有了触发新块级格式化上下文的条件,而且挨着一个浮动元素时,它就会忽略本身的边界必须接触本身的包含快边界的规则。此时,这个元素会收缩到适当大小。不只行盒子如此,全部盒子都是如此。
下面看一个使用常规方法清除浮动的示例:
.media-block {
background-color: gray;
border: solid 1px black;
}
.media-fig {
float: left;
width: 30%;
}
.media-body {
float: right;
width: 65%;
}
.media-block::after {
content: ' ';
display: block;
clear: both;
}
复制代码
<div class="media-block">
<img class="media-fig" src="/img/pic.jpg" alt="The pic" />
<div class="media-body">
<h3>Title of this</h3>
<p>Brief description of this</p>
</div>
</div>
复制代码
经过触发新的块级格式化上下文的方式,咱们能够换种方式清除浮动:
.media-block {
background-color: gray;
border: solid 1px black;
}
.media-fig {
float: left;
width: 30%;
margin-right: 5%;
}
.media-block,
.media-body {
overflow: auto;
}
复制代码
这样就能实现咱们的目标:
.media-block
包住浮动的图片,由于块级格式化上下文自动包含浮动;.media-body
声明宽度和浮动。这是由于它会自动调整以适应浮动元素旁边的剩余空间,并确保挨着图片的一遍是直的。若是这里没有新的格式化上下文,并且文本比较多,那么位于浮动 .media-fig
下方的行盒子都会伸长,最终填满图片下方的空间。尽可能基于简单且可预测的行为来建立布局,这样能够下降代码复杂度,并提升布局稳健性。
自印刷出版物诞生以来,排版就一直是平面设计的基础。
当 em
用于计算盒模型的大小时,它不是基于继承的 font-size
,而是基于元素自身计算的 font-size
。
font-size
到底应该选多大,其实没有硬性要求。咱们这里介绍一个适用于标题的大小的叫作「纯四度」(perfect fourth)的数学比例,即上一级标题会比下一级标题的字型大小大自身尺寸的 1/4,或者说是下一级标题字型大小的 1.3333... 倍。
h1 {
font-size: 2.315em; /* 37px */
}
h2 {
font-size: 1.75em; /* 28px */
}
h3 {
font-size: 1.314em; /* 21px */
}
复制代码
此类比例关系对于初始阶段的网页设计相当重要。推荐你们试试 Modular Scale 计算器,其中有不少预设比例关系可供参考。
行内盒子中的内容区显示文本。内容区的高度由 font-size
的测量尺度,即上图中 n
那个 1em
见方的块,以及这个块与字形自己的关系来决定。
小写字母 x
的上边界决定了所谓的「x 高度」。
字形会被摆放在内容区中,每一个字形都在垂直方向上不偏不倚,使得每一个行内盒子的底边都默认对齐于靠近底部的共同水平线,这条线叫基线。内容区也不必定会限制住字形,好比某些字体中的小写字母「g」就会向下伸出内容区。
行高指的是行盒子的总高度。更通俗的叫法是行间距,排版术语叫铅空,就是排字员用来隔开字符行的铅块。
行盒子的总体行高减去 font-size
,获得的值再平分红两份,也就是半铅空。
若是行盒子中包含多个行高不一的行内盒子,那么这个行盒子的最终高度至少等于其中最高的行内盒子。
body {
font-family: Georgia, Times, 'Times New Roman', serif;
line-height: 1.5;
}
复制代码
通常来讲,行高取值在 1.2 ~ 1.5 范围内。关键是行与行之间既不能太密,也不能太疏。
这里给 line-height
设置类没有单位的值 1.5,意思就是当前 font-size
的 1.5 倍。body
的 font-size
为 16px,那么默认的 line-height
就是 24px。
也能够给 line-height
设置像素值、百分比值或 em
值,但要注意 body
元素的全部子元素都会继承 line-height
的计算值。换句话说,就算 body
用的是百分比值或 em
,其子元素继承的都是计算后获得的像素值,但无单位的值就不会致使这个结果。所以,若是给 lien-height
设置没有单位的值,那么子元素继承的是一个系数,永远与本身的 font-size
成比例。
除了 line-height
,行内盒子也会受到 vertical-align
属性的影响。它的默认值是 baseline
,即子元素的基线与父元素的基线对齐。其余值还有 sup
、top
、bottom
、text-top
、text-bottom
和 middle
。
若是行盒子中有一个元素使用 vertical-align
调整了位置,那么它可能会扩展行盒子的高度。
与行内文本相比,行内块和图片的垂直对齐行为稍有不一样,由于它们不必定有本身的惟一基线。
咱们使用 font-weight
属性来设置标题文本的粗细。关键字有如下几个:normal
、bold
、bolder
和 lighter
,也能够直接给出数字值:100,200,300,……,900。默认值 normal
对应 400,bold
对应 700,这两个粗细值是最经常使用的。
对阅读体验有着重大影响的因素:行长。用排版的行话说,就是版心宽度。过长或太短的文本行会打断人的眼球移动,致使读者没法连续阅读。
一行文本到底多长才合适,并无什么终极答案。Robert Bringhurst 的经典图书 The Elements of Typographic Style 提到,主题内容的文本行长一般是 45 ~ 75 个字符,平均值为 66 个字符。
在下载 Web 字体的时候,浏览器有两种方式处理相应的文本内容。第一种方式是在字体下载完成前暂缓显示文本,术语叫 FOIT(flash of invisible text)。Safari、Chrome 和 IE 默认采用这种方式,问题是用户必须等待字体下载完成才能看到内容。若是用户的网络速度很慢,这个问题会很是明显。
第二种方式是在字体下载完成前,浏览器先用一种后备字体显示内容。这样能够避免因网速慢而引发的问题,但也会带来字体切换时的闪动问题。这个闪动有时候也被称为 FOUT(flash of unstyled text)。
背景会附着在指定元素的后面,若是你滚动页面,那么背景也会随着元素移动而移动。能够经过 background-attachment
属性改变这种行为。
.profile-box {
background-attachment: fixed;
}
复制代码
随着页面滚动,该背景图片不会动,好像藏到了页面后面同样。
Level 3 Backgrounds and Borders 规范如今支持一个元素设置多个背景图片。所以,每一个背景属性也就有了相应的多值语法,多个值由逗号分隔。
.multi-bg {
background-image: url(img/spades.png), url(img/hearts.png), url(img/diamonds.png), url(img/clubs.png);
background-position: left top, right top, left bottom, right bottom;
background-repeat: no-repeat, no-repeat, no-repeat, no-repeat;
background-color: pink;
}
复制代码
多重背景按声明的前后次序自上而下堆叠,最早声明的在最上面,最后声明的在最下面。背景颜色层在全部背景图片下面。
对于具备固定宽高比的位图,把高度设置为 auto
,只改变宽度,或者把宽度设置为 auto
,只改变高度,都是能够的。
可是若是没有固定宽高比的元素呢?如何是其在可伸缩的同时保持固定宽高比?
iframe
和 object
就属于这种情形,某些状况下的 SVG 内容也是。常见的例子是在页面中经过 iframe
嵌入一段视频:
<iframe width="420" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen ></iframe>
复制代码
若是像这样给它设置一个可伸缩的宽度:
iframe {
width: 100%; /* 或者其余任何比例 */
}
复制代码
就会致使 iframe
宽度为 100%,而高度始终是 315 像素。由于视频自己也有宽高比,因此咱们但愿这里的高度也能够自适应。
此时不管把 iframe
的高度设置为 auto
仍是删除 height
属性都无论用,由于 iframe
自己没有固定的宽高比。此外,这样作极可能致使 iframe
的高度变成 150 像素。为何是 150 像素呢?CSS 规范指出,对于没有指定大小的可替代内容(如 iframe
、img
、object
),最终的默认大小为 300 像素宽或 150 像素高。
要解决这个问题,须要借助一些巧妙的 CSS 技术。 首先,把 iframe
包在一个元素里:
<div class="object-wrapper">
<iframe width="420" height="315" src="https://www.youtube.com/embed/dQw4w9WgXcQ" frameborder="0" allowfullscreen ></iframe>
</div>
复制代码
而后让这个包装元素的尺寸与要嵌入的对象具备相同的宽高比。简单计算一下,用原始的高度 315 像素除以原始宽度 420 像素,结果是 0.75。换句话说,高度是宽度的 75%。
接下来,将包装元素的高度设置为 0,但把 padding-bottom
设置为 75%:
.object-wrapper {
width: 100%;
height: 0;
padding-bottom: 75%;
}
复制代码
以前介绍过,内边距和外边距若是使用百分比值来设置,那它们的实际值是基于包含块的宽度来计算的。这里的宽度是 100%(与包含块宽度相等),所以内边距就是包含块的 75%。因而咱们就建立了一个具备宽高比的元素。
最后,在这个包装元素中绝对定位嵌入对象。尽管包装元素的高度是 0,仍然能够经过绝对定位把嵌入对象放到一个「可保持宽高比」的内边距盒子里:
.object-wrapper {
width: 100%;
height: 0;
padding-bottom: 75%;
position: relative;
}
.object-wrapper iframe {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}
复制代码
成功!这样就能够在页面中包含可伸缩的嵌入对象了。
定位并不适合整体布局,由于它会把元素拉出页面的正常流。关于定位的总结以下:
static
),意思是块元素垂直堆叠relative
),而后能够相对于其原始位置控制该元素的偏移量,同时又不影响其周围的元素。与此同时,这也为该元素的后代元素创造了定位上下文。这一点也是相对定位真正的用处。absolute
)支持精肯定位元素,相对于其最近的定位上下文:或者是其非静态定位的祖先元素,或者是 html 元素。绝对定位的元素会脱离页面流,而后再相对于其定位上下文进行定位。默认状况下,它们会被浏览器定位与以前静态定位时所处的位置,但不会影响周围的元素。而后,咱们能够相对于定位上下文来改变它们的位置。fixed
)与绝对定位基本相似,只不过定位上下文被自动设置为浏览器视口。绝对定位很是适合建立弹出层、提示和对话框这类覆盖于其余内容之上的组件。
要用好定位,还有一个重点技术必须掌握,那就是 z-index
,也就是堆叠元素的次序。静态定位(static
)之外的元素会根据它们在代码树中的深度依次叠放,就像打扑克发牌同样,后发的牌会压在先发的牌上面。它们的次序能够经过 z-index
来调整。
除了 z-index
,还有其余影响元素堆叠次序的因素。这里有一个概念,叫堆叠上下文。就像一盒扑克牌,每张牌自己也是一个上下文(牌盒),而牌只能相对当前的牌盒排定次序。有一个根堆叠上下文,全部 z-index
不是 auto
的定位元素都会在这个上下文中排序。随着其余上下文的创建,就会出现堆叠层级。
堆叠上下文是由特定属性和值建立的。好比,任何设定了 position: absolute
及值不是 auto
的 z-index
属性的元素,都会建立一个本身后代元素的堆叠上下文。
在一个堆叠上下文内部,不管 z-index
值多大或多小,都不会影响其余堆叠上下文,毕竟不能相对于别的堆叠上下文从新排序。
设置小于 1 的 opacity
值也能够触发新的堆叠上下文。
对于利用行内块建立水平布局而言,若是须要垂直对齐,有如下两点:
vertical-align: top
;vertical-align: middle
。对于每一个块都占据确切宽度的水平布局而言,空白是一个突出的问题。HTML 源代码中的换行符会被渲染成空白符,若是水平布局的几个行内块的宽度之和刚好等于包含元素宽度,那么这几个行内块必定会发生折行。解决这种问题的方法简单粗暴,就是把包含元素的 font-size
设置为 0(从而让每一个空格的宽度为 0)。
Flexbox,也就是 Flexible Box Layout 模块,是 CSS 提供的用于布局的一套新属性。这套属性包含针对容器(弹性容器,flex container)和针对其直接子元素(弹性项,flex item)的两类属性。Flexbox 能够控制弹性项的以下方面:
Flexbox 能够针对页面中某一区域,控制其中元素的顺序、大小、分布及对齐。这个区域内的盒子能够沿两个方向排列:默认水平排列(成一行),也能够垂直排列(成一列)。这个排列方向称为主轴(main axis)。
与主轴垂直的方向称为辅轴(cross axis),区域内的盒子能够沿辅轴发生位移或伸缩。Flexbox 布局中最重要的尺寸就是主轴方向的尺寸:水平布局时的宽度或垂直布局时的高度。咱们称主轴方向的这个尺寸为主尺寸(main size)。
若是不指定大小,Flex 容器内的项目就会自动收缩。也就是说,一行中的各项会收缩到各自的最小宽度,或者一列中的各项会收缩到各自的最小高度,以刚好能够容纳自身内容为限。
Flexbox 对子项的排列有多种方式。沿主轴的排列叫排布(justification),沿辅轴的排列则叫对齐(alignment)。
用于指定排布方式的属性就是 justify-content
,其默认值是 flex-start
,表示按照当前文本方向排布(也就是向左对齐)。justify-content
的其余几个关键字为:flex-end
、center
、space-between
、space-around
。
Flexbox 不容许经过以上这些关键字指定个别项的排布方式。然而,对 Flexbox 的子项指定值为 auto
的外边距在这里却有不一样的含义。具体来讲,若是指定某项一侧的外边距值为 auto
,并且在容器里那一侧还有空间,那么该外边距就会扩展占据可用空间。利用这一点,能够创造让一项位于一侧,其余项位于另外一侧的布局。
.navbar li:first-child {
margin-right: auto;
}
复制代码
像上面这样,对第一项应用 margin-right: auto
能够吃掉全部剩余空间,把其余项推到右侧。
控制辅轴对齐的属性 align-items
,其默认值是 stretch
。也就是说,子项默认拉伸,以填满可用空间。其余的关键字还有 flex-start
、center
、flex-end
、baseline
。baseline
关键字能够将子项中文本的基线与容器基线对齐,效果与行内块的默认行为相似。若是子项大小不一,而你但愿它们在辅轴上虽然位置不一样,但自己对齐,那么就能够采用这种方法。
除了同时对齐全部项,还能够在辅轴上使用 align-self
指定个别项的对齐方式。
Flexbox 可让咱们轻松解决垂直对齐问题。在容器里面只有一个元素时,只要将容器设置为 flex
,再将须要居中的元素的外边距设置为 auto
就好了。这是由于 Flexbox 中各项的自动外边距会扩展「填充」相应方向的空间。
<div class="flex-container">
<div class="flex-item">
<h2>Not so lost in space</h2>
<p>This item sits right in the middle of its container...</p>
</div>
</div>
复制代码
想要水平而且垂直居中 .flex-item
,仅须要如下 CSS 代码,不管容器或其中元素有多大。
html,
body {
height: 100%;
}
.flex-container {
height: 100%;
display: flex;
}
.flex-item {
margin: auto;
}
复制代码
Flexbox 支持对元素大小的灵活控制。这一点既是实现精确内容布局的关键,也是迄今为止 Flexbox 中最复杂的环节。可伸缩的尺寸在实现以前,确实是很难预测的。
Flex 的意思是「可伸缩」,这体如今如下 3 个属性中:flex-basis
、flex-grow
和 flex-shrink
。这 3 个属性应用给每一个可伸缩项,而不是容器。
flex-basis
:控制项目在主轴方向上、通过修正以前的「首选」大小(width
或 height
)。能够是长度值(如 18em
)、百分比(相对于容器的主轴而言),也能够是关键字 auto
(默认值)。关键字 auto
的意思好像是把 width
或 height
设置为自动,但实际上并非那么回事。这里 auto
值的意思是这个项目能够从对应的属性(width
或 height
)那里得到主尺寸 -- 若是设置了相应属性的话。若是没有设置主尺寸,那么该项目就根据其内容肯定大小,有点相似浮动元素或行内块。也能够设置 content
值,意思也是根据项目内容肯定大小,可是会忽略经过 width
或 height
设置的主轴尺寸(与 auto
不一样了)。
flex-grow
:一个弹性系数(flex factor)。在经过 flex-basis
为每一项设置了首选大小以后,若是还有剩余空间,该系数表示该如何处理。其值是一个数值,表示剩余空间的一个比值。默认值是 0,表示从 flex-basis
取得尺寸后就再也不扩展。
flex-shrink
:也是一个弹性系数,与 flex-grow
相似,但做用相反。换句话说,若是空间不够了,该如何收缩?增长了 flex-shrink
这个因素以后,计算过程就更复杂了。默认值是 1,表示若是空间不够,全部项都会以本身的首选尺寸为基准等比例收缩。
要理解 flex-basis
与 flex-grow
以及 flex-shrink
的关系可并不容易。Flexbox 使用了至关复杂的算法来计算各伸缩项的大小。可是,若是咱们将计算过程简化成如下两个步骤,那么理解起来就容易多了。
(1)检查 flex-basis
,肯定假想的主尺寸。
(2)肯定实际的主尺寸。若是按照假想的主尺寸把各项排布好以后,容器内还有剩余空间,那么它们能够伸展。伸展多少由 flex-grow
系数决定。相应地,若是容器装不下那么多项,则根据 flex-shrink
系数决定各项如何收缩。
使用 flex
简写属性能够一次性设置 flex-grow
、flex-shrink
和 flex-basis
属性:
.navbar li {
flex: 1 0 0%;
}
复制代码
在多行布局中,咱们能够相对于容器来对齐行或列。咱们可使用一个叫作 align-content
的属性,默认值为 stretch
,意思是每一行都会拉伸本身以填充本身应占的容器高度。align-content
对容器中多行的做用,与 justify-content
对主轴内容排布的做用很是类似。align-content
的其余取值为:flex-start
、flex-end
、center
、space-between
、space-around
。
使用 Flexbox 的 order
属性,能够彻底摆脱项目在源代码中的顺序的约束。只要告诉浏览器这个项目排在第几就好了。默认状况下,每一个项目的 order
值都为 0,意味着按照它们在源代码中的顺序出现。
经过 Flexbox 重拍次序只影响呈现的效果。按 Tab 键切换键盘焦点和屏幕阅读器并不会受 order
属性的影响。所以 HTML 代码仍是要按照逻辑来写。