css动画
https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-style
3d动画
perspective
这个 perspective(视域)属性通常作用在外部容器元素上,例如body,figure和 div 等标签上。这样我们就在3D空间操作内在的子元素。你可以将这个属性理解为类似flex
box
这个属性,因为其也可以影响内部元素的外观和位置。如果没有这个属性,即使我们应用了 CSS 3D 的Transforms属性我们也无法看到预期的3D视觉效果。
父元素{
perspective: px;
}
第一个:镜头,第二个:拍摄的环境的空间,第三个:要拍摄的物件。
transform:perspective
他们的一个区别就是,一个给父元素加,一个给自身加
perspective(视域)原理
使用长焦距的望远镜头,物体可以拉近且比较不会变形,使用短焦距的广角镜,拍摄的物体就容易变形,从下图可以看出,镜头的焦距可以让空间内的物体产生不同的变形。
变成都用div进行展现,在对应的div 上头加入对应的style属性,就可以进行模拟,藉由上面所提到的三个要素,我们这里就必须要用到三层div,最外层是摄影镜头,第二层为立体空间,第三层则是立体空间内的立体元素.
<div class="camera">
<div class="space">
<div class="box"></div>
</div>
</div>
设定camera
如上述代码我们将最外层的div(以下通称camera )定义为相机镜头,为了让其具有相机的拍摄功能,我们就要为其定义相关的属性,camera包含两个属性:
perspective-origin
和 perspective
。
perspective
透视点同样也是物体到摄影机的距离( d ) ,但又因为CSS的3D空间里头具有Z轴,所以perspective的距离会因为Z轴的关系而有所缩放( 不过千万要注意,这里的Z指的是物体的Z轴,也就是translateZ,不是摄影机的)。
perspective-origin
perspective-origin
是摄影机的中心点位置,预设相对应空间div ( 以下都称为space ) 的中心点,不做设定的话预设都是center center ( 或50% 50% ),换句话说,作为摄影镜头的camera 的三个维度,perspective-origin 代表了X 和Y 轴,而perspective 代表Z 轴( 和内容物体的Z 轴相减才会变成摄影机的),camera 就可以在三维空间里头进行移动,下图同样是W3C网站 对于perspective-origin 所作的解释,当摄影镜头往上移动,图形的下半部就看不到了。
在代码中这时候会完全没有画面是正常的,因为还没有设定空间和物体。
.camera{
width: 200px;
height: 200px;
perspective-origin: center center;
perspective: 500px;
}
perspecitve设定的界限
很重要 important
值越小,越扭曲
设定space
摄影机完成后,我们需要定义一个立体空间space,这个空间设定的方式很简单,只要设定一个属性:transform-style
,这个属性默认值为flat,也就是只要是这个div内的子元素,一律都是以扁平( flat )的方式呈现,所属的变换transform也默认一律都是用flat的方式变换,换句话说就是没有Z轴的存在,为了让内容元素都是立体元素,所以我们要将transform-style
的值设为3d属性,如此一来内容元素就全部都可以用3D进行变换,为了方便区分,下面我将会设置space的boder属性设置为黑色虚线用于识别。
.space {
width: 100%;
height: 100%;
border: 1px dashed #000;
transform-style: preserve-3d;
}
transform-style: preserve-3d;
以保证多个三维物体都位于同一空间
设置box
最后就是内容元素box了,接下来,我们先用这个box来验证一下前面讲的观点,在没有设定box的traslateZ、rotate的情形下,不论我们如何去修改camera的perspective-origin和perspective的值,box的大小和位置都不会有变化,为什么呢? 因为在没有设定的box的translateZ或rotate,让Z的深度有所变化,摄影机透过perspective看上去的位置都是相同的,也造成不论怎么去看这个box都是一样的大小。示例代码如下
.box {
width: 100px;
height: 100px;
background: #006699;
transform: translateX(50px) translateY(50px);
}
设置更多的box
你可能要变换多个物体,接下来我们尝试下添加多个box。并且让这些box的位置改变或旋转,看看效果如何,这里比较需要注意的是我们必须要在最外层的div加入position:absolute
的属性,因为div本身为block属性,会互相挤压,要设定位置为绝对位置,才会正确地放在space空间里。
<style>
.camera {
width: 200px;
height: 200px;
perspective-origin: center center;
perspective: 500px;
}
.space {
width: 100%;
height: 100%;
border: 1px dashed #000;
transform-style: preserve-3d;
}
.space div {
position: absolute;
width: 100px;
height: 100px;
}
.box1 {
background: #069;
transform: translateX(50px) translateY(50px) rotateY(60deg);
}
.box2 {
background: #c00;
transform: translateX(100px) translateY(20px) rotateX(60deg);
}
.box3 {
background: #f90;
transform: translateX(0px) translateZ(-250px) rotateY(20deg);
}
.box4 {
background: #0c9;
transform: translateX(20px) translateY(80px) rotateX(-80deg);
}
</style>
<body>
<div class="camera">
<div class="space">
<div>
<div class="box1"></div> //蓝色的
translateX(50px) translateY(50px) rotateY(60deg)
<div class="box2"></div>//红色的
translateX(100px) translateY(20px) rotateX(60deg);
<div class="box3"></div>//黄色的
transform: translateX(0px) translateZ(-250px) rotateY(20deg);
<div class="box4"></div>//绿色的
transform: translateX(20px) translateY(80px) rotateX(-80deg);
</div>
</div>
</div>
效果图
translateX
translateY
只是移动x轴和y轴的位置
顺序不同 见后面坐标轴
这个规则就是tramsform里头是有顺序的,因为CSS 3D完全是藉由2D演算而来,并不是真的像3D软件构建是真的有3D的空间,所以就变成会「按照顺序」进行演算,而且又因为transform会造成物体的整个坐标轴会随着变换而变换,在顺序的编排上就格外重要,顺序不同效果就有所不同。
数量越多造成的视觉差异就强烈
.space div {
position: absolute;
width: 100px;
height: 100px;
}
.box1 {
background: #069;
transform: translateY(50px) translateX(100px) rotateY(60deg) rotateX(60deg) translateX(-50px);
}
.box2 {
background: #c00;
transform: translateX(-50px) translateY(50px) rotateX(60deg) rotateY(60deg) translateX(100px);
}
.space div {
position: absolute;
width: 100px;
height: 100px;
}
.box1 {
background: #069;
transform: translateY(50px) translateX(100px) rotateY(60deg);
}
.box2 {
background: #c00;
transform: translateY(50px) rotateY(60deg) translateX(100px);
}
个人简介
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OUXH3xps-1683944959940)(D:\总结\img\动画\CU632]WF[C]Y{HYHI@WQQ$R.png)]
-
- 前面和背面分别设置样式
<div class="front">
</div>
<div class="back">
</div>
-
- back和front设置绝对定位,让他们在一起,
- 将front隐藏,就可以只显示背面,
- 将front倒转过来设置perspective
- 设置transition
.back, .front { width: 100%; height: 100%; overflow: hidden; /* 1. 将前面和后面设置绝对定位*/ position: absolute; /* 3.front隐藏 */ backface-visibility: hidden; /* 4.设置transform运动的时间 */ transition: transform 0.5s linear; } .front { background: rgba(255, 255, 255, .7); padding: 40px; /* 2.将front倒装过来 */ transform: perspective(600px) rotateX(180deg); }
-
- 1.设置back的transform
- 2.当hover的时候transform的变化
.back { /* 6.设置back */ transform: perspective(600px) rotateX(0deg); } .business-card:hover .front { transform: perspective(600px) rotateX(0deg); } .business-card:hover .back { transform: perspective(600px) rotateX(180deg); }
炫酷点缀
.front::before {
background: #2f3542;
width: 80px;
height: 120px;
bottom: 0;
clip-path: polygon(0 100%, 50% 0, 100% 100%);
}
.front::after {
background: #2f3542;
width: 100px;
height: 100%;
bottom: 0;
clip-path: polygon(0 0, 100% 0, 100% 100%);
}
收获
backface-visibility
backface-visibility:hidden;
backface-visibility:visible;
perspective 透视度
3D立体视图的可是效果,当距离越近,视角越变形
/* Keyword value */
perspective: none;
/* <length> values */
perspective: 20px;
perspective: 3.5em;
/* Global values */
perspective: inherit;
perspective: initial;
perspective: unset;
transform-style
transform-style: flat;
transform-style: preserve-3d;
clip-path: polygon(0 100%, 50% 0, 100% 100%);
css炫酷盒子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nBYK0eKP-1683944959941)(D:\总结\img\动画\1.png)]
html
-
- 设置大盒子container
- 每一个正方形都是一个box,一共四个
- 在box下面设置文字
<div class="container">
<div class="box">
<div class="content">
<h2>01</h2>
<h3>Service One</h3>
<p>
love is evry beautifulLinux is vetulove is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu
</p>
<a href="">Reader more</a>
</div>
</div>
<div class="box">
<div class="content">
<h2>02</h2>
<h3>Service Two</h3>
<p>
love is evry beautifulLinux is vetulove is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu
</p>
<a href="">Reader more</a>
</div>
</div>
<div class="box">
<div class="content">
<h2>03</h2>
<h3>Service Three</h3>
<p>
love is evry beautifulLinux is vetulove is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu
</p>
<a href="">Reader more</a>
</div>
</div>
<div class="box">
<div class="content">
<h2>04</h2>
<h3>Service Four</h3>
<p>
love is evry beautifulLinux is vetulove is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu,love is evry beautifulLinux is vetu
</p>
<a href="">Reader more</a>
</div>
</div>
</div>
css之布局
- 2.body用flex布局
- 3.contanier用grid布局
- 4.box用grid布局
body {
margin: 0;
padding: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background: #060c21;
font-family: 'Poppins', sans-serif;
}
.container {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
grid-template-rows: auto;
width: 90%;
grid-gap: 0 40px;
}
.container .box {
position: relative;
height: 400px;
background: #060c21;
display: flex;
justify-content: center;
justify-items: center;
border: 1px solid #000;
}
css之h2变化
- 1.当hover上的时候top值从20px变成-40px
- 设置过渡时间0.5s
.box .content h2 {
position: absolute;
font-size: 10em;
top: 26px;
right: 20px;
margin: 0px;
padding: 0px;
color: rgba(255, 255, 255, .05);
transition: 0.5s;
}
.box:hover .content h2 {
top: -40px;
}
css之a标签变化
- 将a标签y轴上移动从
translateY(-40px);
到transform: translateY(0);
- 当a被hover上时,颜色和背景变化
.box .content a {
position: relative;
margin: 0;
padding: 10px 20px;
text-decoration: none;
border: 1px solid #fff;
display: inline-block;
transition: 0.5s;
transform: translateY(-40px);
opacity: 0;
visibility: hidden;
}
.box:hover .content a {
transform: translateY(0);
opacity: 1;
visibility: visible;
}
.box .content a:hover {
background: #fff;
color: #000;
}
css之炫酷边框
.container .box::before {
content: '';
position: absolute;
top: -2px;
left: -2px;
bottom: -2px;
right: -2px;
background: #fff;
transform: skew(2deg, 2deg);
z-index: -1;
}
.container .box:nth-child(1):before {
background: linear-gradient(315deg, #ff0057, #e64a19);
}
.container .box:nth-child(2):before {
background: linear-gradient(315deg, #89ff00, #00bcd4);
}
.container .box:nth-child(3):before {
background: linear-gradient(315deg, #e91e63, #5d02ff);
}
.container .box:nth-child(4):before {
background: linear-gradient(315deg, #ff0000, #ffc107);
}
.container .box::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
background: rgba(255, 255, 255, .05);
pointer-events: none;
}
动画层级的控制,保持动画层级在最上方
这个问题可能有一点难理解。需要了解 CSS 动画渲染优化的相关知识。
先说结论,动画层级的控制的意思是尽量让需要进行 CSS 动画的元素的 z-index
保持在页面最上方,避免浏览器创建不必要的图形层(GraphicsLayer),能够很好的提升渲染性能。
OK,再一次提到了图形层(GraphicsLayer),这是一个浏览器渲染原理相关的知识(WebKit/blink内核下)。
简单来说,浏览器为了提升动画的性能,为了在动画的每一帧的过程中不必每次都重新绘制整个页面。在特定方式下可以触发生成一个合成层,合成层拥有单独的 GraphicsLayer。
需要进行动画的元素包含在这个合成层之下,这样动画的每一帧只需要去重新绘制这个 Graphics Layer 即可,从而达到提升动画性能的目的。
那么一个元素什么时候会触发创建一个 Graphics Layer 层?从目前来说,满足以下任意情况便会创建层:
- 硬件加速的 iframe 元素(比如 iframe 嵌入的页面中有合成层)
- 硬件加速的插件,比如 flash 等等
- 使用加速视频解码的 元素
- 3D 或者 硬件加速的 2D Canvas 元素
- 3D 或透视变换(perspective、transform) 的 CSS 属性
- 对自己的 opacity 做 CSS 动画或使用一个动画变换的元素
- 拥有加速 CSS 过滤器的元素
- 元素有一个包含复合层的后代节点(换句话说,就是一个元素拥有一个子元素,该子元素在自己的层里)
- 元素有一个 z-index 较低且包含一个复合层的兄弟元素
本题中说到的动画层级的控制,原因就在于上面生成层的最后一条:
元素有一个 z-index 较低且包含一个复合层的兄弟元素。
这里是存在坑的地方,首先我们要明确两点:
- 我们希望我们的动画得到 GPU 硬件加速,所以我们会利用类似
transform: translate3d()
这样的方式生成一个 Graphics Layer 层。 - Graphics Layer 虽好,但不是越多越好,每一帧的渲染内核都会去遍历计算当前所有的 Graphics Layer ,并计算他们下一帧的重绘区域,所以过量的 Graphics Layer 计算也会给渲染造成性能影响。
动画导航
outline
语法
/* 宽度 | 样式 | 颜色 */
outline: 1px solid white;
:link:hover { outline: 1px solid #000; }
:link:hover { outline: solid black 1px; }
transition-property
语法
transition-property: none|all| property;
值 | 描述 |
---|---|
none | 没有属性会获得过渡效果。 |
all | 所有属性都将获得过渡效果。 |
property | 定义应用过渡效果的 CSS 属性名称列表,列表以逗号分隔。 |
transition
transition
CSS 属性是 transition-property
,transition-duration
,transition-timing-function
和 transition-delay
的一个简写属性。
transition: margin-right 4s ease-in-out 1s;
box-sizing
<div class="content-box">Content box</div>
<br>
<div class="border-box">Border box</div>
div {
width: 160px;
height: 80px;
padding: 20px;
border: 8px solid red;
background: yellow;
}
.content-box {
box-sizing: content-box;
/* Total width: 160px + (2 * 20px) + (2 * 8px) = 216px
Total height: 80px + (2 * 20px) + (2 * 8px) = 136px
Content box width: 160px
Content box height: 80px */
}
.border-box {
box-sizing: border-box;
/* Total width: 160px
Total height: 80px
Content box width: 160px - (2 * 20px) - (2 * 8px) = 104px
Content box height: 80px - (2 * 20px) - (2 * 8px) = 24px */
}
如果为content-box,将是216*136的盒子
如果为border-box,将是104px*24px的盒子
a标签
nav a {
display: inline-block;
text-decoration: none;
color: #fff;
font-weight: bold;
margin: 15px 25px;
letter-spacing: 2px;
font-size: 1.3em;
text-transform: uppercase;
outline: none;
text-shadow: 0 0 1px rgba(255, 255, 255, 0.3);
}
a标签:
- 设置
display: inline-block;
- 设置字体
color: #fff;
font-weight: bold;
font-size: 1.3em;
letter-spacing: 2px;`` text-shadow
左右开门
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hktI3MCY-1683944959942)(D:\总结\img\动画\11.png)]
基底
<body>
<div class="container">
<section class="color-1">
<nav class="cl-effect-1">
<a href="#">Wafture</a>
<a href="#">Sumptuous</a>
<a href="#">Scintilla</a>
<a href="#">Propinquity</a>
<a href="#">Harbinger</a>
</nav>
</section>
</div>
</body>
*,
*:after,
*::before {
box-sizing: border-box;
}
body {
font-family: 'Raleway', sans-serif;
}
.container {
background: #C4E538;
box-sizing: border-box;
}
nav a:hover,
nav a:focus {
outline: none;
}
第一步
- 先设置before和after的整体样式
- 可以在这里设置过度的动画,这个动画的重点
transition: transform 0.2s, opacity 0.3s;
就是靠的它实现的动画
nav a::before,
nav a::after {
display: inline-block;
opacity: 0;
transition: transform 0.2s, opacity 0.3s;
}
第二步
- 设置before和after的各自样式
- 将
transform
向左/右移动 - 设置
margin-right
是因为当hover的时候与文字的距离
nav a::before {
content: "[";
margin-right: 10px;
transform: translateX(27px);
}
nav a::after {
content: "]";
margin-left: 10px;
transform: translateX(-27px);
}
第四步
- 当hover上的时候,两个动画元素的改变
nav a:hover::before,
nav a:hover::after {
transform: translateX(0px);
opacity: 1;
}
注意:
这里是nav a:hover::before,
不能写成nav a:hover nav a::before,
上去隐藏
attr()
p:before {
content:attr(data-foo) " ";
}
<p data-foo="hello">world</p>
结果:helloworld
注意:
- attr后面的双引号
“ ”
要加上 attr()
理论上能用于所有的CSS属性但目前支持的仅有伪元素的content
属性,
rotate和tanslate的结合
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ACd8j9Fy-1683944959943)(D:\总结\img\动画\33.png)]
transform: rotateX(30deg) translateY(-10px);}
边旋转边往里面走
再加上下面这个属性,会有一种往外的感觉,因为默认为center center
,现在的中心变成了top
了
transform-origin: top center;
translateY(-10px);}
这个属性有文字往里面走的感觉
implement
<div class="container">
<section class="color-4">
<nav class="cl-effect-2">
<a href="#"><span data-hover="Ratatouille">Ratatouille</span></a>
<a href="#"><span data-hover="Lassitude">Lassitude</span></a>
<a href="#"><span data-hover="Murmurous">Murmurous</span></a>
<a href="#"><span data-hover="Palimpsest">Palimpsest</span></a>
<a href="#"><span data-hover="Assemblage">Assemblage</span></a>
</nav>
</section>
</div>
这里只有两个盒子
第一步
所以a
就当作camera
.cl-effect-2 a {
perspective: 600px;
perspective-origin: center center;
}
第二步
span充当两个作用,space和box
.cl-effect-2 a span {
background: #2195de;
padding: 10px;
display: inline-block;
transform-style: preserve-3d;
transform-origin: top center;
transition: transform 0.3s;
}
transform-origin: top center;
1这里设置了这个属性,规定它以哪个中心点移动
第三步
当hover上时
.cl-effect-2 a:hover span {
transform: rotateX(90deg) translateY(-30px);
}
见前面
第四步
设置hover上时,before的变化
.cl-effect-2 a span::before {
content: attr(data-hover)"";
position: absolute;
bottom: 0%;
left: 0%;
color: red;
padding: 10px;
display: inline-block;
transform: rotateX(-90deg);
transition: background 3s;
transform-origin: center top;
}
.cl-effect-2 a:hover span::before {
background: #2195de;
}
注意
hover属性伪元素会和标签一样,一起运动,所以他们一起使用了第三步的hover属性
transform:tanslateY(0px)
注意:
transform:tanslateY(0px)
可以让物体变到padding的外面,本来伪元素:before
是在padding
里面的
上移错觉
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-o07z65R9-1683944959944)(D:\总结\img\动画\4.png)]
transform: translateY(-100%);的妙用
将a标签设置
.cl-effect-2 a {
overflow: hidden;
height: 1em;
}
.cl-effect-2 a span::after {
content: attr(data-hover);
position: absolute;
top: 100%;
left: 0%;
transform: translate3d(0, 0, 0);
}
.cl-effect-2 a:hover span {
transform: translateY(-100%);
}
伪元素记得定位 position: absolute;
设置了这个属性之后,要记得设置top
left
的值
通过top,height设置的动画
设置了这个属性之后,要记得设置top
left
的值
.cl-effect-5 a:hover::before {
top: 100%;
}
.cl-effect-5 a:hover::after {
height: 100%;
}
transform:translateY(0%)
使用transform:translateY(0%)到transform:translateY(100%)感觉会一些不同
向左翻书
.cl-effect-10 a span {
display: inline-block;
padding: 10px 20px;
background: #0f7c67;
transform: translateX(0%);
transition: transform 0.3s;
}
.cl-effect-10 a:hover span {
transform: translateX(100%);
}
span从 translateX(0%);
到 transform: translateX(100%);
.cl-effect-10 a::before {
content: attr(data-hover)"";
/* z-index: -1; */
position: absolute;
top: 0;
left: 0;
padding: 10px 20px;
color: #0f7c67;
background: #fff;
transform: translateX(-25%);
transition: transform 0.3s;
}
.cl-effect-10 a:hover:before {
transform: translateX(0%);
}
::before 从 transform: translateX(-25%);
到 transform: translateX(0%);
display:block
要变成块级元素才才能动呀
text-shadow
text-shadow: 10px 0 #fff, -10px 0 #fff;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VvZoDjCN-1683944959944)(D:\总结\img\动画\5.png)]
从一个圆点变成三个
往左边旋转的盒子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BnTjdgeb-1683944959945)(D:\总结\img\动画\5 (2)].png)
第一步:定基
<body>
<div class="container">
<section class="color-5">
<nav class="cl-effect-19">
<a href="#"><span data-hover="Ratatouille">Ratatouille</span></a>
<a href="#"><span data-hover="Lassitude">Lassitude</span></a>
<a href="#"><span data-hover="Murmurous">Murmurous</span></a>
<a href="#"><span data-hover="Palimpsest">Palimpsest</span></a>
<a href="#"><span data-hover="Assemblage">Assemblage</span></a>
</nav>
</section>
</div>
</body>
<style>
*,
*:after,
*::before {
box-sizing: border-box;
}
body {
font-family: 'Raleway', sans-serif;
}
.container {
background: #435a6b;
box-sizing: border-box;
}
nav a:hover,
nav a:focus {
outline: none;
}
nav a {
display: inline-block;
text-decoration: none;
color: #fff;
font-weight: bold;
margin: 15px 25px;
letter-spacing: 2px;
font-size: 1.3em;
text-transform: uppercase;
outline: none;
text-shadow: 0 0 1px rgba(255, 255, 255, 0.3);
}
</style>
第二步:设置盒子
.cl-effect-19 a {
margin: 15px;
line-height: 2em;
perspective: 600px;
perspective-origin: center center;
}
.cl-effect-19 a span {
position: relative;
background: #e35041;
display: inline-block;
padding: 0 10px;
transform-style: preserve-3d;
}
第三步:设置中心👿
- 记住有两个面
-
- 第一个面:中心是
center center
- 第二个面:是
left center
- 第一个面:中心是
.cl-effect-19 a span {
transition: transform 0.3s, background 0.3s;
transform-origin: center center -100px;
}
.cl-effect-19 a span::after {
content: attr(data-hover)"";
position: absolute;
top: 0%;
right: 0%;
width: 100%;
height: 100%;
background: #b53a2d;
transform: rotateY(90deg);
transform-origin: left center;
}
第四步:旋转
.cl-effect-19 a:hover span {
transform: rotateY(-90deg);
}
get it
transform-origin的第三个值😈
三个值:
- 前两个值和只有两个值时的用法相同。
- 第三个值必须是距离,它始终代表Z轴偏移量。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IUc3jOYl-1683944959945)(D:\总结\img\动画\6.png)]
想象是x,y,z三个轴,等于是向z轴移动了100px
坐标轴
dom元素坐标系
每一个DOM元素都有一个这样的初始坐标系。其中,原点位于元素的左上角,z轴指向观察者(也就是屏幕外的我们)。初始坐标系的z轴并不算是三维空间,而是像z-index
那样作为参照,决定网页元素的绘制顺序,绘制顺序靠后的元素将覆盖绘制顺序靠前的。
transform元素坐标系
在使用transform的时候,情况则有所不同。transform所参照的并不是初始坐标系,而是一个新的坐标系:
transform所用的这个坐标系,相比初始坐标系,x、y、z轴的指向都不变,只是原点位置移动到了元素的正中心。如果想要改变这个坐标系的原点位置,使用transform-origin
。transform-origin
的默认值是50% 50%
,因此,默认情况下,transform坐标系的原点位于元素中心。
我们都可能像transform: rotateY(45deg) translateX(100px);
这样使用多个变换函数。这种时候,需要意识到变换函数的顺序。这是因为,每一个变换函数不仅改变了元素,同时也会改变和元素关联的transform坐标系,当变换函数依次执行时,后一个变换函数总是基于前一个变换后的新transform坐标系。
https://meyerweb.com/eric/tools/matrix/小工具测试的
只要旋转了rotate
他的坐标轴就会变,前面的就是一个很好的例子
left、top等常规属性对3d transform的影响
相对于transform的translate3d()
这类改变空间位置的变换函数,原来css里就有的定位属性left
、top
似乎会让情况变得很复杂。
对此,有一个比较推荐的分析方式:
- 就三维空间的位置而言,常规属性
left
、top
,甚至margin-left
等,是先生效的,它们的效果其实只有一个,就是改变元素的初始位置,从而改变元素的transform-origin
的那个原点位置,然后三维空间的transform是后生效的,它会再基于前面的transform-origin
继续改变位置。
perspective-origin和transform-origin的区别
现在你已经了解到,perspective-origin
是一个摄像机的属性,定义的是透视画面的灭点,而transform-origin
是任意元素都有的,定义的是的元素的transform坐标系的原点。
css
解决图片文字的问题
如果让图片之间没有间距,百度里面的答案是设置font-size:0
因为文字的底部默认会有间距
其实本质就是 vertival-align:middle
基线对齐的方式居中
img{
width:280px;
height:280px;
vertival-align:middle
}
<img/> 兮
<img/>
flot父级高度塌陷问题
BFC(块级格式化上下文)
overflow:hidden
它可以创造BFC环境
.clearflex::after{
content: ".";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
BFC
常见定位方案
- 普通流 (normal flow)
在普通流中,元素按照其在 HTML 中的先后位置至上而下布局,在这个过程中,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的一个新行,除非另外指定,否则所有元素默认都是普通流定位,也可以说,普通流中元素的位置由该元素在 HTML 文档中的位置决定。
- 浮动 (float)
在浮动布局中,元素首先按照普通流的位置出现,然后根据浮动的方向尽可能的向左边或右边偏移,其效果与印刷排版中的文本环绕相似。
- 绝对定位 (absolute positioning)
在绝对定位布局中,元素会整体脱离普通流,因此绝对定位元素不会对其兄弟元素造成影响,而元素具体的位置由绝对定位的坐标决定。
触发 BFC
只要元素满足下面任一条件即可触发 BFC 特性:
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
同一个 BFC 下外边距会发生折叠
<head>
div{
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
</head>
<body>
<div></div>
<div></div>
</body>
从效果上看,因为两个 div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 所以第一个 div 的下边距和第二个 div 的上边距发生了重叠,所以两个盒子之间距离只有 100px,而不是 200px。
首先这不是 CSS 的 bug,我们可以理解为一种规范,如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
<div class="container">
<p></p>
</div>
<div class="container">
<p></p>
</div>
.container {
overflow: hidden;
}
p {
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
BFC 可以包含浮动的元素(清除浮动)
我们都知道,浮动的元素会脱离普通文档流,来看下下面一个例子
<div style="border: 1px solid #000;">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
由于容器内元素浮动,脱离了文档流,所以容器只剩下 2px 的边距高度。如果使触发容器的 BFC,那么容器将会包裹着浮动元素。
<div style="border: 1px solid #000;overflow: hidden">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
BFC 可以阻止元素被浮动元素覆盖
先来看一个文字环绕效果:
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div>
<div style="width: 200px; height: 200px;background: #eee">我是一个没有设置浮动,
也没有触发 BFC 元素, width: 200px; height:200px; background: #eee;</div>
这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可触第二个元素的 BFC 特性,在第二个元素中加入 overflow: hidden,就会变成:
这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度(去掉上面右边内容的宽度)。
filter
https://developer.mozilla.org/zh-CN/docs/Web/CSS/filter
blur()
给图像设置高斯模糊。“radius”一值设定高斯函数的标准差,或者是屏幕上以多少像素融在一起,所以值越大越模糊;如果没有设定值,则默认是0;这个参数可设置css长度值,但不接受百分比值。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y7lQtJrp-1683944959952)(https://mdn.mozillademos.org/files/3710/Test_Form_2.jpg)]
brightness()
给图片应用一种线性乘法,使其看起来更亮或更暗。如果值是0%,图像会全黑。值是100%,则图像无变化。其他的值对应线性乘数效果。值超过100%也是可以的,图像会比原来更亮。如果没有设定值,默认是1。
contrast()
调整图像的对比度。值是0%的话,图像会全黑。值是100%,图像不变。值可以超过100%,意味着会运用更低的对比。若没有设置值,默认是1。
drop-shadow()
给图像设置一个阴影效果。阴影是合成在图像下面,可以有模糊度的,可以以特定颜色画出的遮罩图的偏移版本。 函数接受(
在CSS3背景中定义)类型的值,除了“inset”关键字是不允许的。该函数与已有的box-shadow
box-shadow
属性很相似;不同之处在于,通过滤镜,一些浏览器为了更好的性能会提供硬件加速。 参数如下:
grayscale()
将图像转换为灰度图像。值定义转换的比例。值为100%则完全转为灰度图像,值为0%图像无变化。值在0%到100%之间,则是效果的线性乘子。若未设置,值默认是0。
hue-rotate()
给图像应用色相旋转。“angle”一值设定图像会被调整的色环角度值。值为0deg,则图像无变化。若值未设置,默认值是0deg。该值虽然没有最大值,超过360deg的值相当于又绕一圈。
filter: hue-rotate(90deg)
invert()
反转输入图像。值定义转换的比例。100%的价值是完全反转。值为0%则图像无变化。值在0%和100%之间,则是效果的线性乘子。 若值未设置,值默认是0。
filter: invert(100%)
opacity()
转化图像的透明程度。值定义转换的比例。值为0%则是完全透明,值为100%则图像无变化。值在0%和100%之间,则是效果的线性乘子,也相当于图像样本乘以数量。 若值未设置,值默认是1。该函数与已有的opacity属性很相似,不同之处在于通过filter,一些浏览器为了提升性能会提供硬件加速。
filter: opacity(50%)
saturate()
转换图像饱和度。值定义转换的比例。值为0%则是完全不饱和,值为100%则图像无变化。其他值,则是效果的线性乘子。超过100%的值是允许的,则有更高的饱和度。 若值未设置,值默认是1。
filter: saturate(200%)
sepia()
将图像转换为深褐色。值定义转换的比例。值为100%则完全是深褐色的,值为0%图像无变化。值在0%到100%之间,则是效果的线性乘子。若未设置,值默认是0。
filter: sepia(100%)
复合函数
你可以组合任意数量的函数来控制渲染。下面的例子可以增强图像的对比度和亮度。
filter: contrast(175%) brightness(3%)
见代码中的小案例
火焰
值得注意的细节点
动画虽然美好,但是具体使用的过程中,仍然有一些需要注意的地方:
- CSS 滤镜可以给同个元素同时定义多个,例如
filter: contrast(150%) brightness(1.5)
,但是滤镜的先后顺序不同产生的效果也是不一样的;
也就是说,使用
filter: contrast(150%) brightness(1.5)
和filter: brightness(1.5) contrast(150%)
处理同一张图片,得到的效果是不一样的,原因在于滤镜的色值处理算法对图片处理的先后顺序。
- 滤镜动画需要大量的计算,不断的重绘页面,属于非常消耗性能的动画,使用时要注意使用场景。记得开启硬件加速及合理使用分层技术;
blur()
混合contrast()
滤镜效果,设置不同的颜色会产生不同的效果,这个颜色叠加的具体算法本文作者暂时也不是很清楚,使用时比较好的方法是多尝试不同颜色,观察取最好的效果;- CSS3 filter 兼容性不算太好,但是在移动端已经可以比较正常的使用,更为精确的兼容性列表,查询 Can i Use。
css动画
实现边框
假设我们的单标签是一个 div
:
<div></div>
定义如下通用CSS
:
div{
position:relative;
width:200px;
height:60px;
background:#ddd;
}
法一:border
这个应该是最最最容易想到的了
div{
border-left:5px solid deeppink;
}
法二:使用伪元素
一个标签,算上 before
与 after
伪元素,其实算是有三个标签,这也是很多单标签作图的基础,本题中,使用伪元素可以轻易完成。
div::after{
content:"";
width:5px;
height:60px;
position:absolute;
top:0;
left:0;
background:deeppink;
}
法三:外 box-shadow
盒阴影 box-shadow
大部分人都只是用了生成阴影,其实阴影可以有多重阴影,阴影不可以不虚化,这就需要去了解一下 box-shaodw
的每一个参数具体作用。使用 box-shaodw
解题:
div{
box-shadow:-5px 0px 0 0 deeppink;
}
法四:内 box-shadow
盒阴影还有一个参数 inset
,用于设置内阴影,也可以完成:
div{
box-shadow:inset 5px 0px 0 0 deeppink;
}
法五:drop-shadow
drop-shadow
是 CSS3 新增滤镜 filter
中的其中一个滤镜,也可以生成阴影,不过它的数值参数个数只有 3 个,比之 box-shadow 少一个。
div{
filter:drop-shadow(-5px 0 0 deeppink);
}
法六:渐变 linearGradient
灵活使用 CSS3 的渐变可以完成大量想不到的图形,CSS3 的渐变分为线性渐变和径向渐变,本题使用线性渐变,可以轻易解题:
div{
background-image:linear-gradient(90deg, deeppink 0px, deeppink 5px, transparent 5px);
}
法七:轮廓 outline
这个用的比较少,outline (轮廓)是绘制于元素周围的一条线,位于边框边缘的外围,可起到突出元素的作用。这个方法算是下下之选。
.div{
margin-left:25px;
height:50px;
outline:5px solid deeppink;
}
.div:after{
position:absolute;
content:"outline实现";
top:-5px;
bottom:-5px;
right:-5px;
left:0;
background:#ddd;
}
法八: 滚动条
这个方法由 小火柴的蓝色理想 提供,通过改变滚动条样式实现:
div{
width:205px;
background:deeppink;
overflow-y:scroll;
}
div::-webkit-scrollbar{
width: 200px;
background-color:#ddd;
}
实现不同颜色的边框
这一题主要考查的是盒子模型 Box Model
与 背景 background
的关系,以及使用 background-clip
改变背景的填充方式。
但有一点需要注意,background-color
是从元素的边框左上角起到右下角止,而 background-image
却不一样,他是从 padding
边缘的左上角起而到 border
的右下角边缘止。
可以有三种方法实现
第一种
应用的是先讲
div {
position: relative;
width: 180px;
height: 180px;
}
div {
background: #9c27b0;
border: 10px dashed #2196f3;
}
div::after {
content: "";
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: #fff;
}
第二种
用outline属性
.style_outline {
&::before{
content:"";
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
outline:20px solid #ffc107;
background:#fff;
z-index:-1;
}
第三种
div{
background:#fff;
background-clip:padding-box;
border:20px dashed #cccc99;
}
div::before{
content:"";
position:absolute;
top:-20px;
left:-20px;
bottom:-20px;
right:-20px;
background:#996699;
z-index:-1;
}
background-clip
background-clip
设置元素的背景(背景图片或颜色)是否延伸到边框下面。
background-clip: border-box; // 背景延伸到边框外沿(但是在边框之下)
background-clip: padding-box; // 边框下面没有背景,即背景延伸到内边距外沿。
background-clip: content-box; // 背景裁剪到内容区 (content-box) 外沿。
z-index
会看到,inline-block
的 div
不再一定叠在 float
的 div
之上,而是和 HTML 代码中 DOM 的堆放顺序有关,后添加的 div 会 叠在先添加的 div 之上。
这里的关键点在于,添加的 opacity:0.9
这个让两个 div 都生成了 stacking context(堆叠上下文)
的概念。此时,要对两者进行层叠排列,就需要 z-index ,z-index 越高的层叠层级越高。
那么,如何触发一个元素形成 堆叠上下文
?方法如下,摘自 MDN:
- 根元素 (HTML),
- z-index 值不为 "auto"的 绝对/相对定位,
- 一个 z-index 值不为 "auto"的 flex 项目 (flex item),即:父元素 display: flex|inline-flex,
- opacity 属性值小于 1 的元素(参考 the specification for opacity),
- transform 属性值不为 "none"的元素,
- mix-blend-mode 属性值不为 "normal"的元素,
- filter值不为“none”的元素,
- perspective值不为“none”的元素,
- isolation 属性被设置为 "isolate"的元素,
- position: fixed
- 在 will-change 中指定了任意 CSS 属性,即便你没有直接指定这些属性的值
- -webkit-overflow-scrolling 属性被设置 "touch"的元素
inherit
-webkit-box-reflect
这是一个十分新的 CSS 属性,使用起来十分简单,可以从各个方向反射我们内容。不过兼容性过于惨淡:
基本上是只有 -webkit- 内核的浏览器才支持。
其他说明
-
倒影不占据尺寸空间,是和
outline
,box-shadow
一样的那种真正意义上的不占据空间尺寸。所以,demo使用了padding值撑开间距,免得几张鸭子图片重叠在一起; -
上面提到了,倒影偏移值支持百分比,且是根据元素自身尺寸计算的。但还有一点需要补充,就是,尺寸计算的方位是根据你的倒影方向自动识别的。比说说,你的倒影方向是
below
或above
,则偏移百分比是根据原始元素的高度想计算的,如你的倒影方向是left
或right
,则根据元素的宽度来计算; -
遮罩图片可以使用CSS3渐变。并且,这里的渐变语法和CSS3
background-image
的语法几乎是一模一样的。注意这里的措辞“几乎”,说明还是有不同之处的,不同支持就是-webkit-box-reflect
的遮罩图片不支持多图(对于background的多背景),只能是一张图。其他的语法就是一模一样的。包括不仅支持线性渐变(linear-gradient
),还支持径向渐变(radial-gradient
),支持to top
或to bottom
新语法,支持
stop
断点,例如:-webkit-box-reflect: below 0 linear-gradient(transparent, white 50%, white);
-
使用遮罩图片的时候,倒影的偏移值是不能缺省的。如果没有偏移,请使用
0
占位,这也是为何示意代码中有个0
的原因; -
遮罩的最终效果与颜色无关,也就是你使用
linear-gradient(transparent, white)
和linear-gradient(transparent, black)
的效果是一模一样的,关键在于是否透明以及透明度是多少。实色遮罩的结果就是透明,透明遮罩的结果就是暴露原始色值。 -
遮罩图片也可以直接是图片,语法同
background-image
。但是有个需要注意的是,当图片应用于倒影遮罩的时候,这个图片自身也会被(因倒影)而翻转。比方说上面demo最后一个例子,遮罩出了一个“帅”字,而这个原始的“帅”文字图片是这样的:大家发现没,是倒着的。这样,倒影下来,我们就可以在倒影上看到正过来的“帅”效果了。
-
倒影效果具有实时渲染特性。也就是,如果我们突然把鸭子恢复到当年“丑小鸭”的状态,则,鸭子一定会想起不堪回事的往事。
于是,我们可以利用这一特性,实现一些很酷的动效。对吧,就那种……上面动下面也跟着一起动的那种……你应该懂的~~
inherit,使用继承
本题主要还是为了介绍这种方法,兼容性好。
inherit
是啥,每个 CSS 属性定义的概述都指出了这个属性是默认继承的 (“Inherited: Yes”) 还是默认不继承的 (“Inherited: no”)。这决定了当你没有为元素的属性指定值时该如何计算值。
灵活使用 inherit
继承父值,可以解决许多看似复杂的问题。对于本题,我们对图片容器添加一个伪元素,使用 background-image:inherit
继承父值的背景图值,就可以做到无论图片如何变,我们的 CSS 代码都无需改动:
多列均匀布局
通过给伪元素 :after
设置 inline-block
设置宽度 100%
,配合容器的 text-align: justify
就可以轻松实现多列均匀布局了。再多配合几句 hack 代码,可以实现兼容到 IE6+ ,最重要的是代码不长,很好理解。
那么为什么使用了 :after 伪元素之后就可以实现对齐了呢?
原因在于 justify 只有在存在第二行的情况下,第一行才两端对齐,所以在这里,我们需要制造一个假的第二行,而 :after 伪元素正好再适合不过。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
.container {
width: 400px;
margin: 50px auto 0;
background: #ddd;
}
.justify i {
width: 24px;
line-height: 24px;
display: inline-block;
text-indent: 9px;
background: #333;
color: white;
border-radius: 50%;
overflow: hidden;
font-style: normal;
}
.justify {
text-align: justify;
}
.justify i {
width: 24px;
line-height: 24px;
display: inline-block;
text-align: center;
border-radius: 50%;
}
.justify:after {
content: "";
display: inline-block;
position: relative;
width: 100%;
}
</style>
</head>
<body>
<div class="container">
<div class="justify">
<i>1</i>
<i>2</i>
<i>3</i>
<i>4</i>
<i>5</i>
</div>
<div class="justify">
<i>1</i>
<i>2</i>
<i>3</i>
<i>4</i>
</div>
<div class="justify">
<i>1</i>
<i>2</i>
<i>3</i>
</div>
<div class="justify">
<i>1</i>
<i>2</i>
</div>
<div class="justify">
<i>1</i>
</div>
</div>
</body>
</html>
:target伪类选择器
首先,我们要解决的问题是如何接收点击事件
,这里第一种方法我们采用 :target
伪类接收。
:target
是 CSS3 新增的一个伪类,可用于选取当前活动的目标元素。当然 URL 末尾带有锚名称 #,就可以指向文档内某个具体的元素。这个被链接的元素就是目标元素(target element)。它需要一个 id 去匹配文档中的 target 。
选项卡
运用了兄弟选择器
#content1:target,
#content2:target {
display: block;
}
#content1:target~.nav li {
background: #ddd;
color: #000;
}
#content1:target~.nav li:first-child {
background: #ff7300;
color: #fff;
}
#content2:target~.nav li {
background: #ddd;
color: #000;
}
#content2:target~.nav li:last-child {
background: #ff7300;
color: #fff;
float: right;
}
多列等高布局
法一:display:flex
#container {
width: 400px;
margin: 0 auto;
background-color: #ddd;
overflow: hidden;
display: flex;
align-items: stretch;
}
.left,
.right {
display: 1;
width: 200px;
font-size: 16px;
line-height: 24px;
color: #333;
}
.left {
background-color: deeppink;
}
.right {
background-color: yellowgreen;
}
法二:使用正负 margin 与 padding 相冲的方式实现
#container{
width:400px;
margin:0 auto;
background:#eee;
overflow:hidden;
}
.left,
.right{
width:200px;
float:left;
font-size: 16px;
line-height:24px;
color:#333;
padding-bottom:5000px;
margin-bottom:-5000px;
}
法三:父容器设置背景色实现
linear-gradient
默认情况下,从一个颜色的终止点平滑的过渡到另一个颜色的终止点,颜色之间的中点是两个颜色颜色转换的中点。你可以将中点移动到这两个颜色之间的任意位置,方法是在两个颜色之间添加未标记的 %,以指示颜色的中转位置。下面的示例是从起始点到10%的位置标记红色,从90%到结束标记蓝色。在10%到90%之间,颜色从红色过渡到蓝色,然而过渡的中点是在30%的标记上,而不是在没有30%中转点的情况下会默认为50%。
linear-gradient(red 10%, 30%, blue 90%);
如果两个或多个颜色终止在同一位置,则在该位置声明的第一个颜色和最后一个颜色之间的过渡将是一条生硬线。
颜色终止列表中颜色的终止点应该是依次递增的。如果后面的颜色终止点小于前面颜色的终止点则后面的会被覆盖,从而创建一个硬转换。下面的变化是从红色到黄色在40%的位置,然后过渡从黄色到蓝色终止于65%的位置处。
linear-gradient(red 40%, yellow 30%, blue 65%);
允许颜色多个颜色终止位置。通过在CSS声明中包含两个位置,可以将一个颜色声明为两个相邻的颜色终止。以下三个梯度是相等的:
linear-gradient(red 0%, orange 10%, orange 30%, yellow 50%, yellow 70%, green 90%, green 100%);
linear-gradient(red, orange 10% 30%, yellow 50% 70%, green 90%);
linear-gradient(red 0%, orange 10% 30%, yellow 50% 70%, green 90% 100%);
默认情况下,如果不带0%终止的颜色,则在该点声明的第一个颜色。类似地,最后一种颜色将持续到100%标记,或者如果在最后一个没有声明长度,则在100%标记处。
可以转变线的角度
linear-gradient(90deg, yellowgreen 50%, deeppink 0)
实现斜线功能
这种方法使用了背景的线性渐变实现,渐变背景很重要的一点是,虽然名字唤作渐变,但是也是可以画出实色而非渐变色。
我们选定线性渐变的方向为 45deg,依次将渐变色值设为:transparent
-> deeppink
-> deeppink
-> transparent
。
background:
linear-gradient(45deg, transparent 49.5%, deeppink 49.5%, deeppink 50.5%, transparent 50.5%);
控制文字溢出的三个属性
white-space: normal;
white-space: nowrap;
white-space: pre;
white-space: pre-wrap;
white-space: pre-line;
white-space
正如它的名字,这个属性是用来控制空白字符的显示的,同时还能控制是否自动换行。它有五个值:normal | nowrap | pre | pre-wrap | pre-line
。因为默认是normal
,所以我们主要研究下其它四种值时的展现情况。
先看下white-space:nowrap
时的情况:
<div id="box">
Hi ,
This is a incomprehensibilities long word.
</br>
你好 ,
这 是一个不可思议的长单词
</div>
white-space:nowrap
时的情况:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3LdMidSk-1683944962353)(null)]
不仅空格被合并,换行符无效,连原本的自动换行都没了!只有 </br>
才能导致换行!所以这个值的表现还是挺简单的,我们可以理解为永不换行
。
white-space:pre
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FrvXOAR0-1683944969898)(null)]
空格和换行符全都被保留了下来!不过自动换行还是没了。保留,所以pre
其实是preserve
的缩写,这样就好记了。
white-space:pre-wrap
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Faa2iim2-1683944963378)(null)]
显然pre-wrap
就是preserve
+wrap
,保留空格和换行符,且可以自动换行。
white-space:pre-line
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jupdcPig-1683944970454)(null)]
空格被合并了,但是换行符可以发挥作用,line
应该是new line
的意思,自动换行还在,所以pre-line
其实是preserve``new line
+wrap
。
我整理了一个表予以总结:
是否能发挥作用 | 换行符 | 空格 | 自动换行 | 、nbsp; |
---|---|---|---|---|
normal | × | ×(合并) | √ | √ |
nowrap | × | ×(合并) | × | √ |
pre | √ | √ | × | √ |
pre-wrap | √ | √ | √ | √ |
pre-line | √ | ×(合并) | √ | √ |
word-break
从这个名字可以知道,这个属性是控制单词如何被拆分换行的。它有三个值:normal | break-all | keep-all
。
word-break:keep-all
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AWqn0f92-1683944963892)(null)]
所有“单词”一律不拆分换行,注意,我这里的“单词”包括连续的中文字符(还有日文、韩文等),或者可以理解为只有空格可以触发自动换行
word-break:break-all
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-10INRH7D-1683944961838)(null)]
所有单词碰到边界一律拆分换行,不管你是incomprehensibilities
这样一行都显示不下的单词,还是long
这样很短的单词,只要碰到边界,都会被强制拆分换行。所以用word-break:break-all
时要慎重呀。
这样的效果好像并不太好呀,能不能就把incomprehensibilities拆一下,其它的单词不拆呢?那就需要下面这个属性了:
word-wrap(overflow-wrap)
word-wrap
又叫做overflow-wrap
:
word-wrap 属性原本属于微软的一个私有属性,在 CSS3 现在的文本规范草案中已经被重名为 overflow-wrap 。 word-wrap 现在被当作 overflow-wrap 的 “别名”。 稳定的谷歌 Chrome 和 Opera 浏览器版本支持这种新语法。
这个属性也是控制单词如何被拆分换行的,实际上是作为word-break
的互补,它只有两个值:normal | break-word
,那我们看下break-word
:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-S067kZoL-1683944962863)(null)]
终于达到了上文我们希望的效果,只有当一个单词一整行都显示不下时,才会拆分换行该单词。
所以我觉得overflow-wrap
更好理解好记一些,overflow,只有长到溢出的单词才会被强制拆分换行!
(其实前面的word-break
属性除了列出的那三个值外,也有个break-word
值,效果跟这里的word-wrap:break-word
一样,然而只有Chrome、Safari等部分浏览器支持)
总结
最后总结一下三个属性
- white-space,控制空白字符的显示,同时还能控制是否自动换行。它有五个值:
normal | nowrap | pre | pre-wrap | pre-line
- word-break,控制单词如何被拆分换行。它有三个值:
normal | break-all | keep-all
- word-wrap(overflow-wrap)控制长度超过一行的单词是否被拆分换行,是
word-break
的补充,它有两个值:normal | break-word
clip-path
https://www.zhangxinxu.com/wordpress/2014/12/css3-svg-clip-path/
生成工具https://www.html.cn/tool/css-clip-path/
insert
- 值为(上 右 下 左 round 左上角radius 右上角radius 右下角radius 左下角radius)
- round前面的数值,表示的是距离,如果第一个值为25%,则表示图像在上面从25%开始绘制。
body {
background-color: #000;
}
.fa {
border: 1px solid #fff;
color: yellowgreen;
padding: 10px;
margin: 10px;
}
.fa>div {
width: 110px;
height: 110px;
background-color: yellowgreen;
margin: 20px auto;
}
.inset1 {
clip-path: inset(25% 0% 25% 0% round 0% 25% 0% 25%)
}
.inset2 {
clip-path: inset(0% 25% 25% 0% round 25% 25% 25% 0%)
}
.inset3 {
clip-path: inset(25% 25% 0% 0% round 0% 25% 0% 25%)
}
<div class="fa">
<p>inset</p>
<p>值为(上 右 下 左 round 左上角radius 右上角radius 右下角radius 左下角radius)</p>
<p>round前面的数值,表示的是距离,如果第一个值为25%,则表示图像在上面从25%开始绘制</p>
<div class="inset1"></div>
<div class="inset2"></div>
<div class="inset3"></div>
</div>
.clip-me {
clip-path: inset(30px 56px 0 20px);
}
会看到剪裁区域大小都一样了!诶?我们不禁疑问,clip-path:inset()
四个值的玄机在哪里?很简单,虽然四个值代表的方位是一样的,分别是上边缘、右边缘、下边缘和左边缘;但是,值大小对应的则是距离原始元素的4个边的距离(传统clip是对应“上/左”2个边距离)。加减示意下就是:
此妹子图片尺寸是256 * 191
clip: rect(30px 200px 200px 20px)
=
clip-path: inset(30px (256-200)px (191-200)px 20px)
作为新时代的宠儿,自然inset
不能就矩形剪裁这么点花样,例如:
.clip-path {
-webkit-clip-path: inset(10% round 10% 50% 10% 50%);
clip-path: inset(10% round 10% 50% 10% 50%);
}
clip-path
除了作为clip
的替身,还是SVG clip-path
属性的延伸。于是,SVG中玩得比较开心的东西CSS中也同样适用:
.clip-me {
/* 剪裁路径来自内联SVG <clipPath>元素 */
clip-path: url(#c1);
/* 路径来自外部SVG */
clip-path: url(path.svg#c1);
/* 多边形 */
clip-path: polygon(5% 5%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
/* 圆 */
clip-path: circle(30px at 35px 35px);
/* 椭圆 */
clip-path: ellipse(65px 30px at 125px 40px);
}
例子–绘制三角形
https://www.cnblogs.com/liangdecha/p/9629150.html
-webkit-clip-path: polygon(50% 0,0 100%, 100% 100%);``clip-path: polygon(50% 0,0 100%, 100% 100%);
在这里先抛出一个例子方便理解,利用clip-path绘制一个三角形,每个点用逗号分开,数值(50%,0)可以理解为坐标(x,y)
三个点形成一个闭合区域,这也是页面所显示出来的区域,形成遮罩的效果
三角形绘制的大概的坐标模型,起点为元素的左上角,所以形成的是一个向下发展的坐标系
像我这种对坐标头大的同学,可以利用在线生成器,来制作一些常用的图形,可以说是非常方便了~
简介
clip-path CSS 属性可以创建一个只有元素的部分区域可以显示的剪切区域。区域内的部分显示,区域外的隐藏。剪切区域是被引用内嵌的URL定义的路径或者外部svg的路径,或者作为一个形状。clip-path属性代替了现在已经弃用的剪切 clip属性。
clip-source | basic-shape | geometry-box | none
属性说明
clip-source = url
basic-shape = inset | circle | ellipse | polygon
geometry-box = shape-box | fill-box | stroke-box | view-box
语法详解
基本图形:inset
inset() : 定义一个矩形 。注意,定义矩形不是rect,而是 inset。
语法:见上面
inset( <length-percentage>{1,4} [ round <border-radius> ]? )
//说明
inset()可以传入5个参数,分别对应top,right,bottom,left的裁剪位置,round radius(可选,圆角)
//示例
clip-path: inset(2em 3em 2em 1em round 2em);
基本图形:circle
circle() : 定义一个圆 。
circle( [ <shape-radius> ]? [ at <position> ]? )
//说明
circle()可以传人2个可选参数;
1. 圆的半径,默认元素宽高中短的那个为直径,支持百分比
2. 圆心位置,默认为元素中心点
//示例
clip-path: circle(30% at 150px 120px);
- 值为一个坐标点和半径组成。
- 左上角为原点,右下角是(100%,100%)的点。
- 定义半径的时候可以用at关键字来定义坐标。
body {
background-color: #000;
}
.fa {
border: 1px solid #fff;
color: yellowgreen;
padding: 10px;
margin: 10px;
}
.fa>div {
width: 110px;
height: 110px;
background-color: yellowgreen;
margin: 20px auto;
}
.circle1 {
clip-path: circle(50% at 50% 50%)
}
.circle2 {
clip-path: circle(70% at 50% 50%)
}
.circle3 {
clip-path: circle(30% at 10% 10%)
}
<div class="fa">
<p>circle</p>
<p>值为一个坐标点和半径组成。</p>
<p>左上角为原点,右下角是(100%,100%)的点。</p>
<p>定义半径的时候可以用at关键字来定义坐标。</p>
<div class="circle1"></div>
<div class="circle2"></div>
<div class="circle3"></div>
</div>
基本图形:ellipse
ellipse() : 定义一个椭圆 。
//语法
ellipse( [ <shape-radius>{2} ]? [ at <position> ]? )
//说明
ellipse()可以传人3个可选参数;
1. 椭圆的X轴半径,默认是宽度的一半,支持百分比
2. 椭圆的Y轴半径,默认是高度的一半,支持百分比
3. 椭圆中心位置,默认是元素的中心点
//示例
clip-path: ellipse(45% 30% at 50% 50%);
- 值为椭圆的x轴半径,y轴半径,定位椭圆的坐标三部分组成。
- 左上角为原点,右下角是(100%,100%)的点。
- at关键字将半径和坐标分开。
body {
background-color: #000;
}
.fa {
border: 1px solid #fff;
color: yellowgreen;
padding: 10px;
margin: 10px;
}
.fa>div {
width: 110px;
height: 110px;
background-color: yellowgreen;
margin: 20px auto;
}
.ellipse1 {
clip-path: ellipse(30% 20% at 50% 50%)
}
.ellipse2 {
clip-path: ellipse(20% 30% at 50% 50%)
}
.ellipse3 {
clip-path: ellipse(60% 10% at 10% 10%)
}
<div class="fa">
<p>ellipse</p>
<p>值为椭圆的x轴半径,y轴半径,定位椭圆的坐标三部分组成。</p>
<p>左上角为原点,右下角是(100%,100%)的点。</p>
<p>at关键字将半径和坐标分开</p>
<div class="ellipse1"></div>
<div class="ellipse2"></div>
<div class="ellipse3"></div>
</div>
基本图形:polygon
polygon() : 定义一个多边形 。
//语法
polygon( <fill-rule>? , [ <length-percentage> <length-percentage> ]# )
//说明
<fill-rule>可选,表示填充规则用来确定该多边形的内部。可能的值有nonzero和evenodd,默认值是nonzero
后面的每对参数表示多边形的顶点坐标(X,Y),也就是连接点
//示例
clip-path: polygon(50% 0,100% 50%,0 100%);
多边形裁剪
三角形
-webkit-clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
菱形
-webkit-clip-path: polygon(50% 0%, 100% 50%, 50% 100%, 0% 50%);
梯形
-webkit-clip-path: polygon(20% 0%, 80% 0%, 100% 100%, 0% 100%);
平行四边形
-webkit-clip-path: polygon(25% 0%, 100% 0%, 75% 100%, 0% 100%);
五边形
-webkit-clip-path: polygon(50% 0%, 100% 38%, 82% 100%, 18% 100%, 0% 38%);
六边形
-webkit-clip-path: polygon(50% 0%, 100% 25%, 100% 75%, 50% 100%, 0% 75%, 0% 25%);
七边形
-webkit-clip-path: polygon(50% 0%, 90% 20%, 100% 60%, 75% 100%, 25% 100%, 0% 60%, 10% 20%);
八边形
-webkit-clip-path: polygon(30% 0%, 70% 0%, 100% 30%, 100% 70%, 70% 100%, 30% 100%, 0% 70%, 0% 30%);
特殊图形裁剪
斜角
-webkit-clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
槽口
-webkit-clip-path: polygon(0% 15%, 15% 15%, 15% 0%, 85% 0%, 85% 15%, 100% 15%, 100% 85%, 85% 85%, 85% 100%, 15% 100%, 15% 85%, 0% 85%);
左箭头
-webkit-clip-path: polygon(40% 0%, 40% 20%, 100% 20%, 100% 80%, 40% 80%, 40% 100%, 0% 50%);
右箭头
-webkit-clip-path: polygon(0% 20%, 60% 20%, 60% 0%, 100% 50%, 60% 100%, 60% 80%, 0% 80%);
星星
-webkit-clip-path: polygon(50% 0%, 61% 35%, 98% 35%, 68% 57%, 79% 91%, 50% 70%, 21% 91%, 32% 57%, 2% 35%, 39% 35%);
十字架
-webkit-clip-path: polygon(10% 25%, 35% 25%, 35% 0%, 65% 0%, 65% 25%, 90% 25%, 90% 50%, 65% 50%, 65% 100%, 35% 100%, 35% 50%, 10% 50%);
叉号
-webkit-clip-path: polygon(20% 0%, 0% 20%, 30% 50%, 0% 80%, 20% 100%, 50% 70%, 80% 100%, 100% 80%, 70% 50%, 100% 20%, 80% 0%, 50% 30%);
对话框
-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 75%, 75% 75%, 75% 100%, 50% 75%, 0% 75%);
变形
clip-path属性支持transition,但前提是相同的裁剪函数,及相同的参数个数
下面是一个切角效果向正方形的变形过程
.outer{
width:100px;
height: 100px;
background:orange;
clip-path: polygon(20% 0%, 80% 0%, 100% 20%, 100% 80%, 80% 100%, 20% 100%, 0% 80%, 0% 20%);
transition:.5s clip-path;
}
.outer:hover{
clip-path:polygon(0 0,0 0,100% 0,100% 0,100% 100%,100% 100%,0 100%,0 100%);
}
常用伪类
:root
伪类匹配文档树的根元素。应用到HTML,:root
即表示为``元素,除了优先级更高外,相当于html标签选择器。
语法样式
:root { 样式属性 }
譬如,:root{background:#000}
,即可将页面背景色设置为黑色。
由于属于 CSS3 新增的伪类,所以也可以作为一种 HACK 元素,只对 IE9+ 生效。
介绍 :root
伪类,是因为在介绍使用 CSS变量
的时候,声明全局CSS变量时 :root
很有用。
:empty
伪类
:empty
伪类,代表没有子元素的元素。 这里说的子元素,只计算元素结点及文本(包括空格),注释、运行指令不考虑在内。
考虑一个例子:
div{
height:20px;
background:#ffcc00;
}
div:empty{
display:none;
}
<div>1</div>
<div> </div>
<div></div>
上述的例子,前两个div会正常显示,而第三个则会 display:none
隐藏。
也就是说,要想 :empty
生效,标签中连哪怕一个空格都不允许存在。
[Demo戳我::empty结构性伪类示例]
:not
伪类
CSS否定伪类,:not(X)
,可以选择除某个元素之外的所有元素。
X不能包含另外一个否定选择器。
关于 :not
伪类有几个有趣的现象:
:not
伪类不像其它伪类,它不会增加选择器的优先级。它的优先级即为它参数选择器的优先级。
我们知道,选择器是有优先级之分的,通常而言,伪类选择的权重与类选择器(class selectors,例如
.example
),属性选择器(attributes selectors,例如[type="radio"]
)的权重相同,但是有一个特例,就是:not()
。:not
否定伪类在优先级计算中不会被看作是伪类,但是在计算选择器数量时还是会把其中的选择器当做普通选择器进行计数。
- 使用
:not(*)
将匹配任何非元素的元素,因此这个规则将永远不会被应用。 - 这个选择器只会应用在一个元素上, 你不能用它在排除所有祖先元素。 举例来说, body :not(table) a 将依旧会应用在table内部的`` 上, 因为 将会被:not() 这部分选择器匹配。(摘自MDN)
:target
伪类
:target
伪类,在 #8、纯CSS的导航栏Tab切换方案
中已经实践过了,可以回过头看看。
:target
代表一个特殊的元素,若是谈论区别的话,它需要一个id去匹配文档URI的片段标识符。
:target
选择器的出现,让 CSS 也能够接受到用户的点击事件,并进行反馈。(另一个可以接收点击事件的 CSS 选择器是 :checked
)。
css变量
:root {
--bgColor: deeppink;
}
.main {
height: 100px;
background: var(--bgColor);
}
/*第二个*/
:root {
--word: "this";
--word-second: "is";
--word-third: "CSS Variable";
}
div::before {
content: var(--word)' 'var(--word-second)' 'var(--word-third);
}
div {
text-align: center;
}
/*第三个:计算*/
:root{
--margin: 10px;
}
div{
text-indent: calc(var(--margin)*10)
}
div{
width:400px;
margin:0 auto;
background:#ddd;
}
方便的从 JS 中读/写,统一修改
CSS 变量也是可以和 JS 互相交互。
:root{
--testMargin:75px;
}
// 读取
var root = getComputedStyle(document.documentElement);
var cssVariable = root.getPropertyValue('--testMargin').trim();
console.log(cssVariable); // '75px'
// 写入
document.documentElement.style.setProperty('--testMargin', '100px');
命名规则
譬如我们组内遵循的一套命名规范,其中比较重要的一部分:
- 布局:以
g
为命名空间,例如:g-wrap
、g-header
、g-content
- 状态:以
s
为命名空间,表示动态的、具有交互性质的状态,例如:s-current
、s-selected
- 工具:以
u
为命名空间,表示不耦合业务逻辑的、可复用的的工具,例如:u-clearfix
、u-ellipsis
- 组件:以
m
为命名空间,表示可复用、移植的组件模块,例如:m-slider
、m-dropMenu
- 钩子:以
j
为命名空间,表示特定给 JavaScript 调用的类名,例如:j-request
、j-open
reset.css 和Normalize.css
https://github.com/chokcoco/iCSS/issues/5
font-family
字体的分类
就 Web 常用的一些字体而言,经常听说的字体类型,大致可以分为这几种:
- serif(衬线)
- sans-serif(无衬线)
- monospace(等宽)
- fantasy(梦幻)
- cuisive(草体)
serif – 衬线字体
serif,意为有衬线的字体,衬线的意思是在字符笔画末端有叫做衬线的小细节的额外装饰,而且笔画的粗细会有所不同,这些细节在大写字母中特别明显。
OK,那么有哪些常用字体属于衬线字体呢?
宋体(SimSun)
Windows 下大部分浏览器的默认中文字体,是为适应印刷术而出现的一种汉字字体。笔画有粗细变化,是一种衬线字体,宋体在小字号下的显示效果还可以接受,但是字号一大体验就很差了,所以使用的时候要注意,不建议做标题字体使用。
Times New Roman
Mac 平台 Safari 下默认的英文字体,是最常见且广为人知的西文衬线字体之一,众多网页浏览器和文字处理软件都是用它作为默认字体。
sans-serif – 无衬线字体
sans 的意思是无,sans-serif 也就是无衬线的意思。专指西文中没有衬线的字体,与汉字字体中的黑体相对应。与衬线字体相反,该类字体通常是机械的和统一线条的,它们往往拥有相同的曲率,笔直的线条,锐利的转角。
中文下,无衬线字体就是黑体,黑体字也就是又称方体或等线体,没有衬线装饰,字形端庄,笔画横平竖直,笔迹全部一样粗细。
看看又有哪些常见的无衬线字体。
微软雅黑(Microsoft Yahei)
大名鼎鼎的微软雅黑相信都不陌生,从 windows Vista 开始,微软提供了这款新的字体,一款无衬线的黑体类字体,显著提高了字体的显示效果。现在这款字体已经成为 windows 浏览器最值得使用的中文字体。
华文黑体(STHeiti)、华文细黑(STXihei)
属于同一字体家族系列,MAC OS X 10.6 之前的简体中文系统界面的默认中文字体,正常粗细就是华文细黑,粗体下则是华文黑体。
黑体-简(Heiti SC)
从 MAC OS X 10.6 开始,黑体-简代替华文黑体用作简体中文系统界面默认字体,苹果生态最常用的字体之一,包括 iPhone、iPad 等设备用的也是这款字体。
冬青黑体(Hiragino Sans GB)
又叫苹果丽黑,Hiragino 是字游工房设计的系列字体名称。是一款清新的专业印刷字体,小字号时足够清晰,Mac OS X 10.6 开始自带有 W3 和 W6 。
Helvetica、Helvetica Neue
被广泛用于全世界使用拉丁字母和西里尔字母的国家。Helvetica 是苹果电脑的默认字体,微软常用的Arial 字体也来自于它。
Arial
Windows 平台上默认的无衬线西文字体,有多种变体,比例及字重(weight)和 Helvetica 极为相近。
Verdana
无衬线字体,优点在于它在小字上仍结构清晰端整、阅读辨识容易。
Tahoma
十分常见的无衬线字体,字体结构和 Verdana 很相似,其字元间距较小,而且对 Unicode 字集的支持范围较大。许多不喜欢 Arial 字体的人常常会改用 Tahoma 来代替,除了是因为 Tahoma 很容易取得之外,也是因为 Tahoma 没有一些 Arial 为人诟病的缺点,例如大写“i”与小写“L”难以分辨等。(这里故意反过来写)。
monospace – 等宽字体
这系列字体程序员们其实都不陌生。我们用来敲代码的编辑器,字体的选择经常就是一类等宽字体。
等宽字体是指字符宽度相同的电脑字体,常见于 IDE 或者编辑器中,每个字母的宽度相等,通常用于计算机相关书籍中排版代码块。
除了 IDE ,我们看到的技术文章中的代码块中,经常也是使用等宽字体进行排版。
Consolas
这是一套等宽的字体,属无衬线字体。这个字体使用了微软的 ClearType 字型平滑技术,主要是设计做为代码的显示字型之用,特别之处是它的“0”字加入了一斜撇,以方便与字母“O”分辨。
ClearType:由微软在其操作系统中提供的屏幕亚像素微调字体平滑工具,让 Windows 字体更加漂亮。在 Windows XP 平台上,这项技术默认是关闭,到了Windows Vista 才默认为开启。
上图是 Github 代码区块的字体设置,可以看到,默认字体就是 Consolas
,紧接着的几个都是其它等宽字体,如果用户的系统中都没有预装这些字体,则会匹配最后一个 monospace
,它表示等宽字体系列,会从用户系统中的等宽字体中选取一个展示。
fantasy – 梦幻 和 cuisive – 草体
fantasy和 cuisive 字体在浏览器中不常用,在各个浏览器中有明显的差异。
中文字体的兼容写法
一些中文字体,例如font-family: '宋体'
,由于字符编码的问题,少部分浏览器解释这个代码的时候,中文出现乱码,这个时候设定的字体无法正常显示。
所以通常会转化成对应的英文写法或者是对应的 unicode 编码,font-family:'宋体'
-> font-family: '\5b8b\4f53'
。
\5b8b\4f53
是宋体两个中文字的 unicode 编码表示。类似的写法还有:
- 黑体:
\9ED1\4F53
- 微软雅黑:
\5FAE\8F6F\96C5\9ED1
- 华文细黑:
\534E\6587\7EC6\9ED1
- 华文黑体:
\534E\6587\9ED1\4F53
Unicode编码: 人们希望在一套系统里面能够容纳所有字符,Unicode 编码解决传统的字符编码方案的局限性,每个字符占用 2 字节。这样理论上一共最多可以表示2^16(即65536)个字符。基本满足各种语言的使用。
字体定义的细节
其他一些小细节也很重要,譬如定义字体的时候,何时需要在字体两端添加引号?像这样:
p{
font-family: 'Microsoft YaHei', '黑体-简', '\5b8b\4f53';
}
当字体名字中间有空格,中文名字体及 Unicode 字符编码表示的中文字体,为了保证兼容性,都建议在字体两端添加单引号或者双引号。
字体定义顺序
字体定义顺序是一门学问,通常而言,我们定义字体的时候,会定义多个字体或字体系列。举个栗子:
body {
font-family: tahoma, arial, 'Hiragino Sans GB', '\5b8b\4f53', sans-serif;
}
别看短短 5 个字体名,其实其中门道很深。解释一下:
- 使用
tahoma
作为首选的西文字体,小字号下结构清晰端整、阅读辨识容易; - 用户电脑未预装
tohoma
,则选择arial
作为替代的西文字体,覆盖 windows 和 MAC OS; Hiragino Sans GB
为冬青黑体,首选的中文字体,保证了 MAC 用户的观看体验;- Windows 下没有预装冬青黑体,则使用 ‘\5b8b\4f53’ 宋体为替代的中文字体方案,小字号下有着不错的效果;
- 最后使用无衬线系列字体
sans-serif
结尾,保证旧版本操作系统用户能选中一款电脑预装的无衬线字体,向下兼容。
嗯,其实上面的 font-family
就是淘宝首页 body
的字体定义,非常的规范,每一个字体的定义都有它的意义。
字体书写规则
综上,总结一下,我觉得字体 font-family
定义的原则大概遵循:
1、兼顾中西
中文或者西文(英文)都要考虑到。
2、西文在前,中文在后
由于大部分中文字体也是带有英文部分的,但是英文部分又不怎么好看,同理英文字体中大多不包含中文。
所以通常会先进行英文字体的声明,选择最优的英文字体,这样不会影响到中文字体的选择,中文字体声明则紧随其次。
3、兼顾多操作系统
选择字体的时候要考虑多操作系统。例如 MAC OS 下的很多中文字体在 Windows 都没有预装,为了保证 MAC 用户的体验,在定义中文字体的时候,先定义 MAC 用户的中文字体,再定义 Windows 用户的中文字体;
4、兼顾旧操作系统,以字体族系列 serif
和 sans-serif
结尾
当使用一些非常新的字体时,要考虑向下兼容,兼顾到一些极旧的操作系统,使用字体族系列 serif
和 sans-serif
结尾总归是不错的选择。
position
position:sticky
https://developer.mozilla.org/zh-CN/docs/Web/CSS/position
生效规则
position:sticky
的生效是有一定的限制的,总结如下:
- 须指定 top, right, bottom 或 left 四个阈值其中之一,才可使粘性定位生效。否则其行为与相对定位相同。
- 并且
top
和bottom
同时设置时,top
生效的优先级高,left
和right
同时设置时,left
的优先级高。
- 并且
- 设定为
position:sticky
元素的任意父节点的 overflow 属性必须是 visible,否则position:sticky
不会生效。这里需要解释一下:- 如果
position:sticky
元素的任意父节点定位设置为position:overflow
,则父容器无法进行滚动,所以position:sticky
元素也不会有滚动然后固定的情况。 - 如果
position:sticky
元素的任意父节点定位设置为position:relative | absolute | fixed
,则元素相对父元素进行定位,而不会相对 viewprot 定位。
- 如果
- 达到设定的阀值。这个还算好理解,也就是设定了
position:sticky
的元素表现为relative
还是fixed
是根据元素是否达到设定了的阈值决定的。
position:initial/inherit/unset
{
position: initial;
position: inherit;
position: unset
/* CSS Cascading and Inheritance Level 4 */
position: revert;
}
initial
initial
关键字用于设置 CSS 属性为它的默认值,可作用于任何 CSS 样式。(IE 不支持该关键字)
inherit
每一个 CSS 属性都有一个特性就是,这个属性必然是默认继承的 (inherited: Yes
) 或者是默认不继承的 (inherited: no
)其中之一,我们可以在 MDN 上通过这个索引查找,判断一个属性的是否继承特性。
譬如,以 background-color
为例,由下图所示,表明它并不会继承父元素的 background-color
:
可继承属性
最后罗列一下默认为 inherited: Yes
的属性:
- 所有元素可继承:visibility 和 cursor
- 内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction
- 块状元素可继承:text-indent和text-align
- 列表元素可继承:list-style、list-style-type、list-style-position、list-style-image
- 表格元素可继承:border-collapse
还有一些 inherit 的妙用可以看看这里:谈谈一些有趣的CSS题目(四)-- 从倒影说起,谈谈 CSS 继承 inherit,合理的运用 inherit 可以让我们的 CSS 代码更加符合 DRY(Don‘’t Repeat Yourself )原则。
unset
名如其意,unset
关键字我们可以简单理解为不设置。其实,它是关键字 initial
和 inherit
的组合。
什么意思呢?也就是当我们给一个 CSS 属性设置了 unset
的话:
- 如果该属性是默认继承属性,该值等同于
inherit
- 如果该属性是非继承属性,该值等同于
initial
举个例子,先列举一些 CSS 中默认继承父级样式的属性:
- 部分可继承样式:
font-size
,font-family
,color
,text-indent
- 部分不可继承样式:
border
,padding
,margin
,width
,height
使用 unset
继承父级样式:
看看下面这个简单的结构:
<div class="father">
<div class="children">子级元素一</div>
<div class="children unset">子级元素二</div>
</div>
.father {
color: red;
border: 1px solid black;
}
.children {
color: green;
border: 1px solid blue;
}
.unset {
color: unset;
border: unset;
}
- 由于
color
是可继承样式,设置了color: unset
的元素,最终表现为了父级的颜色red
。 - 由于
border
是不可继承样式,设置了border: unset
的元素,最终表现为border: initial
,也就是默认 border 样式,无边框。
unset
的一些妙用
例如下面这种情况,在我们的页面上有两个结构类似的 position: fixed
定位元素。
区别是其中一个是 top:0; left: 0;
,另一个是 top:0; right: 0;
。其他样式相同。
假设样式结构如下:
<div class="container">
<div class="left">fixed-left</div>
<div class="right">fixed-right</div>
</div>
通常而言,样式如下:
.left,
.right {
position: fixed;
top: 0;
}
.left {
left: 0;
}
.right {
right: 0;
}
使用 unset 的方法:
.left,
.right {
position: fixed;
top: 0;
left: 0;
}
.right {
left: unset;
right: 0;
}
@supports
CSS @supports
通过 CSS 语法来实现特性检测,并在内部 CSS 区块中写入如果特性检测通过希望实现的 CSS 语句。
语法:
@supports <supports_condition> {
/* specific rules */
}
举个例子:
div {
position: fixed;
}
@supports (position:sticky) {
div {
position:sticky;
}
}
上面的例子中,position: sticky
是 position 的一个新属性,用于实现黏性布局,可以轻松实现一些以往需要 javascript 才能实现的布局(戳我了解详情),但是目前只有在 -webkit- 内核下才得到支持。
上面的写法,首先定义了 div 的 position: fixed
,紧接着下面一句 @supports (position:sticky)
则是特性检测括号内的内容,如果当前浏览器支持 @supports
语法,并且支持 position:sticky
语法,那么 div 的 则会被设置为 position:sticky
。
我们可以看到,@supports
语法的核心就在于这一句:@supports (...) { }
,括号内是一个 CSS 表达式,如果浏览器判断括号内的表达式合法,那么接下来就会去渲染括号内的 CSS 表达式。除了这种最常规的用法,还可以配合其他几个关键字:
@supports not
&& @supports and
&& @supports or
@supports not
– 非
not 操作符可以放在任何表达式的前面来产生一个新的表达式,新的表达式为原表达式的值的否定。看个例子:
@supports not (background: linear-gradient(90deg, red, yellow)) {
div {
background: red;
}
}
因为添加了 not 关键字,所以与上面第一个例子相反,这里如果检测到浏览器不支持线性渐变 background: linear-gradient(90deg, red, yellow)
的语法,则将 div 的颜色设置为红色 background: red
。
@supports and
– 与
这个也好理解,多重判断,类似 javascript 的 &&
运算符符。用 and 操作符连接两个原始的表达式。只有两个原始表达式的值都为真,生成的表达式才为真,反之为假。
当然,and 可以连接任意多个表达式看个例子:
p {
overflow: hidden;
text-overflow: ellipsis;
}
@supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical) {
p {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
}
}
上面同时,检测 @supports (display:-webkit-box) and (-webkit-line-clamp:2) and (-webkit-box-orient:vertical)
了三个语法,如果同时支持,则设定三个 CSS 规则。这三个语法必须同时得到浏览器的支持,如果表达式为真,则可以用于实现多行省略效果:
@supports or
– 或
理解了 @supports and
,就很好理解 @supports or
了,与 javascript 的 ||
运算符类似,表达式中只要有一个为真,则生成表达式表达式为真。
看例子:
@supports (background:-webkit-linear-gradient(0deg, yellow, red)) or (background:linear-gradient(90deg, yellow, red)){
div {
background:-webkit-linear-gradient(0deg, yellow, red);
background:linear-gradient(90deg, yellow, red)
}
}
上面的例子中,只有检测到浏览器支持 background:-webkit-linear-gradient(0deg, yellow, red)
或者(or) background:linear-gradient(90deg, yellow, red)
其中一个,则给 div 元素添加渐变。
CSS.supports()
谈到了 @supports
,就有必要再说说 CSS.supports()
。
它是作为 @supports
的另一种形式出现的,我们可以使用 javascript 的方式来获得 CSS 属性的支持情况。
可以打开控制台,输入 CSS.supports
试试:
如果没有自己实现 CSS.supports 这个方法,输出上述信息,表示浏览器是支持 @supports
语法的,使用如下:
CSS.supports('display', 'flex') // true
CSS.supports('position', 'sticky') // true
那它有什么用呢?如果你的页面需要动态添加一些你不确定哪些浏览器支持的新的属性,那它也许会派上用场。以及,它可以配合我们下文即将要讲的 modernizr 。
modernizr
上面介绍了 CSS 方式的特性检测,在以前,通常是使用 javascript 来进行特性检测的,其中 modernizr 就是其中最为出色的佼佼者。
modernizr(戳我查看 Github )是一个开源的 javascript 库。有着将近 2W 的 star ,其优秀程度可见一斑。
简单看看使用方法,假设页面已经引用了 modernizr ,语法如下:
// Listen to a test, give it a callback
Modernizr.on('testname', function( result ) {
if (result) {
console.log('The test passed!');
}
else {
console.log('The test failed!');
}
});
// 或者是类似 CSS.supports()
Modernizr.testAllProps('background', 'linear-gradient(90deg, #888, #ccc)'); // true
举个实际的例子,假设我们希望对是否支持渐变这个样式浏览器下的一个 div 区别对待,有如下 CSS:
div {
background: #aaa;
}
.linear-gradient div{
background: linear-gradient(90deg, #888, #ccc);
}
使用 Modernizr 进行判断,如果支持渐变,则在根元素添加一个 .linear-gradient
样式,方便示例,使用了 jquery 语法:
if (Modernizr.testAllProps('background', 'linear-gradient(90deg, #888, #ccc)')) {
$('html').addClass('linear-gradient');
}
当然,Modernizr 还有很多其他的功能,可以去翻翻它的 API 。
特性检测原理
如果嫌引入整一个 Modernizr 库太大,页面又不支持 @supports
,其实我们自己用简单的 javascript 实现也非常方便简单。
想要知道浏览器支持多少 CSS 属性,可以在调试窗口试试:
var root = document.documentElement; //HTML
for(var key in root.style) {
console.log(key);
}
上面图片截取的只是打印出来的一小部分。如果我们要检测某个属性样式是否被支持,在任意的 element.style 检测它是否存在即可,即上面代码示例的 root
可以替换成任意元素。
当然,元素可能有 background
属性,但是不支持具体的 linear-gradinet()
属性值。这个时候该如何检测呢?只需要将具体的值赋值给某一元素,再查询这个属性值能否被读取。
var root = document.documentElement;
root.style.backgroundImage = 'linear-gradient(90deg, #888, #ccc)';
if(root.style.backgroundImage) {
// 支持
} else {
// 不支持
}
所以上面 Modernizr 的例子里,javascript 代码可以改成:
var root = document.documentElement;
root.style.backgroundImage = 'linear-gradient(90deg, #888, #ccc)';
if(root.style.backgroundImage) {
$('html').addClass('linear-gradient');
}
当然,做这种特定属性值判断的时候由于有个 CSS 赋值操作,所以我们选取用于判断的元素应该是一个隐藏在页面上的元素。
各种方式间的优劣
- 原生的
@supports
的性能肯定是最好的,而且无需引入外部 javascript ,首推这个,但是无奈兼容问题,目前来看不是最好的选择。 - Modernizr 功能强大,兼容性好,但是需要引入外部 javascript,多一个 http 请求,如果只是进行几个特性检测,有点杀鸡用牛刀的感觉。
- 针对需要的特性检测,使用 javascript 实现一个简单的函数,再把上面用到的方法封装一下:
/**
* 用于简单的 CSS 特性检测
* @param [String] property 需要检测的 CSS 属性名
* @param [String] value 样式的具体属性值
* @return [Boolean] 是否通过检查
*/
function cssTest(property, value) {
// 用于测试的元素,隐藏在页面上
var ele = document.getElementById('test-display-none');
// 只有一个参数的情况
if(arguments.length === 1) {
if(property in ele.style) {
return true;
}
// 两个参数的情况
}else if(arguments.length === 2){
ele.style[property] = value;
if(ele.style[property]) {
return true;
}
}
return false;
}
软件工程没有银弹,所以无论哪种方式,都有适合的场景,我们要做的就是掌握了解它们的原理,根据不同的场景灵活运用即可。
瀑布流
https://github.com/chokcoco/iCSS/issues/40
amation播放于暫停
我们知道,在 CSS3 animation 中,有这样一个属性可以播放、暂停动画:
{
animation-play-state: paused | running;
}
animation-play-state: 属性定义一个动画是否运行或者暂停。可以通过查询它来确定动画是否正在运行。另外,它的值可以被设置为暂停和恢复的动画的重放。
如果借助 Javascrip,我们可以实现控制 CSS 动画的运行和播放,下面列出部分关键代码:
<div class="btn">stop</div>
<div class="animation"></div>
<style>
.animation {
animation: move 2s linear infinite alternate;
}
@keyframes move {
0% {
transform: translate(-100px, 0);
}
100% {
transform: translate(100px, 0);
}
}
</style>
document.querySelector('.btn').addEventListener('click', function() {
let btn = document.querySelector('.btn');
let elem = document.querySelector('.animation');
let state = elem.style['animationPlayState'];
if(state === 'paused') {
elem.style['animationPlayState'] = 'running';
btn.innerText = 'stop';
} else {
elem.style['animationPlayState'] = 'paused';
btn.innerText = 'play';
}
});
CodePen – Demo – pause CSS Animation
纯 CSS 实现
下面我们探讨下,使用纯 CSS 的方式能否实现。
hover 伪类实现
使用 hover 伪类,在鼠标悬停在按钮上面时,控制动画样式的暂停。
关键代码如下:
<div class="btn stop">stop</div>
<div class="animation"></div>
<style>
.stop:hover ~ .animation {
animation-play-state: paused;
}
</style>
Demo – 纯 CSS 方式实现 CSS 动画的暂停与播放 (Hover)
当然,这个方法不够智能,如果释放鼠标的自由,点击一下暂停、再点击一下播放就好了。还有其他方法吗?
checked 伪类实现
之前的文章也谈过,使用 radio
标签的 checked
伪类,加上 `` 实现纯 CSS 捕获点击事情。
并且利用被点击的元素可以控制一些 CSS 样式。实现如下:
<input id="stop" type="radio" />
<input id="play" type="radio" />
<div class="box">
<label for="stop">
<div class="btn">stop</div>
</label>
<label for="play">
<div class="btn">play</div>
</label>
</div>
<div class="animation"></div>
部分关键 CSS 代码:
.animation {
animation: move 2s linear infinite alternate;
}
#stop:checked ~ .animation {
animation-play-state: paused;
}
#play:checked ~ .animation {
animation-play-state: running;
}
我们希望当 #stop
和 #play
两个 radio 被击时,给 .animation
元素分别赋予 animation-play-state: paused
或是 animation-play-state: running
。
transform 代替 left、top,减少使用耗性能样式
现代浏览器在完成以下四种属性的动画时,消耗成本较低:
- position(位置):
transform: translate(npx, npx)
- scale(比例缩放):
transform: scale(n)
- rotation(旋转) :
transform: rotate(ndeg)
- opacity(透明度):
opacity: 0...1
正常而言,在生产环境下,我们可能需要使用如下代码,开启硬件加速:
{
will-change: transform;
transform: translateZ(0);
}
将文字设置背景颜色
-webkit-background-clip: text;
div {
margin: 50px auto;
font-size: 54px;
font-weight: bold;
text-align: center;
text-transform: uppercase;
color: transparent;
background: linear-gradient(0, #009688 0%, yellowgreen 100%);
/*background: url('https://unsplash.it/1200/400?image=1067') no-repeat;*/
/*background-size: cover;*/
/*background-position: center center;*/
-webkit-background-clip: text;
}
主要的样式
color: transparent;
-webkit-background-clip: text;
从中间向两边开门
.btn01:after {
content: "";
position: absolute;
width: 0%;
height: 100%;
top: 0%;
left: 50%;
background: deeppink;
z-index: -1;
transition: width 0.5s, left 0.5s;
}
.btn01:hover:after{
width: 100%;
left: 0;
}
conic-gradient
圆形颜色渐变实现贴图
方形贴图
#div1 {
width: 250px;
height: 250px;
margin: 50px auto;
background:
conic-gradient(#000 12.5%, #fff 0 37.5%, #000 0 62.5%, #fff 0 87.5%, #000 0);
position: absolute;
left: 61%;
top: 0%;
background-size: 50px 50px;
}
重复角向渐变 repaeting-conic-gradient
div {
width: 100vw;
height: 100vh;
margin: 0;
background: radial-gradient(#f5a698, black);
}
div:before, div:after {
position: absolute;
top: 50%;
left: 50%;
margin: -100vmax;
width: 200vmax;
height: 200vmax;
opacity: .5;
mix-blend-mode: overlay;
-webkit-animation: rotate 10.5s ease-in-out infinite;
animation: rotate 10.5s ease-in-out infinite;
content: '';
}
div:before {
background: conic-gradient(rgba(3, 10, 0, 0.71), rgba(3, 10, 0, 0.83), rgba(3, 10, 0, 0.9), rgba(3, 10, 0, 0.69), rgba(3, 10, 0, 0.37), rgba(3, 10, 0, 0.09), rgba(3, 10, 0, 0.29), rgba(3, 10, 0, 0.95), rgba(3, 10, 0, 0.5), rgba(3, 10, 0, 0.97), rgba(3, 10, 0, 0.07), rgba(3, 10, 0, 0.56), rgba(3, 10, 0, 0.74), rgba(3, 10, 0, 0.01), rgba(3, 10, 0, 0.52), rgba(3, 10, 0, 0.23), rgba(3, 10, 0, 0.6), rgba(3, 10, 0, 0.29), rgba(3, 10, 0, 0.1), rgba(3, 10, 0, 0.82), rgba(3, 10, 0, 0.97), rgba(3, 10, 0, 0.85), rgba(3, 10, 0, 0.12), rgba(3, 10, 0, 0.11), rgba(3, 10, 0, 0.56), rgba(3, 10, 0, 0.9), rgba(3, 10, 0, 0.07), rgba(3, 10, 0, 0.97), rgba(3, 10, 0, 0.44), rgba(4, 9, 1, 0.77), rgba(3, 10, 0, 0.81), rgba(3, 10, 0, 0.71), rgba(3, 10, 0, 0.83), rgba(3, 10, 0, 0.9), rgba(3, 10, 0, 0.69), rgba(3, 10, 0, 0.37), rgba(3, 10, 0, 0.09), rgba(3, 10, 0, 0.29), rgba(3, 10, 0, 0.95), rgba(3, 10, 0, 0.5), rgba(3, 10, 0, 0.97), rgba(3, 10, 0, 0.07), rgba(3, 10, 0, 0.56), rgba(3, 10, 0, 0.74), rgba(3, 10, 0, 0.01), rgba(3, 10, 0, 0.52), rgba(3, 10, 0, 0.23), rgba(3, 10, 0, 0.6), rgba(3, 10, 0, 0.29), rgba(3, 10, 0, 0.1), rgba(3, 10, 0, 0.82), rgba(3, 10, 0, 0.97), rgba(3, 10, 0, 0.85), rgba(3, 10, 0, 0.12), rgba(3, 10, 0, 0.11), rgba(3, 10, 0, 0.56), rgba(3, 10, 0, 0.9), rgba(3, 10, 0, 0.07), rgba(3, 10, 0, 0.97), rgba(3, 10, 0, 0.44), rgba(4, 9, 1, 0.77));
}
div:after {
background: conic-gradient(rgba(3, 10, 0, 0.1), rgba(3, 10, 0, 0.98), rgba(3, 10, 0, 0.49), rgba(3, 10, 0, 0.36), rgba(3, 10, 0, 0.04), rgba(3, 10, 0, 0.47), rgba(3, 10, 0, 0.33), rgba(4, 9, 2, 0.84), rgba(3, 10, 0, 0.5), rgba(3, 10, 0, 0.47), rgba(3, 10, 0, 0.91), rgba(3, 10, 0, 0.34), rgba(3, 10, 0, 0.23), rgba(3, 10, 0, 0.72), rgba(3, 10, 0, 0.08), rgba(3, 10, 0, 0.12), rgba(3, 10, 0, 0.81), rgba(3, 10, 0, 0.1), rgba(3, 10, 0, 0.98), rgba(3, 10, 0, 0.49), rgba(3, 10, 0, 0.36), rgba(3, 10, 0, 0.04), rgba(3, 10, 0, 0.47), rgba(3, 10, 0, 0.33), rgba(4, 9, 2, 0.84), rgba(3, 10, 0, 0.5), rgba(3, 10, 0, 0.47), rgba(3, 10, 0, 0.91), rgba(3, 10, 0, 0.34), rgba(3, 10, 0, 0.23), rgba(3, 10, 0, 0.72), rgba(3, 10, 0, 0.08), rgba(3, 10, 0, 0.12));
-webkit-animation-duration: 3.2s;
animation-duration: 3.2s;
animation-direction: reverse;
}
@-webkit-keyframes rotate {
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
@keyframes rotate {
to {
-webkit-transform: rotate(1turn);
transform: rotate(1turn);
}
}
mix-blend-mode
{
mix-blend-mode: normal; // 正常
mix-blend-mode: multiply; // 正片叠底
mix-blend-mode: screen; // 滤色
mix-blend-mode: overlay; // 叠加
mix-blend-mode: darken; // 变暗
mix-blend-mode: lighten; // 变亮
mix-blend-mode: color-dodge; // 颜色减淡
mix-blend-mode: color-burn; // 颜色加深
mix-blend-mode: hard-light; // 强光
mix-blend-mode: soft-light; // 柔光
mix-blend-mode: difference; // 差值
mix-blend-mode: exclusion; // 排除
mix-blend-mode: hue; // 色相
mix-blend-mode: saturation; // 饱和度
mix-blend-mode: color; // 颜色
mix-blend-mode: luminosity; // 亮度
mix-blend-mode: initial;
mix-blend-mode: inherit;
mix-blend-mode: unset;
}
面试问题
margin塌陷的问题如何解决
- 把子盒子块级标签转换成行内块标签
- 把子盒子的margin-top改成padding-top
- 把子盒子加一个边框
- 把父盒子加一个
overflow:hidden
font-size:0/text-indent:-9999
https://www.jianshu.com/p/48f9805f1b06
解决文字或者图片之间空隙的问题
div {
font-size: 0;
}
direction:rtl;
ltr | 默认。文本方向从左到右。 |
---|---|
rtl | 文本方向从右到左。 |
inherit | 规定应该从父元素继承 direction 属性的值。 |
user-select: none;
用户不可以选中文本
**none:**文本不能被选择
**text:**可以选择文本
**all:**当所有内容作为一个整体时可以被选择。如果双击或者在 上下文上点击子元素,那么被选择的部分将是以该子元素 向上回溯的最高祖先元素。
**Element:**可以选择文本,但选择范围受元素边界的约束
- 但支持使用标签属性
onselectstart="return false;"
来达到user-select:none
的效果;Safari和Chrome也支持该标签属性; - 直到Opera12.5仍然不支持该属性,但和IE6-9一样,也支持使用私有的标签属性
unselectable="on"
来达到user-select:none
的效果;unselectable 的另一个值是 off; - 除Chrome和Safari外,在其它浏览器中,如果将文本设置为
-ms-user-select:none;
,则用户将无法在该文本块中开始选择文本。不过,如果用户在页面的其他区域开始选择文本,则用户仍然可以继续选择将文本设置为-ms-user-select:none;
的区域文本;
resize
<!DOCTYPE html>
<html>
<head>
<style>
div
{
border:2px solid;
padding:10px 40px;
width:300px;
resize:both;
overflow:auto;
}
</style>
</head>
<body>
<div>resize 属性规定是否可由用户调整元素尺寸。</div>
<p><b>注释:</b> Firefox 4+、Safari 以及 Chrome 支持 resize 属性。</p>
</body>
</html>
outline
none | 默认。定义无轮廓。 |
---|---|
dotted | 定义点状的轮廓。 |
dashed | 定义虚线轮廓。 |
solid | 定义实线轮廓。 |
double | 定义双线轮廓。双线的宽度等同于 outline-width 的值。 |
groove | 定义 3D 凹槽轮廓。此效果取决于 outline-color 值。 |
ridge | 定义 3D 凸槽轮廓。此效果取决于 outline-color 值。 |
inset | 定义 3D 凹边轮廓。此效果取决于 outline-color 值。 |
outset | 定义 3D 凸边轮廓。此效果取决于 outline-color 值。 |
inherit | 规定应该从父元素继承轮廓样式的设置。 |
<!DOCTYPE html>
<html>
<head>
<style>
div {
margin:20px;
width:150px;
padding:10px;
height:70px;
border:2px solid black;
outline:10px groove red;
outline-offset:15px;
}
</style>
</head>
<body>
<p><b>注释:</b>Internet Explorer 和 Opera 不支持 support outline-offset 属性。</p>
<div>这个 div 在边框边缘之外 15 像素处有一个轮廓。</div>
</body>
</html>
border-image-slice
https://developer.mozilla.org/en-US/docs/Web/CSS/border-image-slice
https://blog.csdn.net/dengdai848586/article/details/51488700
scss
https://zhuanlan.zhihu.com/p/48504021
font-family: ‘Playball’, cursive;
1px像素问题
伪类 + transform 实现
.border-1px{
position: relative;
margin-bottom: 20px;
border:none;
}
.border-1px:after{a
display :block ;
position :absolute;
bottom :0;
left :0 ;
width:100%;
border-top:1px solid $color;
content :' ';
}
@media (-webkit-min-device-pixel-ratio: 1.5),(min-device-pixel-ratio:1.5) {
.border-1px
&::after
-webkit-transform:scaleY(0.7)
transform:scaleY(0.7);
}
@media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio:2){
.border-1px
&::after
-webkit-transform:scaleY(0.5)
transform:scaleY(0.5);
}
让文字不换行
text-align: justify;
p.test {word-break:break-all;}
https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-origin ↩︎