css中的流,元素,基本尺寸

流 元素 基本尺寸

流之所以影响整个css世界,是因为它影响了css世界的基石 --HTML

HTML 常见的标签有虽然标签种类繁多,但通常我们就把它们分为两类: 块级元素(block-level element)和内联元素(inline element)。

1.块级元素

1.1 概念相关

“块级元素”对应的英文是 block-level element,常见的块级元素有 div,li,table等。

块级元素和 display:block 不是一个概念

例如块级元素 li 和 table ,他们的 display 的值分别为 list-item 和 table

块级元素具有换行性质,也就是一个水平流上只能单独显示一个元素,多个块级元素则换行显示;

由于这种 换行性质,理论上块级元素都可以配合 clear 属性来清除浮动带来的影响

.clear:after {
 content: '';
 display: table; // 也可以是 block,或者是 list-item
 clear: both;
} 

实际开发中,display的值要么是block,要么是table,并不会使用list-item

1.2 为什么 list-item会出现项目符号

所有的块级元素都有一个主盒子,而list-item除了主盒子,还有一个附加盒子

list-item 之所以会出现项目符号(小黑点),是因为生成了一个附加盒子,学名为 “标记盒子”,专门来存放圆点,数字这些项目符号

IE不支持display:list-item 的原因可能就是因为IE无法创建 这个标记盒子的原因。

1.3 display:inline-block

display:inline-block 我们可以把一个这样的元素分为两个部分组成,外在的inline内联盒子,里面的block块级盒子组成。这样,由于外在的外联盒子,它的呈现方式既可以和文字等元素同为一行,又因为内在的块级盒子,它可以设置元素的宽高。

于是,按照display的属性值不同

display 外盒子 内盒子
block block block
inline inline inline
inline-block inline block
table block table
inline-table inline table

外盒子影响着流的走向,内盒子控制元素的基本属性

2. width/height 作用的具体细节

我们在上面已经说过, width/height等属性作用在内盒子中,也就是容器盒子中。接下来我们说一下具体的作用细节。

流特性体现在水平方向上,我们来讨论width

2.1 width:auto

width的默认值就是auto

  • 充分利用空间 -- div的默认宽度一般都是100%

  • 收缩和包裹

  • 收缩到最小 -- min-content

    当每一列空间都不够的时候,文字能断就断,但中文是随便断的,英文单词不能断。

  • 超出容器限制

    没有相关设置的情况下,一般元素不会主动超过父级宽度容器,除非一些特殊情况

    例如:内容而很长的连续英文和数字

    ​ 或者内联元素被设置了 white-space:nowrap 属性

在 CSS 世界中,盒子分“内在盒子”和“外在盒子”,显示也分“内部显示”和“外部显示”,同样地,尺寸也分“内部尺寸”和“外部尺寸”。

上述的width:auto 的四条特性里面,是默认宽度 100%显示,是“外部尺寸”,其余全部是“内部尺寸”。而这唯一的“外部尺寸”,是“流”的精髓所在。

2.2 外部尺寸与流体特性

  1. 正常流宽度。

    当我们在一个容器里倒入足量的水时,水一定会均匀铺满整个容器。

    a {
     display: block;
     width: 100%;
    } 
    

    默认为inline的a元素display设置为block,本身就是表示宽度铺满整个父级,后面的100%宽度就不用再加了。

    作者总结过一套三无准则: 无宽度,无图片,无浮动。

    其中无宽度的原因就是因为一旦外部尺寸的块级元素设置了宽度,其流动性就丢失了。

  2. 格式化宽度

    格式化宽度仅出现在“绝对定位模型”中,也就是出现在 position属性值为 absolute 或 fixed 的元素中。在默认情况下,绝对定位元素的宽度表现是“包裹性”,宽度由内部尺寸决定

    但是有一种情况其宽度是由外部尺寸所决定的,例如:

    div { position: absolute; left: 20px; right: 20px; } 
    

    假设该元素最近的具有定位特性的祖先元素的宽度是 1000 像素,则这个元素的宽度是 960(即 1000−20−20)像素。

2.3 内部尺寸与流体特性

所谓“内部尺寸”,简单来讲就是元素的尺寸由内部的元素决定,而非由外部的容器决定。

如何判断一个元素是否为内部尺寸呢?

