实现精美页面是前端工程师的核心能力之一,CSS布局技术是实现精美页面的核心技术,但CSS布局好入门,难精通。随着用户审美标准越来越高,前端页面对精美度、实用性要求越来越高,深度掌握CSS布局,可更快提升竞争力。
flex
Flex 是 Flexible Box 的缩写,意为“弹性布局”或者“弹性盒子”,是 CSS3 中的一种新的布局模式,可以简便、完整、响应式地实现各种页面布局,当页面需要适应不同的屏幕大小以及设备类型时非常适用。目前,几乎所有的浏览器都支持 Flex 布局。flex布局也经常被称之为flexbox,使用flex布局之后,它会给子元素提供强大空间分配和对齐能力。采用 Flex 布局的元素,称为 Flex 容器(flex container),简称“容器”。它的所有子元素自动成为容器成员,称为 Flex 项目(flex item),简称“项目”。容器默认存在两根轴,分别为水平的主轴(main axis)和垂直的交叉轴(cross axis)。主轴的开始位置叫做 main start,结束位置叫做 main end;交叉轴的开始位置叫做 cross start,结束位置叫做 cross end。项目默认沿主轴排列。单个项目占据的主轴空间叫做 main size,占据的交叉轴空间叫做 cross size。如下图所示:
CSS 中提供了一些固定属性来实现 Flex 布局,按照作用范围的不同,可以分为两类:容器属性与项目属性
如下图所示:
渐变gradient
CSS3中的Gradient有两种,分别是线性渐变(linear-gradient)和径向渐变(radial-gradient)
效果如下图:
兼容性写法:
.demo{
background:red; /* 一些不支持背景渐变的浏览器 */
background:-moz-linear-gradient(top, red, rgba(0, 0, 255, 0.5));
background:-webkit-gradient(linear, 0 0, 0 bottom, from(#ff0000), to(rgba(0, 0, 255, 0.5)));
background:-o-linear-gradient(top, red, rgba(0, 0, 255, 0.5));
}
实际开发中通常结合PostCSS的Autoprefixer自动实现以上兼容性写法。
GPU加速
css3硬件加速又叫做GPU加速,是利用GPU进行渲染,减少CPU操作的一种优化方案。浏览器首先将页面解析成DOM树,DOM树和CSS让浏览器构建渲染树,渲染树中的每个渲染对象会被分配到一个图层中,每个图层会被更新到GPU中,由于GPU中的transform等CSS属性不触发repaint,因此不需要重绘,单独处理,所以能大大提高网页的性能。当浏览器引擎检测到页面中某个MOD元素应用了某些CSS规则时候就会开启,最显著的特征的元素是3D变换。
开启硬件加速:
- transform
- opacity
- ilter
强行开始加速:
- transform:translate3d(0,0,0);
注意问题
- 过多的使用GPU处理会导致内存问题,可能导致浏览器崩溃,比如一些古董电脑。
- 在GPU渲染字体会导致抗锯齿无效,因为GPU和CPU的算法不同,因此即使最终硬件加速停止了,文本还是会在动画期间显示的很模糊,所以尽量不要包含文字。
高级选择器
在 CSS 中,可以根据选择器的类型,把选择器分为基础选择器和高级选择器(又称为复合选择器),高级选择器是建立在基础选择器之上,对基本选择器进行组合形成的。高级选择器是由两个或多个基础选择器,通过不同的方式组合而成,高级选择器可以更准确、更高效的选择目标元素,常用的高级选择器包括层次选择器、属性选择器、伪类选择器等等。
CSS3高级选择器示例:
- E:first-of-type
- E:last-of-type
- E:only-of-type
<style>
.main div:first-of-type{
color:red;
}
.main div:last-of-type{
color:sienna
}
.main h2:only-of-type{
color:green;
}
.main p:nth-of-type(1){
color:violet;
}
</style>
<div class="main">
<h1>Title 1</h1>
<h2>Title 2</h2>
<div>Div 1</div>
<div>Div 2</div>
<div>Div 3</div>
<div>Div 4</div>
<div>Div 5</div>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</div>
效果如下图:
网站外链统一添加Icon
a[href*="baidu"] {
color: #df7009;
background-image:url(assets/imgs/icon/link.png);
background-repeat: no-repeat;
background-size: 22% 50%;
background-position: 3px 8px;
padding-left: 17px;
}
效果如下图:
CSS选择器这块就到这里,UI层面的开发仍然是需要熟能生巧的基本功练习。
rem em px
几个知识点需要记牢:
- px是固定的像素,一旦设置了就无法因为适应页面大小而改变
- em相对于父元素,一般都是以的“font-size”为基准
- 任何浏览器默认字体大小都是16px,所有未经调整的浏览器都符合1em=16px
- rem相对于根元素,通常做法是给html元素设置一个字体大小,然后其它元素的长度单位就为rem。
vw vh %
- vw: 视窗宽度的百分比(1vw 代表视窗的宽度为 1%)
- vh: 视窗高度的百分比( 1vh 代表视窗的高度为 1%)
- vmin:当前 vw 和 vh 中较小的一个值
- vmax:当前 vw 和 vh 中较大的一个值
- %:相对于父元素的大小设定比率
混合模式
在CSS中,有两个属性负责混合。
- mix-blend-mode:用于混合DOM元素
- background-blend-mode:用于组合多个CSS背景
mix-blend-mode
<style>
.container {
width: 800px;
height: 400px;
border: 1px solid #ccc;
margin-bottom: 20px;
text-align: center;
}
.container .circle {
width: 200px;
height: 200px;
border-radius: 50%;
background-color: cadetblue;
margin: 100px auto;
}
.container p {
font-size: 32px;
font-weight: bold;
mix-blend-mode: overlay;
margin-top: -140px;
color: #38a904;
}
</style>
<div class="container">
<div class="circle"></div>
<p>Dom Blend</p>
</div>
background-blend-mode
准备的素材:
<style>
.main {
position: relative;
width: 800px;
height: 400px;
text-align: center;
background-image: url('./assets/lines.png'),
url('./assets/waterline.png'),
url('./assets/wavepage.png'),
url('./assets/demo.jpg');
background-color: rgb(48, 98, 164);
background-size: cover, 160px, cover, cover;
background-repeat: no-repeat, repeat, no-repeat, no-repeat;
background-position: center center;
background-blend-mode: soft-light;
}
.main>h1 {
display: block;
height: 100px;
width: 100%;
position: absolute;
top: 200px;
left: 0;
font-size: 38px;
font-weight: 600;
line-height: 100px;
background-color: rgb(34, 112, 196);
color: #199e65;
border: 0.1em solid #ccc;
border-width: 0.1em 0;
mix-blend-mode: hard-light;
}
</style>
<!-- CSS混合 -->
<div class="main">
<h1>CSS Blend</h1>
</div>
<!-- 原图效果,用于对比 -->
<img src="./assets/demo.jpg" width="800" />
效果对比如下图:
CSS支持的15种混合模式如下:
效果分类 | 混合模式 | 描述信息 |
---|---|---|
变暗 | multiply | 前景色越亮背景色显示越多 |
darken | 选择颜色较暗的展示 | |
color-burn | 增加对比度,提高背景色暗度 | |
变亮 | screen | 前景色越暗背景色显示越多 |
lighten | 选择颜色较亮的展示 | |
color-dodge | 减少对比度,提高背景色亮度 | |
对比 | overlay | 暗色使用multiply,亮色使用screen |
hard-light | 大幅度增加对比度 | |
soft-light | 小服务增加对比度,效果柔和 | |
复合 | hue | 将上层的色相混合到下层颜色 |
saturation | 将上层的饱和度混合到下层颜色 | |
luminosity | 将上层的亮度混合到颜色上 | |
color | 将上层的色相与饱和度混合到下城颜色上 | |
比较 | difference | 从亮色中剔除暗色 |
exclusion | 从亮色中剔除暗色,对比度稍弱 |
link 与 @import
CSS外部引用方式有两种:link、@import
现代Web布局
CSS预处理器
CSS预处理器用一种专门的编程语言,进行Web页面样式设计,然后再编译成正常的CSS文件,以供项目使用。CSS预处理器为CSS增加一些编程的特性,无需考虑浏览器的兼容性问题。 比如说:Sass、Less、Stylus、Turbine、Swithch CSS、CSS Cacheer、DT CSS等都属于css预处理器,其中比较优秀的: Sass、LESS,Stylus。
Sass
全称:Syntactically Awesome Stylesheets,可译为“语法上很棒的样式表”,基于Ruby环境运行。
Sass编译器有三种dart-sass、node-sass、ruby-sass。推荐使用dart-sass。
输出方式有四种,默认为nested
nested:嵌套缩进的css代码
expanded:展开的多行css代码
compact:简洁格式的css代码
compressed:压缩后的css代码
- 为什么很多地方常见Scss?
最初的Sass语法是不兼容CSS的,所以为了提高对CSS/CSS3的支持,在Sass 3钟引入了新的语法,在继承了原有Sass强大的功能之上还很好的兼容了CSS3,使得原有的CSS代码直接放到Scss文件中可以完美运行,其与CSS的关系很像TypeScript与JavaScript。Sass版本3.0之前的后缀名为.sass,版本3.0之后的后缀名.scss。
Less
全称:Leaner Style Sheets ,可译为精简版样式表。其第一个版本与Sass相同由Ruby语言开发,后来的版本中改为了JavaScript。
Sass有的Less都有,Sass没有的Less也有。
Less 借助less.js可以直接在客户端上运行,借助 Node.js还可在服务端运行 。
Stylus
Stylus的语法比上面两种花样多一些,相对自由。Stylus产自于node社区,自然也是基于node环境运行。
Postcss
以上的Sass/Scss、Less、Stylus都是可以称作CSS预处理器,一种基于CSS之上的高级语言。Postcss则与他们是完全不同的性质,官网介绍自己为:“是一个用 JavaScript 工具和插件转换 CSS 代码的工具”,我们可以将Postcss视作一个平台,这个平台上允许运行各类插件。一方面名字的原因容易与CSS预处理器们混淆,另一方面Postcss可以做到类似CSS预处理的事情而经常与它们放在一起讨论。
PostCSS 的主要功能只有两个:第一是把 CSS 解析成 AST,第二是运行插件来处理 AST 。PostCSS 一般与已有的构建工具进行集成,比如Webpack。同时再Postcss平台上我们也可以开发一些插件。
CSS模块化方案
CSS命名方案
由于传统 CSS 没有作用域的概念,不同组件中的 CSS 样式会全局生效,因此开发过程中有极大可能会遇到样式被覆盖的问题。为保证样式互不影响,出现了统一的 CSS 命名规范及命名方案。
BEM
BEM 是 Yandex 公司提出的一套CSS 样式命名规范,BEM 分别指代 Block(块)、Element(元素)、Modifier(修饰符),BEM 规定 CSS 样式名称由这三部分内容组成。
BEM 规范有以下几种组合方式:
- .Block {} .
- Block__Element {} .
- Block--Modifier {} .
- Block__Element--Modifier {}
(Block 和 Element 之间用双下划线__相连接,Block 或 Element 与 Modifier 之间用双中划线--连接)
示例:
<div class="layout"> <!-- B:layout -->
<div class="layout__header"> <!-- E:header -->
<div class="layout__menu"> <!-- E:menu -->
<div class="menu__item">首页</div>
<!-- M:active -->
<div class="menu__item menu__item--active">关于</div>
</div>
</div>
</div>
BEM规范中最长类名:Block__Element--Modifier,即:menu__item--active,在多层嵌套情况也要注意命名规范,避免出现“layout__header_menu_item--active”这类情况。BEM 中不需要考虑结构的深度,Block 子元素的 BEM 类名仅包含 Block 名称和当前Element 的名称。
OOCSS
在CSS模块化规范里出现了一种新的编程思想,借鉴面向对象(OOP)的形式,出现了OOCSS。其中面向的“对象”就是指HTML元素或与其关联的内容,通常理解泛指HTML元素。OOCSS官网地址
在OOCSS中有两个原则:1、结构样式分析。2、容器内容分离。
1、结构样式分析。比如在页面定义两个大小完全相同、主题风格不同的卡片。实例代码如下:
<style>
.card {
width: 200px;
height: 200px;
padding: 6px;
background-color: #ccc;
color: #ccc;
font-weight: 600;
text-align: center;
}
.card-normal {
background-color: #565496;
color: chartreuse;
}
.card-highlight {
background-color: #fff;
color: #000;
box-shadow: 0 0 10px rgb(137, 145, 149);
}
</style>
<!-- 定义两个风格略有差别的卡片 -->
<div class="card card-normal">
<h1>Normal Card Content</h1>
</div>
<br /><br />
<div class="card card-highlight">
<h1>Hightlight Card Content</h1>
</div>
2、容器内容分离。
OOCSS这一点推荐将 .card h1{}
定义为 .card-text{}
这一点其实不强制,因为我们还是要灵活运用CSS选择器的便利。
ITCSS
在众多CSS规范里,它可能是存在感很低的了,相信很多开发者至今都不知道这世上还有它的存在,这个现象也和它的作者个性有点关系。ITCSS在之前很长一段时间里都是没有官网和文档的,一开始就走了个小众路线,倘若在哪个社区了遇到了一个同样有ITCSS困扰的人,怕是真的很有缘分了。后来有了官网 itcss.io/,其风格依旧是一副无所吊谓的样式,如下图我们近距离感受下。
只有背景是定时变化的,其它就都没了,唯一一个链接指向了作者的Twitter,推上也貌似停更很久了。不过综合了网上各处的信息显示:作者Harry Roberts很厉害,ITCSS框架也很不错,但是不建议国内开发者使用,感兴趣的可以了解其背后的编程思想。
ITCSS架构将CSS纵向氛围七层
- settings:存放一些自定义变量。
- tools: Mixins和函数。
- generic:标准化样式,如 normalize.css或reset.css。
- base:定义标准HTML元素样式。
- objects:定义页面结构类。
- components:组件类定义。
- trumps:权重最高的样式文件,可覆盖上六层的内容。
项目结构通常如下,划分不同的CSS不同职责,实践中伴随SCSS/LESS使用。
SMACSS
全称:Scalable and Modular Architecture for CSS,可译为:针对CSS的可扩展和模块化架构
官网地址:smacss.com/
SMACSS架构中将CSS分为五类
- Base:标准化样式,如 normalize.css或reset.css。
- layout:涉及布局的 CSS,只负责布局。
- module:模块化、可重用的 CSS 规则定义。
- state:定义元素、模块状态。
- theme:主题风格文件。
SUITCSS
全程:Style tools for UI components,可译为:专为UI组件提供的样式工具。
官网地址:suitcss.github.io/
在SUITCSS中将CSS类名分为两类:工具类和组件类
Atomic CSS
Atomic CSS——原子化CSS,不同于以上命名方案,它指的是一种新架构方式,它倾向于小巧且用途单一的 class,并且会以视觉效果进行命名。目前市面上有不少原子化CSS框架:TailWind CSS、Windi CSS、UnoCSS、Tachyons。
CSS Modules
在前端逐渐自动化的进程中,CSS也逐渐向模块化方向发展,CSS Modules 允许我们像 import 一个 JS Module 一样去 import 一个 CSS Module。每一个 CSS 文件都是一个独立的模块,每一个类名都是该模块所导出对象的一个属性。通过这种方式,便可在使用时明确指定所引用的 CSS 样式。并且,CSS Modules 在打包时会自动将 id 和 class 混淆成全局唯一的 hash 值,从而避免发生命名冲突问题。
CSS Module 的官方定义就是如下所示。
A CSS Module is a CSS file in which all class names and animation names are scoped locally by default. 译:一个CSS模块是一个一个CSS文件,默认情况下,所有类名和动画名都是本地作用域。
CSS Module存在以下几个特性:
- 作用域:模块中的名称默认都属于本地作用域,定义在 :local 中的名称也属于本地作用域,定义在 :global 中的名称属于全局作用域,全局名称不会被编译成哈希字符串。
- 命名:对于本地类名称,CSS Modules 建议使用 camelCase 方式来命名,这样会使 JS 文件更干净,即 styles.className。也可以使用 styles['class-name'],允许但不提倡。
- 组合:使用 composes 属性来继承另一个选择器的样式,这与 Sass 的 @extend 规则类似。
- 变量:使用 @value 来定义变量,不过需要安装 PostCSS 和 postcss-modules-values 插件。
CSS-in-JS
CSS-in-JS是一种样式化技术,简单点说就是可以通过JavaScript写CSS,并可以将JavaScript解析成CSS。书面一点就是CSS-in-JS 是用现有的标准用 JavaScript 去控制、扩展和实时联动 CSS 的一套方案。CSS-in-JS 将 CSS 模型抽象到组件级别,而不是文档级别,这一点与上面所说的CSS模块化有较大差别。
styled-components
styled-components 是目前最流行最好用的 CSS-in-JS 库,已在 React 中被广泛使用。
使用方式如下图:
// 标题样式
export const Title = styled.h1`
font-size: 20px;
font-weight:800;
color:#000;
text-align: center;
`
// 调用
export default function App() {
return (
<Wrapper>
<Title>Hello World!</Title>
</Wrapper>
)
}
CSS-in-JS其它实现方案还有:JSS、Emotion、Glamorous、Radium等,感兴趣的都可以深入研究下。
CSS-in-JS有好处也有坏处,我们一定要根据自己的实际情况进行衡量和取舍来确定是不是要在自己的项目中使用它,永远不要为了使用一个技术而用一个技术,编程路漫漫,上下求索。