01|深入理解Content
01|content和替换元素
根据是否具有可替换的内容,我们也可以把元素分为替换元素和非替换元素,那么什么是替换元素?
其实所谓的替换元素就可以被替换的元素就称之为"替换元素" , 因此对应的标签 img object video iframe 和表单元素 textarea和input都是典型的替换元素!
当然替换元素还有以下特性:
-
内容的外观不受页面上的CSS的影响 样式表现在CSS作用域之外!
-
有自己的尺寸 表单的替换元素的尺寸和浏览器相关,没有明显的规律!
-
在很多CSS属性上有自己的一套表现规则 替换元素的内容往往不可能含有字符x,于是替换元素的极限就被硬生生定义成了元素的下边缘!
-
替换元素的display的默认值 除了FireFox的textarea和input元素上面返回的inline而不是inline-block,其实就可以说明FireFox对替换元素的内联表现是有自己的想法的!
-
其中input和button中的按钮有什么区别? 其实区别就在于 input中的button的white-space值为pre 而普通的button元素的white-space为normal(正常)
02|替换元素的尺寸计算规则
替换元素的尺寸从内而外分为3类:
- 固有尺寸
- HTML尺寸
- CSS尺寸
固有尺寸,其实就是替换内容原本的尺寸! 不加修饰的默认尺寸!
HTML尺寸 通过HTML原生属性改变
CSS尺寸通过width和height或者说max-height或者是min-width设置的尺寸!
对应盒子尺寸!
其中三者的关系 层层递进 CSS尺寸===> HTML尺寸===> 固有尺寸
- 有CSS尺寸就用CSS尺寸
- 没有CSS尺寸则使用HTML尺寸,否则使用固有尺寸!
- 最后当CSS尺寸和HTML尺寸不存在的时候才是用固有尺寸!
固有尺寸有其固有的宽高比例
Wbe开发的时候,为了提高加载性能以及节约贷款费用,首屏以下的图片通过滚屏进行异步加载,但是为了布局稳健,体验良好一般都是使用的图名的图片占位:
<img src="transparent.png" >
<!-- 其实直接可以使用 img -->
<img >
<style>
img{visibility:hidden;}
img[src]{visibility:visible;}
</style>
这里的img是直接没有src属性的,直接没有的话图片是没有任何请求的,是最高效的实现方式!
CSS世界中的替换元素的固有尺寸有一个很重要的特性,其实就是"我们无法改变这个替换元素内容的固有尺寸的!"
那么可能问题来了,及让说替换元素的固有尺寸无法改变,那么对应的我们设定的width和height会影响图片的尺寸呢?
- 替换元素中的content替换内容默认的适配方式是填充(fill) 也就是外部设定的尺寸有多大,因此尺寸变化的话本质并不是改变固有尺寸,二十采用了填充作为适配HTML尺寸和CSS尺寸的方式! 并且在CSS之前,该适配方式是不能修改的!
03|替换元素和非替换元素的距离有多远?
观点1. 替换元素和非替换元素之间的间隔只隔了一个src属性!
其实我们都有一种思维定视,认为<img> 等同于图片,如果我们把src属性去掉的话,其实<img> 就是一个和span类似的普通内联元素,也就是一个非替换元素!
img{display:block;outline:1px solid;}
其中图片的宽度为多少?
最终的宽度其实就是100%适应父容器,其表现和span类似,已经完全不是替换元素了! 现在应该懂了FireFox浏览器下面img设置width和height不起作用了吧
其实该示例,也很好的说明了,"如果图片没有替换内容,图片就是一个普通的内联标签!"
当然对应的Chrome需要通过特定的条件进行触发才行
<img alt="任意值" />
这个很好理解,但是为什么IE没有对应的src属性的同时,还是完全的替换元素呢?
原因在于IE浏览器中有一个默认的 占位替换内容,当src属性缺失的时候,会使用默认的占位内容! 在IE8浏览器下面,这个占位内容全然暴露了,可以参照书籍里面得 4-8图片! (该图标并非打叉的小图标或者是破裂的小图标!)
其实还有一种方法证明 替换元素和非替换元素区别在于src属性,就是基于伪元素的图片生成技术! 可以对img元素使用 ::before和::after伪元素进行内容生成以及样式构建,但是该方法的支持是有限制的! 首先是兼容问题! Chrome和FireFox都能够兼容,但是IE浏览器却不支持! 如果要让Chrome和FireFox等浏览器生效的话,其实需要注意的技术点如下:
-
不能有src属性
-
不能够使用content属性生成图片 (针对Chrome)
-
需要有alt属性并优质!(针对Chrome)
-
FireFox下面::before元素的content只会被无视,但是after并不会 与FireFox自己占用了::before的元素的content属性相关!
基于伪元素的图片内容生成技术,并不属于实用技术,但是实际网页开发的过程中,必须使用到该元素,此时这些隐藏的技术往往就会有神迹表现!
使用缺省的src的img元素实现滚屏加载效果,如果说javascript加载比较慢的时候页面可能出现一块一块白色的图片区域,没有任何信息,用户体验差,虽然说alt能够提示具体的图片描述,但是由于视觉效果不好,就被隐藏掉了! 如果说图片还没加载的时候就能把alt信息呈现出来多好啊!
此时的src没有因此对应的::before和::after可以生效,因此可以如下所示去写代码:
img::after{
content:attr(alt);
position:absolute bottom;
width:100%;
background-color:rgba(0,0,0,0.5);
transition:transform 0.2s;
}
img:hover::after{
transform:transkateX(0);
}
见图片4-10
观点二:替换元素和非替换元素之间只隔了一个CSS content属性!
替换元素之所以为替换元素,就是因为其内容可替换,其内容就是 content-box,因此可以明白content属性决定了是替换元素还是非替换元素!
在Chrome浏览器下面,所有的元素都支持content属性,而别的浏览器下面只有::before和::after才可以支持content属性!
img:not[src]{content:url(1.jpg);} ====> /*<img src="1.jpg"/> */
其实上面视觉效果是一摸一样的!
因此在Chrome浏览器中我们可以很轻松的通过content属性对元素的内容进行修改操作! (详情请见:https://demo.cssworld.cn/4/1-4.php)
content属性改变的仅仅只是视觉呈现,当我们以右键或者其他形式保存这张图片的时候保存的还是原来src对应的图片!
不仅如此,使用content属性,我们可以将普通的元素变成替换元素,举个例子,官网的标志往往都会使用<h1></h1>
标签 里面会有网站的名称和标志图作为背景图使用,如下面的代码:
<h1>css world</h1>
<style>
h1{
width:180px;
height:36px;
background:url(logo.jpg)
text-indent:-999px;/*文字隐藏!*/
}
</style>
尺寸规则还是替换元素的规则,完美适应原始图片大小,虽然说视觉效果上的文字被替换了,但是屏幕阅读设备阅读的还是文字,搜索引擎SEO抓取的还是原始的文本信息,因此对页面的可访问性等没有任何影响!
但是,虽然说我们这样看着没什么问题,但是,其实还是存在一些局限性的,替换元素的尺寸是无法设置的,如今移动端的retina屏幕已经是标配了,为了更好的视觉体验,真实图片往往是显示图片尺寸的两倍,于是问题来了,使用content生成图片我们是无法设置图片的尺寸的,只能迫不得已使用一倍图,然后导致图片看上去有点儿模糊!
因此我们建议在移动端上面使用SVG矢量图片!
03|content与替换元素的关系剖析
CSS世界中content属性生成的对象称之为"匿名替换元素" 他们的属性不是微妙,而是赤裸裸的!
其实 content生成的内容都是替换元素,没错 就是替换元素!
正因为是替换元素,才与普通元素有诸多不同,我们使用Content生成的内容是无法被选中的,就像是user-select:none; 声明一般,但是普通元素的文本可以被轻松选中,同时content生成的文本无法被屏幕设备读取! 也无法被搜索引擎抓取!
这其实也引出了重要的内容:
- 重要的信息不要使用content属性进行生成操作,因为此时的可访问性和SEO都很不友好!
- content属性一般用来生成无关紧要的内容,比如说装饰性的图形或者说序号之类的
- 不必担心重要的图文信息被content替换,替换的仅仅是视觉层!
有人可能会说无法被选中可能是伪元素的原因而并非替换元素的原因,我们可以使用::first-lette对比一下,可以选中,但是::before和::after内容却无法被选中,因而可以确定多半content的原因而并非伪元素的原因!
不能左右:empty伪类. :empty是一个CSS选择器,当元素里面无内容的时候进行匹配,
空格也算内容,伪元素不算内容!
content动态生成的值无法获取!
content是一个强大的属性,其中比较厉害的就是一个计数器!
.total::after{content:counter(icecream);}
我们无法获得此时content对应的具体数值为多少,一点儿办法也没有!
04|content的内容生成技术
其实content应用最多的地方还是在::before中和::after中,但是CSS世界中主要讲的是针对IE8及以上版本的浏览器!
而对应的IE浏览器仅支持单冒号的伪元素,一般使用的时候将对应的content数值值设置为空字符串!
- 利用其他CSS代码来生成辅助元素,或者实现图形效果,或实现特定布局!
其实这样做的好处是,会让HTML代码会显得更加干净和精简!
- 其实很多情况下是用来清除浮动带来的影响:
.clearfix{
content:'';
display:table;/*block*/
clear:both;
}
- 还有就是柱状图content辅助元素与布局
预览请见:https://demo.cssworld.cn/4/1-7.php
- 当然还有就是字符内容生成
常见的应用就是配合@font-face 规则实现图标字体效果
详情请见:https://demo.cssworld.cn/4/1-8.php
- 当然 还有一个值得介绍的点就是,除了常规的字符之外,我们还可以输入Unicode字符,比较经典的就是输入换行符来实现某些布局或者效果, 还能让我们加载的时候让元素动起来,进行过渡的动画!
详情请见:https://demo.cssworld.cn/4/1-9.php content换行符与打点loading效果实例页面
02|温和的padding属性
在盒尺寸中,padding的性格是最温和的,并且padding指的是 内补间 这个词比较术语化,其实可以简单理解为蛋白! 鸡蛋中的蛋壳 蛋白 蛋黄!
因为在CSS中默认的box-sizing是content-box,所以我们使用padding的话会增加元素的尺寸!
.box{width:80px;padding:20px;}
如果说不考虑到别的元素的干扰的情况下那么对应的宽度就为120px; 但是这样的话是不符合现实世界的认知的,人们总是习惯把代码世界和现实世界做映射,导致人们总在使用padding的时候遇到坑,于是乐此不疲的直接将box-sizing设置为border-box!
其中作者也提到了不推荐这种做法:重置box-sizing,更何况是全局重置,尽量采用无宽度以及宽度分离准则的情况下实现才是好的解决方法!
但是很多人认为,重置了box-sizing:border-box; 这样设置了元素尺寸就不会发生变化,但是大部分人没有考虑到的事,如果说padding足够大的话,那么对应的width也就无能为力了!
.box{
width:80px;
padding:20px 60px;
box-sizing:border-box;
}
那么此时的width就无效了,最终的宽度为120px(60px2) 里面的内容表现为"首选最小宽度*"
但是padding表现在内联元素上面的话则不一样!
同样的会在垂直方向上影响布局,影像视觉表现,只是内联元素没有对应的可视宽度和可视高度的说法,垂直方向上完全受行高和对应的垂直对齐影响的!
但是视觉上面并没有改变上下行的间距,我们的感觉就是垂直padding没有起到对应的作用!
但是如果说,给对应的内联元素添加背景色或者说边框的话,确实能够看到尺寸空间的变化(受到了padding的影响!)!
详情请见:https://demo.cssworld.cn/4/2-1.php
虽然说尺寸发生了变化,但是上下元素的原有布局却没有任何影响,仅仅是垂直方向上发生了层叠!
不影响其他元素布局而是出现层叠效果的现象
-
relative元素的定位
-
盒阴影box-shadow以及outline等
-
纯视觉层叠 不影响外部尺寸 例如说:box-shadow outline
-
影响外部尺寸
如何区别层叠效果到底是纯视觉层叠还是非纯视觉层叠呢?
父容器 overflow:hidden 如果说层叠区域超出父容器的时候没有滚动条出现 那么就是纯视觉的否则就是影响布局的那种!
如果说内联元素的padding有用的时候,那么对于我们实际应用CSS的时候有什么实质性的帮助吗?
-
在不影响当前布局的时候 优雅的增加连接或者按钮区域的大小!
-
高度可控的分隔线 详情请见:https://demo.cssworld.cn/4/2-2.php
-
还可以辅助布局,实际上对于非替换块元素的内联元素,不仅padding不会加入行盒高度的计算,并且对应的margin和border也是如此! 都是不计算高度 但是实际上在内联盒周围都发生了渲染!
01|padding的百分比值
- padding不能够为负值
- padding支持百分比值
但是padding的百分比值计算规则和height还是有些不同的,padding的百分比值的计算规则不管是水平还是垂直都是相对于宽度计算的!
那么为什么会相对于width计算而不是height计算呢?
因为如果说相对于height计算的话,大多数情况下都是0,那么跟摆设是没有什么区别的!
还不如相对计算的! 相反因为CSS默认的水平流,计算值一直都会有效,并且还能够利用这个特性实现一些有意思的布局效果!
当然一般的就是网页开发的时候经常会有横贯整个屏幕的头图效果,使用padding进行等比例控制,在小屏幕下面的时候高度天然等比例缩小,没有任何javascript的时候,却依然适配良好!
预览请见:https://demo.cssworld.cn/4/2-3.php
02|标签元素内置的padding
其中介绍了很多人可能不知道的关于padding的一些小秘密,ol/ul列表内置的padding-left,但是单位是px而不是em,例如Chrome浏览器下面是40px,因此对应的元素和左边缘距离受制于font-size的大小!
还有就是很多表单元素都内置了对应的padding!
其实最明显的就是button按钮了,在不同的浏览器中高度计算下的button的padding值都千差万别,但是为了更好地兼容的话可以这样去处理
<button id="btn"></button>
<label for="btn">按钮</label>
<style>
button{position:absolute;clip:rect(0,0,0,0)}
label{display:inline-block;line-height:20px;padding:10px;}
</style>
其实这样一来的话在所有的主流浏览器中的按钮高度都是为40px,就很好的解决了button的高度在不同高度计算的浏览器下面的表现不同的问题了!
label元素中的for对应的值和元素的id值想通就行了!
03|padding与图形绘制
预览请见:https://demo.cssworld.cn/4/2-4.php
03|激进的margin属性
虽然说padding比较温和,但是所谓的margin就比较激进了,负责外间距,虽然都是间距但是两者的差别还是很大的,有此事margin,比较奇怪的地方还是比较多的!
01|margin与元素尺寸以及相关布局
其实之后的内容会过多的涉及到尺寸,为了更好的甄别这个名词,把相关的概念梳理一下
- 元素尺寸: 元素的border-box尺寸 也就是元素的 偏移尺寸
- 元素内部尺寸: 元素的padding box的尺寸 我们一般称之为 元素可视尺寸
- 元素外部尺寸: 也就是margin-box的尺寸
其中margin最大的不同其实就是margin的值可以是负值,但是如果说我们将 外部尺寸理解为 元素占据的空间尺寸 可能就好理解得多了吧!
02|margin与元素的内部尺寸
如果说元素设定了对应的width或者保持 包裹性 的时候,margin对尺寸没有影响,只有元素是 充分利用可用空间,状态的时候,margin才可以改变元素的可视尺寸!
.father{width:300px;margin:0 30px;/*如果是这样的话 那么对应的元素尺寸不会发生任何变化!*/}
但是如果过说充分利用可用空间的话就能够使用margin进行设定!
<div class="father">
<div class="son">
</div>
</div>
<style>
.father{width:300px;}
.son{margin:0 -20px;}
</style>
这样一来对应的class为son的元素的宽度就是为340像素了!
只要元素的尺寸表现符合"充分利用可用空间",无论是垂直方向上还是水平方向上,都可以通过margin改变尺寸!
由于margin具有这种流体特性下的改变尺寸的特性,所以很多时候可以使用margin方便的实现很多流体布局的效果:
预览请见:https://demo.cssworld.cn/4/3-1.php
可以利用margin实现顺序完美一致的自适应效果 借助margin负值定位进行实现!
当然还能够利用margin的特性实现两端对齐我们设置三个元素在一行中,同一设定margin-right的话最后一个会有多余的控件!
因此维护起来比较麻烦,但并不是没有办法解决的:
ul{margin-right:20px;} /*ul 的width就为 100%+20px*/
li{float:left:margin-right:20px;width:100px;}
这样一来的话 最后的li元素的margin-right:20px;此时的位置 也就对应了 ul右边缘的宽度位置!
03|margin与元素的外部尺寸
对于普通块状元素,在默认的水平流下面,margin只能够改变元素的左右方向的内部尺寸!垂直方向上则无法改变!
如果说使用writing-mode改变流向为垂直的话,那么则水平方向内部尺寸无法改变,垂直方向可以改变,这是由margin:auto的计算规则决定的!
margin属性的影响更为宽泛,只要元素具有块状特性,无论有没有设置width/height无论是水平还是垂直方向,即使发生了margin合并,margin对外部尺寸都着着实实发生了影响! 实际上很多棘手的问题都是需要再借助Margin外部尺寸的特性来实现的!
其中子元素的高度超过content box的尺寸大小 触发滚动条显示,如果说留白效果的话 使用padding是不推荐的,推荐使用margin,滚动容器的底部留白也只是推荐margin-bottom实现!
还有一种应用就是,使用margin来实现等高布局:
预览请见: https://demo.cssworld.cn/4/3-2.php
其中最常见的问题就是: 为什么可以实现等高布局呢?
无法改变元素的内部尺寸,但是可以改变元素的外部尺寸,这样通过margin-bottom和padding-bottom一正一负相互抵消,虽然说在布局层面没有什么太大影响,但是带来了我们需要的东西 9999px高度的可使用的背景色,但是数值太大了,因此使用了overflow:hidden把多余的部分隐藏掉了! 因此视觉层面就是等高的效果了!
04|margin的百分比值
不管是padding还是margin百分比都是相对于width计算的,但是margin百分比的应用价值就比padding小了一节,元素设置margin在垂直方向尚无法改变元素自身的内部尺寸,往往需要父元素做为载体! 又因为margin合并的问题存在,垂直方向上面的往往需要双倍尺寸才能和padding表现一致!
05|正确看待margin中的合并
- 块级元素的上外边距和下外边距 有些时候会合并成为一个外边距,这种现象被称之为"margin合并"
margin合并的条件如下:
- 块级元素 但不包括浮动和绝对定位元素,尽管浮动和捕获两点重要的信息!
- 只发生在垂直方向 该说法不考虑 writing-mode的情况下 严格说的话 只发生在和当前文档流方向的相垂直的方向上! 默认文档流是水平流 发生margin合并的方向是垂直方向!
margin合并的常见三种情景:
- 兄弟相邻元素
- 父级和第一个/最后一个元素
- 空块级元素的margin合并
如何阻止margin-top合并的发生呢?
- 父元素设置为BFC块级格式化上下文元素
- 父元素设置border-top
- 父元素设置padding-top
- 父元素和第一个子元素之间添加内联元素进行分隔!
如何阻止margin-bottom合并的发生呢?
- 父元素设置为BFC块级格式化上下文元素
- 父元素设置border-bottom
- 父元素设置padding-bottom
- 父元素设置height,min-height或者说max-height
其中涉及到了块级格式化上下文的内容部分,具体详情:
- 根元素或包含根元素的元素
- 浮动元素(元素的
float
不是none
) - 绝对定位元素(元素的
position
为absolute
或fixed
) - 行内块元素(元素的
display
为inline-block
) - 表格单元格(元素的
display
为table-cell
,HTML表格单元格默认为该值) - 表格标题(元素的
display
为table-caption
,HTML表格标题默认为该值) - 匿名表格单元格元素(元素的
display
为table、``table-row
、table-row-group、``table-header-group、``table-footer-group
(分别是HTML table、row、tbody、thead、tfoot的默认属性)或inline-table
) -
overflow
值不为visible
的块元素 -
display
值为flow-root
的元素 -
contain
值为layout
、content
或strict
的元素 - 弹性元素(
display
为flex
或inline-flex
元素的直接子元素) - 网格元素(
display
为grid
或inline-grid
元素的直接子元素) - 多列容器(元素的
column-count
或column-width
不为auto,包括 ``column-count
为1
) -
column-span
为all
的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
其中比较重要的部分,也就是空块级元素的margin合并:
其实是合并了三次的,如果两个块级元素中加了一个空元素的块级标签!
第一个padding-bottom和第二个的padding-top 以及第三个的padding-top和中间的padding-bottom
之后呢 中间的margin你被合并之后了,第一个和第三个继续进行合并, 从第一个的padding-bottom和第三个的padding-top进行合并之后! 总共合并了三次!
如果说不希望空标签里面有对应的margin合并,那么可以进行如下操作:
- 设置垂直方向的border
- 设置垂直方向的padding
- 里面添加内联元素(直接的空格是没有用的!)
- 设置height或者是max-height
其中涉及到了对应的margin合并规则的话,有以下三个
- 正正取大值
- 正负值相加
- 负负最负值!
06|margin合并的设计初衷
CSS世界的CSS属性一定是为了更好的图文展示 为了更好的布局体验!
其实自身margin合并的意义在于可以避免不小心遗落或者生成的空标签影响排版和布局!
07|深入理解CSS中的margin:auto
margin:auto的规则如下
- 如果一侧定值,一侧auto,则auto为剩余空间大小
- 如果两侧均为auto,则平分剩余空间!
明明容器定高元素定高那么margin:auto却无法垂直居中?
其实出发margin:auto计算有一个前提条件,就是width或者说height为auto的时候,元素是具有对应方向的自动填充属性的!
水平垂直居中的方法:
.son{
position:absolute;top:0;right:0;bottom:0;left:0;
width:200px;height:100px;
margin:auto;
}
预览请见:https://demo.cssworld.cn/4/3-5.php
通过格式化宽高并且使用margin:auto自动分割垂直和水平方向的空间!
08|margin无效情形解析
- display计算值inline的非替换元素的垂直margin是无效的, 对于内联替换元素垂直margin有效,并且不存在margin合并问题,因此图片永远都不会margin合并!
- 表格中的tr或者说td元素 或者说设置display计算值是table-cell或者是table-row元素的margin都是无效的!
- margin合并的时候,更改margin值可能是没有效果的,
- 决定定位的非定位方位的margin "无效",是什么意思呢? 主要是因为绝对定位元素的渲染是独立的,而普通兄弟元素是心连心,但是绝对定位元素是无法印象兄弟元素定位的,因此对应的margin就无效了!
- 定稿容器子元素的margin-bottom或者宽度定死的子元素的margin-right的定位失效!
- 鞭长莫及的margin无效
- 内联特性导致的margin无效,
04|功勋卓越的border属性
为什么这么说呢,主要是边框在我们设计网页的时候确实起到了很多作用,并且与此同时,其良好的兼容性和稳定的特性表现菜的次荣耀的!
为什么不支持百分比值
- 主要是CSS世界创造的背景主要是为图文展示所服务的,它的设计初衷就决定了他不支持百分比值!
- 其中不仅仅是border-width不支持 其实还有一些CSS属性也是如此:
- outline
- box-shadow
- text-shadow
其实border-width还支持一些默认值:
- thin 薄薄的 等同于1px
- medium(默认) 薄厚均匀 等同于3px
- thick 厚厚的 等同于4px
可能有些人会问 为什么不是thin为默认值呢?
因为border-style:double对应的数值最起码3px才有效果!
01|了解border-style
是的对应的border-style默认值为none 我们使用的时候 使用 border:1px solid red; 是通过重置边框样式的时候出现的!
- solid 实线
- dashed 虚线边框
- dotted 规范上面的是小圆点 但是Chrome和对应的Firefox上面的却是小方点!
这样一来的话如果需要一个圆我们可以使用对应的border的属性来实现了!
- border-style:double; 双线边框!
当然还有其他的border-style
分别为: inset 内凹 outset 外凸 groove 沟槽 ridge山脊
border-color和color
有一个很重要但是很实用的特性,border-color默认颜色其实就是color色值, 当然没有制定对应的色值的时候 会使用当前元素的color计算值作为边框色!
02|border与透明边框技巧
.box{
border-right:50px solid transparent;
background-position:100% 50%;
}
优雅的增加点击区域的大小
其实可以利用透明的border进行处理:
.icon-clear{
width:16px;height:16px;
border:11px solid transparent;
}
后面有很多对border的应用!
网友评论