​ 假如这个元素里面没有内容,宽度就是 0,那就是应用的“内部尺寸”。

“内部尺寸”有下面 3 种表现形式:

  1. 包裹性。

    “包裹性”,除了“包裹”,还有“自适应性”。“自适应性”是区分后面两种尺寸表现很重要的一点。自适应,指的是元素尺寸由内部元素决定。

    按钮就是 CSS 世界中极具代表性的 inline-block 元素,可谓展示“包裹性”最好的例子,具体表现为:按钮文字越多宽度越宽(内部尺寸特性),但如果文字足够多,则会在容器的宽度处自动换行(自适应特性)。

    “包裹性”对实际开发的作用

    请看这个需求:页面某个模块的文字内容是动态的,可能是几个字,也可能是一句话。然
    后,希望文字少的时候居中显示,文字超过一行的时候居左显示。该如何实现?

    官方演示代码连接

  2. 首选最小宽度

    在 CSS 世界中,图片和文字的权重要远大于布局,因此,CSS 的设计者显然是不会让图文在 width:auto 时宽度变成 0 的,此时所表现的宽度就是“首选最小宽度”。

    • 汉字最小宽度是每个字的宽度

    • 英文最小宽度是由连续的英文字符单元决定,终止于空格,短横线及其他非字母符号

      想让英文字符和中文一样一个字符为最小宽度,可以使用css中的 word-break:break-all 属性

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

  3. 最大宽度

    最大宽度就是元素可以有的最大宽度。

    如果内部没有块级元素或者块级元素没有设定宽度值,则“最大宽度”实际上是最大的连续内联盒子的宽度。

2.4 width 值作用的细节

对于一个元素,我们设定其宽度为 100px,如下:div { width: 100px; }
请问,100px 的宽度是如何作用到这个元素上的?

width 是作用在“内在盒子”上的,实际上,这个内在盒子是由很多部分组成 --- 盒子模型

盒子模型

我们的这个“内在盒子”又被分成了 4 个盒子,分别是 content box、padding box、border box和 margin box

“margin 的背景永远是透明的”,因此不可能作为 backgound-clip 或 backgroundorigin属性值出现。margin 一旦设定具体宽度和高度值,其本身的尺寸是不会因 margin值变化而变化的。

width宽度作用在content盒子上

假设一个盒子的css如下:

div { width: 100px; padding: 20px; border: 20px solid; } 

那么它的宽度就变成了 100 + 20x2 + 20x2 = 180 px 了

合情合理,但是这种机制会导致以下问题:

  1. 流动性丢失
  2. 与现实世界表现不一致的困扰

有没有什么办法能避免这种盒子计算而导致的错位问题呢,方法之一就是采用书写方式约束,使用“宽度分离原则”

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

所谓“宽度分离原则”,就是 CSS 中的 width 属性不与影响宽度的 padding/border(有时候包括 margin)属性共存

如何实现?

分离,width 独立占用一层标签,而padding、border、margin 利用流动性在内部自适应呈现。

例子:

这里有一个div盒子

  • 常规布局

    .box {
     width: 100px;
     border: 1px solid;
    } 
    

    此时宽度为102像素,我们现在希望元素内边框有20像素的留白,我们一般会想到的解决办法是加padding的值

    .box {
     width: 100px;
     padding: 20px;
     border: 1px solid;
    } 
    

    ok 此时有了留白,但是我们发现宽度变成了 102 + 40 = 142px, 我们常规的会使用减少宽度来实现我们的要求

    .box {
     width: 60px; // 通过计算,减去 40 像素
     padding: 20px;
     border: 1px solid;
    } 
    

    要求实现了,但是如果我们是通过计算,才能达到我们想要的,以后的调试会有更多的麻烦。

  • 宽度分离

    .father {
     width: 102px;
    }
    .son {
     border: 1px solid;
     padding: 20px;
    } 
    

    嵌套一层标签,父元素定宽,子元素因为 width 使用的是默认值 auto,所以会如水流般自动填满父级容器。

    宽度还是 102 像素,子元素的 content box 自动变成了 60 像素,和上面反例的表现一样。

    也就是说,使用“宽度分离”后,咱们不需要烧脑子去计算了,而且页面结构反而更稳固。

    这个做法的唯一缺点就是要多嵌套一层html标签,和对开发者极高的css要求水平。

    针对这中情况,有没有即无需计算,又不用额外的套用标签而实现呢? ----> box-sizing

