CSS世界 CSS

基础知识与盒尺寸

Posted on 2018-02-09,13 min read

CSS概念

首先,应该明白CSS是什么,CSS全称Cascading Style Sheets,中文简称就是“层叠样式表”,所谓层叠就是样式可以层层叠加,比如页面元素都继承了12像素的大小,某标题又设置14像素的大小,那么后者即14像素大小的会覆盖掉继承的12像素大小,正是由于这种策略使得CSS编写起来得心顺手,而CSS世界的诞生主要是为图文信息展示服务的。

为何display:list-item会出现项目符号

在日常使用中,如果我们对一个元素应用以下CSS规则,则会出现项目符号:

HTML:
<p>这是内容</p>

CSS:
.foo{
    display:list-item;
}

效果:

这是内容

在css的世界中,这似乎看似“理所当然”的现象的背后,实际上可能有一整套的体系支撑,创造CSS的造物主原本的想法很简单:我要创造一个世界,就像现实世界中男女一样,块级盒子(block)和内联盒子(inline)。块级盒子负责结构,内联盒子负责内容。然而事实并非如此,正如显示生活中不止有男女,还有特殊性别,于是乎,造物主便重新命名一个新的盒子,叫做“附加盒子”,这样一来,所有的块级元素都有一个“主块级盒子”,list-item除此之外还有一个“附加盒子”。“附加盒子”学名也称作“标记盒子”,专门用来存放圆点、数字这些项目符号的,IE浏览器下伪元素不支持list-item或许就是无法创造这个“标记盒子”导致的。同理可得,值为inline-block的元素实际上由外在的“内联盒子”和内在的“块级容器盒子”组成,这样一来,对于以前理解display值为inline-block的元素为何能和图文在一行显示,又能设置宽高了吧,因为有两个盒子,一个是inline级别,一个是block级别。

深藏不露的“width:auto”

我们应该知道,width的默认值是auto,但是可别小看这一auto属性,它可至少包含了4种不同的宽度表现。

充分利用可用空间: 比方说这些元素默认宽度都是100%于父容器的,这种充分利用可用空间的行为还有个专有名字,叫做fill-available,这个只做了解。

收缩与包裹: 典型代表就是浮动、绝对定位,只做了解。

收缩到最小:直接看效果图:

当一列的空间不够时候,文字能断就断,但中文是随便断的,英文却是有讲究的。于是,第一列被无情的每个字砍掉,形成一柱擎天。
超出容器限制:直接看代码:

HTML:
    <p><span>恰如一江春水向东流,流到断崖也不回头</span></p>

CSS:
.father {
    width: 150px;
    padding: 10px;
    background-color: #cd0000;
    white-space: nowrap;
}

.child {
    display: inline-block;
    padding: 5px;
    background-color: #f0f3f9;
}

效果:

恰如一江春水向东流,流到断崖也不回头

包裹性

包裹性简答来讲就是一个元素具有一个容器,这个容器将内容包含在内,不让其溢出,另一个方面也包括了自适应性,比如,对于一个元素,如果它的display值是inline-block,那么即使里面的内容再多,也不会超出这个容器。那么包裹性有什么用处呢?就拿按钮元素button来讲,有以下代码:

HTML:
    <div class="box">
      <button>按钮</button>
    </div>
CSS:
    .box {
        width: 240px;
        margin: 20px auto;
    }

文字再多一点

按钮文字越多宽度越宽(包裹,内部尺寸特性),但不会超过容器宽度(自适应性)

效果:

嗯?按钮咋还换行了呢,之所以你没印象,是因为你在项目中按钮的文字个数比较有限,没机会换行,当然这是针对button元素,对于input标签,依旧是不会换行的。

在了解这个只是后,现在有个需求:

页面中某个模块的文字内容是动态的,可能几个文字,可能是一句话,然后希望文字少的时候居中,文字多的时候居左显示,该如何显示?核心代码:

