共计 12871 个字符,预计需要花费 33 分钟才能阅读完成。
注:本文内容分享转载自 HarmonyOS Developer 官网文档
一. CSS 语法参考
CSS 是形容 HML 页面构造的款式语言。所有组件均存在零碎默认款式,也可在页面 CSS 款式文件中对组件、页面自定义不同的款式。请参考通用款式理解兼容 JS 的类 Web 开发范式反对的组件款式。
尺寸单位
● 逻辑像素 px(文档中以 <length> 示意):
○ 默认屏幕具备的逻辑宽度为 720px(配置见配置文件中的 window 大节),理论显示时会将页面布局缩放至屏幕理论宽度,如 100px 在理论宽度为 1440 物理像素的屏幕上,理论渲染为 200 物理像素(从 720px 向 1440 物理像素,所有尺寸放大 2 倍)。
○ 额定配置 autoDesignWidth 为 true 时(配置见配置文件中的 window 大节),逻辑像素 px 将依照屏幕密度进行缩放,如 100px 在屏幕密度为 3 的设施上,理论渲染为 300 物理像素。利用须要适配多种设施时,倡议采纳此办法。
● 百分比(文档中以 <percentage> 示意):示意该组件占父组件尺寸的百分比,如组件的 width 设置为 50%,代表其宽度为父组件的 50%。
款式导入
为了模块化治理和代码复用,CSS 款式文件反对 @import 语句,导入 css 文件。
申明款式
每个页面目录下存在一个与布局 hml 文件同名的 css 文件,用来形容该 hml 页面中组件的款式,决定组件应该如何显示。
1. 外部款式,反对应用 style、class 属性来管制组件的款式。例如:
<!-- index.hml --> | |
<div class="container"> | |
<text style="color: red">Hello World</text> | |
</div> |
/* index.css */ | |
.container {justify-content: center;} |
2. 文件导入,合并内部款式文件。例如,在 common 目录中定义款式文件 style.css,并在 index.css 文件首行中进行导入:、
/* style.css */ | |
.title {font-size: 50px;} |
/* index.css */ | |
@import '../../common/style.css'; | |
.container {justify-content: center;} |
选择器
css 选择器用于抉择须要增加款式的元素,反对的选择器如下表所示:
示例:
<!-- 页面布局 xxx.hml --> | |
<div id="containerId" class="container"> | |
<text id="titleId" class="title"> 题目 </text> | |
<div class="content"> | |
<text id="contentId"> 内容 </text> | |
</div> | |
</div> |
/* 页面款式 xxx.css */ | |
/* 对所有 div 组件设置款式 */ | |
div {flex-direction: column;} | |
/* 对 class="title" 的组件设置款式 */ | |
.title {font-size: 30px;} | |
/* 对 id="contentId" 的组件设置款式 */ | |
#contentId {font-size: 20px;} | |
/* 对所有 class="title" 以及 class="content" 的组件都设置 padding 为 5px */ | |
.title, .content {padding: 5px;} | |
/* 对 class="container" 的组件下的所有 text 设置款式 */ | |
.container text {color: #007dff;} | |
/* 对 class="container" 的组件下的间接后辈 text 设置款式 */ | |
.container > text {color: #fa2a2d;} |
以上款式运行成果如下:
其中“.container text”将“题目”和“内容”设置为蓝色,而“.container > text”间接后辈选择器将“题目”设置为红色。2 者优先级雷同,但间接后辈选择器申明程序靠后,将前者款式笼罩(优先级计算见选择器优先级)。
选择器优先级
选择器的优先级计算规定与 w3c 规定保持一致(只反对:内联款式,id,class,tag,后辈和间接后辈),其中内联款式为在元素 style 属性中申明的款式。
当多条选择器申明匹配到同一元素时,各类选择器优先级由高到低程序为:内联款式 > id > class > tag。
伪类
css 伪类是选择器中的关键字,用于指定要抉择元素的非凡状态。例如,:disabled 状态能够用来设置元素的 disabled 属性变为 true 时的款式。
除了单个伪类之外,还反对伪类的组合,例如,:focus:checked 状态能够用来设置元素的 focus 属性和 checked 属性同时为 true 时的款式。反对的单个伪类如下表所示,依照优先级降序排列:
伪类示例如下,设置按钮的:active 伪类能够管制被用户按下时的款式:
<!-- index.hml --> | |
<div class="container"> | |
<input type="button" class="button" value="Button"></input> | |
</div> |
/* index.css */ | |
.button:active {background-color: #888888;/* 按钮被激活时,背景色彩变为 #888888 */} |
阐明
针对弹窗类组件及其子元素不反对伪类成果,包含 popup、dialog、menu、option、picker
款式预编译
预编译提供了利用特有语法生成 css 的程序,能够提供变量、运算等性能,令开发者更便捷地定义组件款式,目前反对 less、sass 和 scss 的预编译。应用款式预编译时,须要将原 css 文件后缀改为 less、sass 或 scss,如 index.css 改为 index.less、index.sass 或 index.scss。
● 以后文件应用款式预编译,例如将原 index.css 改为 index.less:
/* index.less */ | |
/* 定义变量 */ | |
@colorBackground: #000000; | |
.container {background-color: @colorBackground; /* 应用以后 less 文件中定义的变量 */} |
● 援用预编译文件,例如 common 中存在 style.scss 文件,将原 index.css 改为 index.scss,并引入 style.scss:
/* style.scss */ | |
/* 定义变量 */ | |
$colorBackground: #000000; |
在 index.scss 中援用:
/* index.scss */ | |
/* 引入内部 scss 文件 */ | |
@import '../../common/style.scss'; | |
.container {background-color: $colorBackground; /* 应用 style.scss 中定义的变量 */} |
阐明
援用的预编译文件倡议放在 common 目录进行治理。
CSS 款式继承 6+
css 款式继承提供了子节点继承父节点款式的能力,继承下来的款式在多选择器款式匹配的场景下,优先级排最低,以后反对以下款式的继承:
● font-family
● font-weight
● font-size
● font-style
● text-align
● line-height
● letter-spacing
● color
● visibility
二. CSS 动画
1. 属性款式动画
在关键帧(Keyframes)中动静设置父组件的 width 和 height,实现组件变大放大。子组件设置 scale 属性使父子组件同时缩放,再设置 opacity 实现父子组件的显示与暗藏。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="fade"> | |
<text>fading away</text> | |
</div> | |
<div class="bigger"> | |
<text>getting bigger</text> | |
</div> | |
</div> |
/* xxx.css */ | |
.container { | |
background-color:#F1F3F5; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
flex-direction: column; | |
width: 100%; | |
height: 100%; | |
} | |
.fade { | |
width: 30%; | |
height: 200px; | |
left: 35%; | |
top: 25%; | |
position: absolute; | |
animation: 2s change infinite friction; | |
} | |
.bigger { | |
width: 20%; | |
height: 100px; | |
background-color: blue; | |
animation: 2s change1 infinite linear-out-slow-in; | |
} | |
text { | |
width: 100%; | |
height: 100%; | |
text-align: center; | |
color: white; | |
font-size: 35px; | |
animation: 2s change2 infinite linear-out-slow-in; | |
} | |
/* 色彩变动 */ | |
@keyframes change{ | |
from { | |
background-color: #f76160; | |
opacity: 1; | |
} | |
to { | |
background-color: #09ba07; | |
opacity: 0; | |
} | |
} | |
/* 父组件大小变动 */ | |
@keyframes change1 { | |
0% { | |
width: 20%; | |
height: 100px; | |
} | |
100% { | |
width: 80%; | |
height: 200px; | |
} | |
} | |
/* 子组件文字缩放 */ | |
@keyframes change2 { | |
0% {transform: scale(0); | |
} | |
100% {transform: scale(1.5); | |
} | |
} |
阐明
● animation 取值不辨别先后,duration(动画执行工夫)/ delay(动画提早执行工夫)依照呈现的先后顺序解析。
● 必须设置 animation-duration 款式,否则时长为 0 则不会有动画成果。当设置 animation-fill-mode 属性为 forwards 时,组件间接展现最初一帧的款式。
2. transform 款式动画
设置 transform 属性对组件进行旋转、缩放、挪动和歪斜。
设置动态动画
创立一个正方形并旋转 90°变成菱形,并用下方的长方形把菱形下半局部遮蔽造成屋顶,设置长方形 translate 属性值为 (150px,-150px) 确定坐标地位造成门,再应用 position 属性使横纵线追随父组件(正方形)挪动到指定坐标地位,接着设置 scale 属性使父子组件一起变大造成窗户大小,最初应用 skewX 属性使组件歪斜后设置坐标 translate(200px,-710px)失去烟囱。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="top"></div> | |
<div class="content"></div> | |
<div class="door"></div> | |
<!-- 窗户 --> | |
<div class="window"> | |
<div class="horizontal"></div> | |
<div class="vertical"></div> | |
</div> | |
<div class="chimney"></div> | |
</div> |
/* xxx.css */ | |
.container { | |
width:100%; | |
height:100%; | |
background-color:#F1F3F5; | |
align-items: center; | |
flex-direction: column; | |
} | |
.top{ | |
z-index: -1; | |
position: absolute; | |
width: 428px; | |
height: 428px; | |
background-color: #860303; | |
transform: rotate(45deg); | |
margin-top: 284px; | |
margin-left: 148px; | |
} | |
.content{ | |
margin-top: 500px; | |
width: 600px; | |
height: 400px; | |
background-color: white; | |
border: 1px solid black; | |
} | |
.door{ | |
width: 100px; | |
height: 135px; | |
background-color: #1033d9; | |
transform: translate(150px,-137px); | |
} | |
.window{ | |
z-index: 1; | |
position: relative; | |
width: 100px; | |
height: 100px; | |
background-color: white; | |
border: 1px solid black; | |
transform: translate(-150px,-400px) scale(1.5); | |
} | |
/* 窗户的横轴 */ | |
.horizontal{ | |
position: absolute; | |
top: 50%; | |
width: 100px; | |
height: 5px; | |
background-color: black; | |
} | |
/* 窗户的纵轴 */ | |
.vertical{ | |
position: absolute; | |
left: 50%; | |
width: 5px; | |
height: 100px; | |
background-color: black; | |
} | |
.chimney{ | |
z-index: -2; | |
width: 40px; | |
height: 100px; | |
border-radius: 15px; | |
background-color: #9a7404; | |
transform: translate(200px,-710px) skewX(-5deg); | |
} |
设置平移动画
小球降落动画,扭转小球的 Y 轴坐标实现小球着落,在下一段是工夫内减小 Y 轴坐标实现小球回弹,让每次回弹的高度逐次减小直至回弹高度为 0,就模拟出了小球降落的动画。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="circle"></div> | |
<div class="flower"></div> | |
</div> |
/* xxx.css */ | |
.container { | |
width:100%; | |
height:100%; | |
background-color:#F1F3F5; | |
display: flex; | |
justify-content: center; | |
} | |
.circle{ | |
width: 100px; | |
height: 100px; | |
border-radius: 50px; | |
background-color: red; | |
/* forwards 停在动画的最初一帧 */ | |
animation: down 3s fast-out-linear-in forwards; | |
} | |
.flower{ | |
position: fixed; | |
width: 80%; | |
margin-left: 10%; | |
height: 5px; | |
background-color: black; | |
top: 1000px; | |
} | |
@keyframes down { | |
0%{transform: translate(0px,0px); | |
} | |
/* 着落 */ | |
15%{transform: translate(10px,900px); | |
} | |
/* 开始回弹 */ | |
25%{transform: translate(20px,500px); | |
} | |
/* 着落 */ | |
35%{transform: translate(30px,900px); | |
} | |
/* 回弹 */ | |
45%{transform: translate(40px,700px); | |
} | |
55%{transform: translate(50px,900px); | |
} | |
65%{transform: translate(60px,800px); | |
} | |
80%{transform: translate(70px,900px); | |
} | |
90%{transform: translate(80px,850px); | |
} | |
/* 进行 */ | |
100%{transform: translate(90px,900px); | |
} | |
} |
设置旋转动画
设置不同的原点地位(transform-origin)扭转元素所围绕的旋转核心。rotate3d 属性前三个参数值别离为 X 轴、Y 轴、Z 轴的旋转向量,第四个值为旋转角度,旋转向角度可为负值,负值则代表旋转方向为逆时针方向。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="rotate"> | |
<div class="rect rect1"></div> | |
<div class="rect rect2"></div> | |
<div class="rect rect3"></div> | |
</div> | |
<!-- 3d 属性 --> | |
<div class="rotate3d"> | |
<div class="content"> | |
<div class="rect4"></div> | |
<div class="rect5"> </div> | |
</div> | |
<div class="mouse"></div> | |
</div> | |
</div> |
/* xxx.css */ | |
.container { | |
flex-direction: column; | |
background-color:#F1F3F5; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
width: 100%; | |
height: 100%; | |
} | |
.rect { | |
width: 100px; | |
height: 100px; | |
animation: rotate 3s infinite; | |
margin-left: 30px; | |
} | |
.rect1 {background-color: #f76160;} | |
.rect2 { | |
background-color: #60f76f; | |
/* 扭转原点地位 */ | |
transform-origin: 10% 10px; | |
} | |
.rect3 { | |
background-color: #6081f7; | |
/* 扭转原点地位 */ | |
transform-origin: right bottom; | |
} | |
@keyframes rotate { | |
from {transform: rotate(0deg) | |
} | |
to {transform: rotate(360deg); | |
} | |
} | |
/* 3d 示例款式 */ | |
.rotate3d { | |
margin-top: 150px; | |
flex-direction: column; | |
background-color:#F1F3F5; | |
display: flex; | |
align-items: center; | |
width: 80%; | |
height: 600px; | |
border-radius: 300px; | |
border: 1px solid #ec0808; | |
} | |
.content { | |
padding-top: 150px; | |
display: flex; | |
align-items: center; | |
justify-content: center; | |
} | |
/* react4 react5 翻转造成眼睛 */ | |
.rect4 { | |
width: 100px; | |
height: 100px; | |
animation: rotate3d1 1000ms infinite; | |
background-color: darkmagenta; | |
} | |
.rect5 { | |
width: 100px; | |
height: 100px; | |
animation: rotate3d1 1000ms infinite; | |
margin-left: 100px; | |
background-color: darkmagenta; | |
} | |
.mouse { | |
margin-top: 150px; | |
width: 200px; | |
height: 100px; | |
border-radius: 50px; | |
border: 1px solid #e70303; | |
animation: rotate3d2 1000ms infinite; | |
} | |
/* 眼睛的动效 */ | |
@keyframes rotate3d1 { | |
0% {transform:rotate3d(0,0,0,0deg) | |
} | |
50% {transform:rotate3d(20,20,20,360deg); | |
} | |
100% {transform:rotate3d(0,0,0,0deg); | |
} | |
} | |
/* 嘴的动效 */ | |
@keyframes rotate3d2 { | |
0% {transform:rotate3d(0,0,0,0deg) | |
} | |
33% {transform:rotate3d(0,0,10,30deg); | |
} | |
66% {transform:rotate3d(0,0,10,-30deg); | |
} | |
100% {transform:rotate3d(0,0,0,0deg); | |
} | |
} |
阐明
transform-origin 变换对象的原点地位,如果仅设置一个值,另一个值为 50%,若设置两个值第一个值示意 X 轴的地位,第二个值示意 Y 轴的地位。
设置缩放动画
设置 scale 款式属性实现涟漪动画,先应用定位确定元素的地位,确定坐标后创立多个组件实现重合成果,再设置 opacity 属性扭转组件不透明度实现组件暗藏与显示,同时设置 scale 值使组件能够一边放大一边暗藏,最初设置两个组件不同的动画执行工夫,实现扩散的成果。
设置 sacle3d 中 X 轴、Y 轴、Z 轴的缩放参数实现动画。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="circle"> | |
<text>ripple</text> | |
</div> | |
<div class="ripple"></div> | |
<div class="ripple ripple2"></div> | |
<!-- 3d --> | |
<div class="content"> | |
<text>spring</text> | |
</div> | |
</div> |
/* xxx.css */ | |
.container { | |
flex-direction: column; | |
background-color:#F1F3F5; | |
width: 100%; | |
position: relative; | |
} | |
.circle{ | |
margin-top: 400px; | |
margin-left: 40%; | |
width: 100px; | |
height: 100px; | |
border-radius: 50px; | |
background-color: mediumpurple; | |
z-index: 1; position: absolute; | |
} | |
.ripple{ | |
margin-top: 400px; | |
margin-left: 40%; | |
position: absolute; z-index: 0; | |
width: 100px; | |
height: 100px; | |
border-radius: 50px; | |
background-color: blueviolet; | |
animation: ripple 5s infinite; | |
} | |
/* 设置不同的动画工夫 */ | |
.ripple2{animation-duration: 2.5s;} | |
@keyframes ripple{ | |
0%{transform: scale(1); | |
opacity: 0.5; | |
} | |
50%{transform: scale(3); | |
opacity: 0; | |
} | |
100%{transform: scale(1); | |
opacity: 0.5; | |
} | |
} | |
text{ | |
color: white; | |
text-align: center; | |
height: 100%; | |
width: 100%; | |
} | |
.content { | |
margin-top: 700px; | |
margin-left: 33%; | |
width: 200px; | |
height: 100px; | |
animation:rubberBand 1s infinite; | |
background-color: darkmagenta; | |
position: absolute; | |
} | |
@keyframes rubberBand { | |
0% {transform: scale3d(1, 1, 1); | |
} | |
30% {transform: scale3d(1.25, 0.75, 1.1); | |
} | |
40% {transform: scale3d(0.75, 1.25, 1.2); | |
} | |
50% {transform: scale3d(1.15, 0.85, 1.3); | |
} | |
65% {transform: scale3d(.95, 1.05, 1.2); | |
} | |
75% {transform: scale3d(1.05, .95, 1.1); | |
} | |
100%{transform: scale3d(1, 1, 1); | |
} | |
} |
阐明
设置 transform 属性值后,子元素会跟着父元素一起扭转,若只扭转父元素其余属性值时(如:height,width),子元素不会扭转。
设置 matrix 属性
matrix 是一个入参为六个值的矩阵,6 个值别离代表:scaleX, skewY, skewX, scaleY, translateX, translateY。上面示例中设置 了 matrix 属性为 matrix(1,0,0,1,0,200) 使组件挪动和歪斜。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="rect"> </div> | |
</div> |
/* xxx.css */ | |
.container{ | |
background-color:#F1F3F5; | |
display: flex; | |
justify-content: center; | |
width: 100%; | |
height: 100%; | |
} | |
.rect{ | |
width: 100px; | |
height: 100px; | |
background-color: red; | |
animation: down 3s infinite forwards; | |
} | |
@keyframes down{ | |
0%{transform: matrix(1,0,0,1,0,0); | |
} | |
10%{transform: matrix(1,0,0,1,0,200); | |
} | |
60%{transform: matrix(2,1.5,1.5,2,0,700); | |
} | |
100%{transform: matrix(1,0,0,1,0,0); | |
} | |
} |
整合 transform 属性
transform 能够设置多个值并且多个值可同时设置,上面案例中展现同时设置缩放(scale),平移(translate),旋转(rotate)属性时的动画成果。
<!-- xxx.hml --> | |
<div class="container"> | |
<div class="rect1"></div> | |
<div class="rect2"></div> | |
<div class="rect3"></div> | |
<div class="rect4"></div> | |
<div class="rect5"></div> | |
</div> |
/* xxx.css */ | |
.container{ | |
width: 100%; | |
height: 100%; | |
flex-direction:column; | |
background-color:#F1F3F5; | |
padding:50px; | |
} | |
.rect1{ | |
width: 100px; | |
height: 100px; | |
background-color: red; | |
animation: change1 3s infinite forwards; | |
} | |
.rect2{ | |
margin-top: 50px; | |
width: 100px; | |
height: 100px; | |
background-color: darkblue; | |
animation: change2 3s infinite forwards; | |
} | |
.rect3{ | |
margin-top: 50px; | |
width: 100px; | |
height: 100px; | |
background-color: darkblue; | |
animation: change3 3s infinite; | |
} | |
.rect4{ | |
align-self: center; | |
margin-left: 50px; | |
margin-top: 200px; | |
width: 100px; | |
height: 100px; | |
background-color: darkmagenta; | |
animation: change4 3s infinite; | |
} | |
.rect5{ | |
margin-top: 300px; | |
width: 100px; | |
height: 100px; | |
background-color: cadetblue; | |
animation: change5 3s infinite; | |
} | |
/* change1 change2 比照 */ | |
@keyframes change1{ | |
0%{transform: translate(0,0); transform: rotate(0deg) | |
} | |
100%{transform: translate(0,500px); | |
transform: rotate(360deg) | |
} | |
} | |
/* change2 change3 比照属性程序不同的动画成果 */ | |
@keyframes change2{ | |
0%{transform:translate(0,0) rotate(0deg) ; | |
} | |
100%{transform: translate(300px,0) rotate(360deg); | |
} | |
} | |
@keyframes change3{ | |
0%{transform:rotate(0deg) translate(0,0); | |
} | |
100%{transform:rotate(360deg) translate(300px,0); | |
} | |
} | |
/* 属性值不对应的状况 */ | |
@keyframes change4{ | |
0%{transform: scale(0.5); | |
} | |
100%{transform:scale(2) rotate(45deg); | |
} | |
} | |
/* 多属性的写法 */ | |
@keyframes change5{ | |
0%{transform:scale(0) translate(0,0) rotate(0); | |
} | |
100%{transform: scale(1.5) rotate(360deg) translate(200px,0); | |
} | |
} |
阐明
● 当设置多个 transform 时,后续的 transform 值会把后面的笼罩掉。若想同时应用多个动画款式可用复合写法,例:transform: scale(1) rotate(0) translate(0,0)。
● transform 进行复合写法时,变动款式内多个款式值程序的不同会出现不一样的动画成果。
● transform 属性设置的款式值要一一对应,若前后不对应,则该动画不失效。若设置多个款式值则只会呈现出已对应值的动画成果。