2.5 改变width/height 作用细节的 box-sizing

box-sizing 被直译为“盒尺寸”,实际上,其更准确的叫法应该是“盒尺寸的作用细节”,或者说得更通俗一点,叫“width 作用的细节”,也就是说,box-sizing 属性的作用是改变 width 的作用细节

正常情况下width作用在盒模型中的四个盒子中的content盒子上,box-sizing的作用就是可以把width作用的盒子变成其他的几个盒子上,有以下几种写法

.box1 { box-sizing: content-box; } /* 默认值 */
.box2 { box-sizing: padding-box; } /* Firefox 曾经支持 */
.box3 { box-sizing: border-box; } /* 全线支持 */
.box4 { box-sizing: margin-box; } /* 从未支持过 */ 

.box3 { box-sizing: border-box; } 来说,就是把原来的宽度作用对象从content-box转到了border-box

.box {
 width: 100px;
 box-sizing: border-box;
}   
此时这个盒子的宽度是100px

.box {
 width: 100px;
 box-sizing: border-box;
 border: 1px solid;
} 
这事的宽度还是100px

2.6 height: auto 和 height: 100%

宽度稀缺,高度无限,所以在css中高度较宽度更简单纯洁

height: auto

所有的元素盒子在页面中表现的每个有多高,加在一起,就是最终的高度值

height: 100%

height 和 width 还有一个比较明显的区别就是对百分比单位的支持。对于 width 属性,就算父元素 width 为 auto,其百分比值也是支持的,但是对于 height 属性,如果父元素height 为 auto,只要子元素在文档流中,其百分比值完全就被忽略了。

对于普通文档流中的元素,百分比高度值要想起作用,其父级必须有一个可以生效的高度值。

为何父级没有具体高度值的时候,height:100%会无效?

如果包含块的高度没有显式指定(即高度由内容决定),并且该元素不是绝对定位,则计算值为auto。一句话总结就是:因为解释成了 auto。要知道,auto 和百分比计算,肯定是算
不了的。

如何让元素支持 height:100%效果

  1. 设定显式的高度值。这个没什么好说的,例如,设置 height:600px,或者可以生效的百分比值高度。

    html, body {
     height: 100%;
    } 
    
  2. 使用绝对定位。

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

    此时的 height:100%就会有计算值,即使祖先元素的 height 计算为 auto 也是如此。

    绝对定位元素的百分比计算和非绝对定位元素的百分比计算是有区别的:

    绝对定位的宽高百分比计算是相对于 padding box 的

    非绝对定位元素则是相对于 content box 计算的

3. min-width/max-width和min-height/max-height

3.1为流体而生的 min-width/max-width

网页宽度在 1200~1400 像素自适应,既满足大屏的大气,又满足笔记本的良好显示

.container {
 min-width: 1200px;
 max-width: 1400px;
} 

无须 width 设置,直接使用 min-width/max-width

再比如一个图片的盒子宽度已定:

img {
 max-width: 100%;
 height: auto!important;
} 

height:auto 是必需的,否则,如果原始图片有设定 height,max-width 生效的时候,图片就会被水平压缩。强制 height 为 auto 可以确保宽度不超出的同时使图片保持原来的比例。但这样也会有体验上的问题,那就是在加载时图片占据高度会从 0 变成计算高度,图文会有明显的瀑布式下落。

3.2 与众不同的初始值

width/height 的默认值是 auto,而 min-width/max-width 和 min-heigh/max-height 的初始值则要复杂些

max-width 和 max-height 的初始值是 none

min-width 和 min-height 的初始值是 auto

3.3 超越!important,超越最大

超越!important

min-width/max-width 和 min-height/max-height 属性间,以及与width 和 height 之间有一套相互覆盖的规则。这套规则用一句比较通俗的话概括就是:超越!important,超越最大。

<img src="1.jpg" style="width:480px!important;">
img { max-width: 256px; }

以上代码作用后,img的宽度为 max-width的宽度 -- 256px,style、!important 通通靠边站!因为 max-width 会覆盖 width。

超越最大

.container {
 min-width: 1400px;
 max-width: 1200px;
 } 

最小宽度居然比最大宽度设置得还大, 最后谁会生效?