HTML:
<div class="box">
    <p  class="content">文字内容</p>
</div>
<div class="box">
    <p  class="content">更多文字更多文字更多文字更多文字更多文字</p>
</div>
CSS:
.box {
  padding: 10px;
  background-color: #cd0000;
  text-align: center;
  width:150px;
  margin-bottom:10px;
}
.content {
  display: inline-block;
  text-align: left;
}

效果:

文字内容

更多文字更多文字更多文字更多文字更多文字

如果不明白原因自己copy代码自己尝试一下就懂了。

首选最小宽度

假设外部容器的宽度为0,内部inline-block元素的宽度是多少,是0吗?当然不是,css的设计者可不会犯这种错误,这时候便会采用一种最小宽度的策略。

具体表现在:

东亚文字(如中文)最小宽度为每个汉字的宽度,即14px。

西方文字则以连续的英文字符单元决定,即终止于空格、短横线、问号以及其他非英文字符。

类似于图片这样的替换元素最小宽度就是该元素的本身的宽度。

了解这个特性后,我们看看有什么实际用处:

需求方需要我们实现一个凹和凸的效果,注意兼容IE8。

HTML:
<span class="ao"></span>
<span class="tu"></span>
CSS:
.ao,
.tu {
  display: inline-block;
  width: 0;
  font-size: 14px;
  line-height: 18px;
  margin: 35px;
  color: red;
}
.ao:before,
.tu:before {
  outline: 2px solid #cd0000;
  font-family: Consolas, Monaco, monospace;
}
.ao:before {
  content: "love你love";
}
.tu {
  direction: rtl;
}
.tu:before {
  content: "我love你";
}

效果:

最大宽度

最大宽度就是元素可以有的最大宽度,即如果内部没有块级元素或者块级元素没有设定宽度值,则“最大宽度”实际上就是最大的连续内联盒子的宽度(即display:inline的多个元素宽度之和)。

<div>
    "我是文本"
    <span>我是内联标签</span>
    <p>我是段落</p>
</div>

效果:

最大宽度为文本+span标签的宽度之和,p标签的最大宽度也是这个值。

这个在轮播图中可以运用,以前轮播图实现一般都是两个div,外层div为容器,一般为显示一张图片的大小,内层div则为所有图片的宽度之和,这样但内部图片增加的时候,往往需要通过js显式再次设置内部容器宽度,从而防止图片换行,导致页面结构变形,现在只需要设置外部容器宽度,内部不需要显示设置,这样就只用css解决了,免去了js的解析执行,具体例子可查这里的demo

CSS流体布局下的宽度分离原则

以前写代码的时候,比如我们设置某一个div的宽度边框大小,要求宽度为100px:

div{
    width:98px;
    border;1px solid #000;
}

此时项目需求说我希望这个div宽度大小变成120px,边框不变,于似乎你就开始用你的小学知识开始算,120宽,边框为2,那么width为118,这一切似乎都没什问题,但是这里存在一个问题,每次修改宽度的时候,都要通过计算得出宽度,如果我宽度要求是1200,边框为71,内边距为17,那么是不是该掏出手机开始计算了,怎么解决这个问题呢?那就是接下来要讲的宽度分离原则了。即css中的width属性不与影响宽度的padding/border共存,也就是不能出现以下的组合:

div{
    width:100px;
    border:1px solid red;
}

不这么写,那该怎么写,很简单,分离,width独立占用一层标签,而padding、border、margin利用流动性在内部自适应呈现(即width:auto可使元素自适应)。

.father{
    width:100px;
}

.son{
    maring:0 auto;
    padding:1px 2px;
    border:1px solid #fff;
}

此时,若设计师要求这个元素为115宽,那直接修改father宽度为115即可,不用再计算边框边距,简单好用,何乐而不为,可能会有有人说这增加了一个标签,但是我想说的是在这个电脑发展如此迅速的今天,你觉得这个会成为你项目的瓶颈问题吗?

