自适应内部元素
难题
我们都知道,如果不给元素指定一个 height,它就会自适应其内容的高度,如果希望 width 也具有类似的行为,应该怎么做呢?
解决方案
css3 给 width 定义了一些新的关键字,其中最有用的应该就是 min-content 了,这个关键字将解析为这个容器内部最大的不可断行元素的宽度(即最宽的单词、图片或具有固定宽度的盒元素),样式中的固定的 max-width 是为了给旧版的浏览器提供一个平稳的回退样式。
<
根据兄弟元素的数量设置样式
难题
在某些场景下,我们需要根据兄弟元素的总数来为它们设置样式。最常见的场景就是,当一个列表不断延长时,通过隐藏控件或压缩控件等方式来节省屏幕空间,以此提升用户体验。
解决方案
如果列表中只有一个列表项时,可以使用 :only-child 选择符来完成。
li
实际上,:only-child 等效于 :first-child:last-child,道理很简单:如果第一项同时也是最后一项,那从逻辑上来说它就是唯一的那一项。 :last-child 其实也是一个快捷写法,相当于 :nth-last-child(1) :
li
那么,同时匹配 :first-child 和 :nth-last-child(4) 的元素是什么呢?一个正好有四个列表项的列表中的第一个列表项,现在已经找到一种命中特定数量列表项中第一项的方法,接下来就可以用兄弟选择符( ~ )来命中它之后的所有兄弟元素:相当于在这个列表正好包含四个列表项时,命中它的每一项。
li
这个方法需要的代码相当冗长繁琐,可以使用预处理器来避免这个问题。
/* 定义mixin */
根据兄弟元素的数量范围来匹配元素
li
满幅的背景,定宽的内容
难题
要实现如上图所示的效果,通常会准备两个元素:外层用来实现满幅的背景,内层用来显示定宽的内容,后者通过 margin:auto 实现居中的。
<
难道为了这个效果就一定要添加一层额外的元素?能否在现代 CSS 的帮助下彻底抛弃这个累赘?
解决方案
用 calc() 取代原先的 auto ,内层容器的样式就会变成:
.
也可以将这个长度值应用到父元素的 padding 上,整个效果是保持不变的:
footer
精确控制表格列宽
难题
对于不固定的内容来说,表格的布局是很难预测的,因为列宽会根据表格的内容进行调整,即时我们显式的指定了列宽 width,也只能起到类似的作用。鉴于这个原因,我们往往不得不使用其他元素来呈现表格型数据,或者干脆接受布局效果的不可预测性。有没有什么办法可以让表格的行为更加可控呢?
解决方案
table-layout 默认值为 auto,其行为模式被称为自动表格布局算法,就是我们最熟悉的那种表格布局方式。它还有另外一个属性值 fixed,把更多的控制权交给了网页开发者。我们设置的(宽度)样式会直接起作用,而不仅仅被视为一种提示;同时,溢出行为(包括text-overflow )与其他元素行为也是一样的,因此表格的内容将只能影响表格行的高度了。
在使用时,需要对 <table> 元素或其他具有 display: table 样式的元素应用这个属性(table-layout:fixed)即可。请注意,为了确保这个技巧奏效,需要为这些表格元素指定一个宽度(哪怕是 100% )。同样,为了让 text-overflow:ellipsis 发挥作用,我们还需要为那一列指定宽度。
垂直居中
难题
在 css 中对元素进行水平居中是非常简单的:如果它是一个行内元素就对它的父元素应用 text-align:center ;如果是一个块级元素,就对它自身使用 margin:auto。但是对一个元素进行垂直居中就比较难了。
基于绝对定位的解决方案
main
上面的方法可以实现完美的垂直居中,但是有一些需要注意的地方:
- 有时候不能使用绝对定位,因为它对整个布局的影响太过强烈;
- 如果需要居中的元素已经在高度上超过了视口,那它的顶部就会被视口裁切掉;
- 在某些浏览器中,这个方法可能会导致元素的显示有一些模糊,因为元素可能被放置在半个像素上。
基于视口单位的解决方案
视口相关的长度单位:
- vw 是与视口宽度相关的。与常人的直觉不符的是, 1vw 实际上表示视口宽度的 1%,而不是 100%。
- 与 vw 类似, 1vh 表示视口高度的 1%。
- 当视口宽度小于高度时, 1vmin 等于 1vw ,否则等于 1vh 。
- 当视口宽度大于高度时, 1vmax 等于 1vw ,否则等于 1vh 。
main
基于 Flexbox 的解决方案
body
当使用 Flexbox 时, margin: auto 不仅在水平方向上将元素居中,垂直方向上也是如此。
另外,Flexbox 还可以将匿名容器(即没有被标签包裹的文本节点)进行垂直居中,假设代码结构为:
<
先给 main 指定一个固定的尺寸,再借助 Flexbox 规范引入的 align-items 和 justify-content 就可以将其内部文本居中。
main
紧贴底部的页脚
难题
在网页设计中,存在一个相当古老但又相当常见的问题,它是前端工程师绕不开的坎。这个问题可以简单地概括如下:有一个具有块级样式的页脚(比如它设置了背景或阴影),当页面内容足够长时它一切正常,而当页面较短时(比如错误信息页面,准确的说,当页面内容的长度小于视口高度减去页脚高度时,这个问题就会出现)就会出现问题。此时的问题在于,页脚不能像我们期望中那样“紧贴”在视口的最底部,而是紧跟在内容的下方。
固定高度的解决方案
在已知 footer 元素的高度的情况下,可以借助视口相关的长度单位以及 calc() 函数 将 main 元素设置一个最小高度,比如 footer 元素高度是 200px,那么可以写如下 css 代码:
#
不过,如果页面布局不是这么简单的话,那这个方法就完全不实用了。当改变页脚的尺寸时,都需要跟着调整min-height 值(也就是说,这不够 DRY);此外,除非我们愿意给页头和内容主体套一层额外的 HTML 元素,否则还要跟着页头的尺寸修改。
更灵活的解决方案
Flexbox 对于此类问题同样是完美的选择。首先需要设置 <body> 元素 display:flex,还需要将 flex-flow 设置为 column,不然子元素会被水平排放在一行上。
body
需要将 body 的 min-height 设置为 100vh,现在只需要给 main 这个容器的 flex 属性指定一个大于 0 的值就可以实现这个效果了:
body