遵循“超越最大”规则(注意不是“后来居上”规则),min-width 活下来,max-width 被忽略,于是,.container 元素表现为至少 1400 像素宽

3.4 任意高度元素的展开收起动画技术

“展开收起”效果是网页中比较常见的一种交互形式,通常的做法是控制 display 属性值在 none 和其他值之间切换

传统实现可以使用 jQuery 的 slideUp()/slideDown()方法

第一反应就是使用 height + overflow:hidden 实现。但是,很多时候,我们展开的元素内容是动态的,换句话说高度是不固定的,因此,height 使用的值是默认的 auto

因此,下面代码呈现的效果也是生硬地展开和收起:

.element {
 height: 0;
 overflow: hidden;
 transition: height .25s;
}
.element.active {
 height: auto; /* 没有 transition 效果,只是生硬地展开 */
} 

auto 是个关键字值,并非数值,正如 height:100%的 100%无法和 auto 相计算一样,从 0px 到 auto 也是无法计算的,因此无法形成过渡或动画效果。

我们可以使用max-height来解决这一问题

.element {
 max-height: 0;
 overflow: hidden;
 transition: max-height .25s;
}
.element.active {
 max-height: 666px; /* 一个足够大的最大高度值 */
} 

展开后我的高度只要比max-height小,那么元素的高度就是height的计算高度,一个高度不定的任意元素的展开动画效果就能实现了。

css世界官方demo

注意: max-height值在保证比height大的情况下尽可能和的小

因为max-height可能会影响动画的时间, 比方说,我们展开的元素高度是 100 像素,而 max-height 是 1000 像素,假如一个动画1000ms,则前 900 ms 我们是看不到收起效果的,因为max-height 从 1000 像素到 100 像素变化这段时间,元素不会有区域被隐藏,会给人动画延迟 900 ms 的感觉

4. 内联元素

4.1 哪些是内联元素

从定义:

内联元素的内联指的是外在盒子,外在盒子表现为inline的元素都是内联元素。

inline-block 和 inline-table 都是“内联元素”,因为它们的
“外在盒子”都是内联盒子。自然 display:inline 的元素也是“内联元素”,那么,
按钮元素是内联元素,因为其 display 默认值是 inline-block;img图片元素也是内联
元素,因为其 display 默认值是 inline 等。

从表现看:

就行为表现来看,“内联元素”的典型特征就是可以和文字在一行显示。

浮动元素貌似也是可以和文字在一个水平上显示的,但是浮动已经脱离文档流,不属于内联元素。

4.2 内联世界深入的基础—内联盒模型 (import)

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

看似普通,实际上包含了很多术语和概念,或者换种通俗的说法,包含了很多种盒子。

  1. 内容区域

    内容区域指一种围绕文字看不见的盒子,其大小仅受字符本身特性控制,本质上是一个字符盒子(character box);但是有些元素,如图片这样的替换元素,其内容显然不是文字,不存在字符盒子之类的,因此,对于这些元素,内容区域可以看成元素自身。

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

    以上代码表现的区域,可以理解为内容区域。

  2. 内联盒子

    如果外部含内联标签等),则属于“内联盒子”;如果是个光秃秃的文字,则属于“匿名内联盒子”

  3. 行框盒子(line box)

    每一行就是一个“行框盒子”(实线框标注),每个“行框盒子”又是由一个一个“内联盒子”
    组成的。

  4. 包含盒子/包含块(containing box)

    <p> 标签就是一个“包含盒子”(实线框标注),此盒子由一行一行的“行框盒子”组成。

4.3 幽灵空白节点

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

<style>
  div {
    background-color: #cd0000;
  }
  span {
    display: inline-block;
  }
</style>
<body>
  <div><span></span></div>
</body>

浏览器打开上述代码,发现div的高度不是0,原因就在于幽灵空白节点。

“幽灵空白节点”实际上也是一个盒子,不过是个假想盒,名叫“strut”,中文直译为“支柱”,是一个存在于每个“行框盒子”前面,同时具有该元素的字体和行高属性的 0 宽度的内联盒。

Each line box starts with a zero-width inline box with the element’s font and line
height properties. We call that imaginary box a “strut”.

内容总结与 张鑫旭大神 -- 《css世界》

posted @ 2018-10-22 13:05  noobakong  阅读(622)  评论(0编辑  收藏  举报