当然除此之外,我们还可以利用box-sizing,这个是css3的属性,但是IE8也支持,只不过要加上浏览器私有属性。box-sizing顾名思义就是盒尺寸,如图:

默认值就是里面最小的矩形,值为content-box,各浏览器支持情况:

.box{
    box-sizing;content-box;/* 默认值 */
}

.box{
    box-sizing;padding-box;/* 火狐曾经支持过 */
}

.box{
    box-sizing;border-box;/* 全线支持 */
}

.box{
    box-sizing;margin-box;/* 从未支持过 */
}

所以我们能用的就是有border-box值和默认值两个,当设置border-box属性值时,content-box就从宽度值中解放,即当设置width属性的时候,不再是作用于content-box,即下面的最小的那个矩形区域,而是作用于border区域,例如:

.box{
    width:100px;
    border:1px solid red;
    padding:2px;
    box-sizing:border-box;
}

此时box所在的元素宽度就是100px,而不是以前我们理解100+2+4=106px,这样一来也解决上面那个问题。

height:100%失效的原因

在日常编程中,比如一个登陆界面,我们希望能够背景图片能全屏显示,于是我们自然而然想到以下的实现方式:

img{ width:100%; height:100%; }

自以为完美解决这个问题,却发现,图片水平是百分百显示了,但是垂直方向似乎没有100%显示,于是很自让按F12,吧height:100%,注释掉,却惊讶发现这货似乎没用,加了和没加似乎没什么区别,于是你认为是浏览器bug,就换一个浏览器,发现也是一样,这时候你开始不解,难不成没用?那增加这个属性干啥。其实要想设置成功,需要以下设置:

html,body{
    height:100%;
}

其中html和body必须同时设置,缺一不可。

不设置为何不行,我们来看一个简单的问题,不显式设置宽高,默认为auto,即:
'auto' * 100% = NaN
那为何宽度可以,简单来讲宽度也应该是失效的,但是在规范中却将这种行为表示成未定义行为,即没有明确表示应该怎么样,浏览器厂商根据自己的理解去发挥,好在各个浏览器的效果都是一致的。

当然,支持高度百分百显示,还有另一种方法就是设置绝对定位,即:

div{
    hegiht:100%;
    position:absolute;
}

这里说一下,绝对定位的元素计算值的大小包括padding值,即content-box+padding-box=height,而非绝对定位元素计算值只包括content-box,具体可查看这个demo

内联盒模型

下面是一段简单的html:

这是一行普通的文字,这里有个em标签。

看似普通,却包含了许多术语和概念。
1.内容区域(content area)。内容区域指的是围绕内容看不见的区域,其大小受字符本身特性控制。我们可以把文本被选中的区域称为内容区域:

2.内联盒子(inlien box)。“内联盒子”不会让内容成块显示,而是排成一行,这里的“内联盒子”实际指的就是元素的“外在盒子”,用来决定元素是块级还是内联,具体看图:

其中,实线部分称为“内联盒子”,虚线部分称为“匿名内联盒子”。
3.行框盒子(line box)。每一行就是一个“行框盒子”,每个“行框盒子”又是由一个一个“内联盒子”组成的。

实体标注部分即为“行框盒子”。
4.包含盒子(containing box)。

实体包含部分即为“包含盒子”,此盒子由一个个“行框盒子”组成。

幽灵空白节点

在文档申明为HTML5中,内联元素的所有渲染和解析表现就如同每个行框盒子的前面有一个“空白节点”一样。这个空白节点永远透明,不占据宽度,无法通过脚本获取,就好像幽灵一般,但是有确确实实存在,因此我们称之为“幽灵空白节点”。

参考自《css世界》

作者:落叶卢生
链接:https://luoyelusheng.com/post/基础知识与盒尺寸
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

下一篇: z-index的层叠规则→