图解 CSS - 梳理与巩固
2020-04-22· 20min
#CSS
#计量单位
- 相对长度单位:vw、vh、rem、em、%、...
- vw、vh相对浏览器的可视区域
- rem相对根节点html的字体大小
- em相对父节点字体的大小
- 绝对长度单位:px、pt、...
- px精确像素
- 扩展
- 物理像素:设备像素(DP,DevicePixels)代表屏幕上有多少个点
- 逻辑像素:设备独立像素(DIP,DeviceIndependentPixels)如 CSS 中的单位 px
- 设备像素比:DPR (DevicePixelRatio),公式:设备像素 / 设备独立像素
- 像素密度:PPI (PixelsPerInch) 表示每英寸的像素个数
- 打印分辨率:DPI (DotsPerInch) 表示每英寸的点数
- 屏幕分辨率:屏幕显示的像素点数,如1080 * 1920
- 图像分辨率:每英寸图像内所拥有的像素点数,如 320 * 640
#盒模型
- 盒模型:由 content、border、margin、paddding 四个部分组成
- W3C 标准盒模型 (content-box),width/height 只包含 content
- IE 盒模型 (border-box),width/height 包含 content、border、padding
- 可通过 box-sizing 改变元素的盒模型:border-box、content-box
- 声明 <!DOCTYPE html>
- 可以让 IE6 及其以上的版本遵循标准兼容模式的方式工作
- 所有的浏览器都会把盒模型解释为标准盒模型
#BFC
- 块级格式化上下文(Block Formatting Context),规定了处于 BFC 内部的块级元素如何布局
- 特性
- BFC 内的子元素不会影响外部元素,反之同
- 当计算其区域的高度时,浮动元素也可以参与计算
- BFC 内的子元素的 margin-top 不会和 BFC 这个父容器发生重叠
- 启用BFC
- float:left|right
- position:absoulte|fixed
- display:flex|grid|table|inline-block|table-cell|flow-root|...
- flow-root:元素块状化,同时包含BCF
- overflow:auto|scroll|hidden
- 根元素(html)、包含body的元素
- 作用
- 防止外边距重叠
- 相邻元素
- 父子元素
- 相邻元素
- 解决高度塌陷
- 父元素
- 父元素
- 清除浮动
- 相邻元素
- 相邻元素
- 防止外边距重叠
- 扩展
- IFC(行级格式化上下文)
- GFC(网格布局格式化上下文)display: grid
- FFC(自适应格式化上下文)display: flex、display: inline-flex
#伪类和伪元素
- 伪类:以冒号 :开头,用于选择处于特定状态的元素。如::hover、:active
- 伪元素:以双冒号 ::开头,用于在文档中插入虚构的元素(并不存在于 DOM 之中)。如:::before、::after
#选择器
- 优先级:!important > 内联样式 > id选择器 > 类选择器、伪类选择器、属性选择器 > 标签选择器、伪元素选择器 > 通配符选择器
- id选择器、类选择器、标签选择器
- 后代选择器(div span):选择 div 里所有 span 元素
- 子选择器(ul > li):选择 ul 直接子元素,如
# Yes <ul> <li></li> </ul> # No <ul> <div><li></li></div> </ul> - 兄弟选择器(h1 ~ div):选择和 h1 元素有相同父元素的所有 div 兄弟元素(在 h1 之后出现的兄弟)
# Yes <h1></h1> <div></div> <div></div> # No <h1></h1> <span></span> <div></div> - 相邻兄弟选择器(h1 + div):选择和 h1 元素相邻的下一个兄弟元素 div
# 仅选择第一个 div <h1></h1> <div></div> <div></div> - 奇数行/偶数行
/* 奇数行 */ div:nth-child(odd) { } /* 偶数行 */ div:nth-child(even) { }
#浮动
- 特性:脱离文档流、变成行内块级元素、浮动元素碰到父元素/浮动元素边就停止
- 场景:文字环绕、灵活布局
- 影响:
- 浮动元素会盖在非浮动兄弟元素之上。(Playground)
- 父元素没有设置高度的话,浮动元素不会撑开父元素的高度(Playground)
- 浮动元素会盖在非浮动兄弟元素之上。(Playground)
- 清除浮动
- CSS属性 clear清除浮动
- 父元素设置高度
- 父元素创建 BFC(如:overflow:hidden、display: flow-root)
- 在父元素内部最后添加一个没有高度的元素,并使用 clear:both
- 父元素添加伪元素 ::after
.parent-box::after { content: ""; display: block; clear: both; }
- CSS属性
#重绘与重排
- 重绘(Repaint)
- 定义:当页面中的元素样式发生改变时,浏览器会重新绘制这些元素的外观,但不会改变它们在页面中的位置和大小。(详见MDN)
- 触发:改变元素的 color、border-style、background...
- 重排(Reflow)
- 定义:当页面中的元素发生布局或几何属性发生变化时,浏览器需要重新计算这些元素的位置和大小,然后重新构建页面的渲染树。(详见MDN)
- 触发:改变元素位置/尺寸/内容/字体大小、改变浏览器窗口尺寸、页面初始渲染、添加/删除可见的 DOM 元素...
- 优化建议:
- 减少重排范围
- 尽可能局部布局
- 避免使用 table 布局(另:table-layout:auto、table-layout:fixed 可减少影响范围)
- 减少重排次数
- 使用 className 修改 DOM 样式(避免一条条地修改)
- 动画元素采用 absolute、fixd 布局,避免影响到其它元素
- 分离 DOM 的读写操作
/* 两次重排 + 重绘 */ div.style.left = div.offsetLeft * 2 div.style.right = div.offsetRight * 2 /* 一次重排 + 重绘 */ const left = div.offsetLeft const right = div.offsetLeft div.style.left = left * 2 div.style.right = right * 2 /* 以下操作,浏览器会强制刷新渲染队列 */ getComputedStyle、offsetXXX、scrollXXX、clientXXX
- 减少重排范围
#布局
#响应式布局(RWD,Responsive Web Design)
- 特点:当屏幕尺寸变化时,布局方式等呈现效果会发生改变(一套代码)
- 设计方法:媒体查询 + 弹式布局(Flexbox Layout)、网格布局(Grid Layout)或 rem、vh、vw 等
- 注意:移动端的浏览器默认 viewport(layout viewport)为 980px/1024px/...
- 布局视口(layout viewport)
- 不同厂商出厂不一致
- document.documentElement.clientWidth/Height(不包含滚动条)
- 可视视口(visual viewport)
- 默认是屏幕的宽度
- window.innerWidth/Height(包含滚动条)
- 理想视口(ideal viewport)
- screen.width/height
- 布局视口(layout viewport)
- meta 标签解析
- name="viewport"仅对移动设备作用
- width=device-width布局视口(layout viewport)= 理想视口(ideal viewport)
- initial-scale=1.0页面的初始缩放值
- maximum-scale=1.0用户最大缩放值
- user-scalable=0不允许用户缩放
<!-- 建议:允许缩放 --> <meta name="viewport" content="width=device-width,initial-scale=1.0" /> <!-- 不建议 --> <meta name="viewport" content="width=device-width,initial-scale=1.0, maximum-scale=1.0, user-scalable=0" />
#自适应布局(AWD,Adaptive Web Design)
- 特点:根据不同设备/尺寸,提供不同版本的网站(多套代码)
- 设计方法:通过检测设备特性(如 UA),提供多个布局
#弹式布局(Flexbox Layout)
- 父级容器
- flex-direction: rowrow-reverse|column|column-reverse 元素排列方向
- flex-wrap: nowrapwrap|wrap-reverse 元素是否换行
- flex-flow<flex-direction> || <flex-wrap>的简写,默认 flex-flow: row nowrap;
- justify-content: flex-startflex-end|center|space-between|space-around 元素在主轴上的对齐方式
- align-items: stretchflex-start|flex-end|center|baseline 元素在交叉轴上的对齐方式
- align-content: stretchflex-start|flex-end|center|baseline 多根轴线的对齐方式
- 子级容器
- order: 0元素排列顺序,值越小越靠前
- flex-grow: 0元素放大比例(默认为 0,即如果存在剩余空间,也不放大)
- flex-shrink: 1元素缩小比例(默认为 1,即如果空间不足,元素将缩小)
- flex-basis: auto在分配多余空间之前,项目占据的主轴空间(默认值为 auto,即元素的本来大小)
- align-self: auto可覆盖 align-items 属性。默认 auto,继承父元素的 align-items 属性,如果没有父元素,则等同于stretch
- flex: 0 1 auto
- flex-grow: 0; 元素不会放大(在 flex 容器中,不会占据剩余的空间),默认为 0
- flex-shrink: 1; 元素会缩小(空间不足,元素将缩小)),默认为 1
- flex-basis: auto; 元素的初始大小将基于其内容或定义的宽度/高度,默认为 0
- flex: 1
- 1 1 0
#网格布局(Grid Layout)
- 关键字
- auto: 自适应
- fr: fraction 的缩写,片段,百分比属性
- grid-template-columnsgrid 布局的每一列 列宽
- grid-template-rowsgrid 布局的每一行 行高
/* 两行两列,每列列宽 60px,每行行高 60px */
.grid-container {
display: grid;
grid-template-columns: 60px 60px; /* repeat(2, 60px) */
grid-template-rows: 60px 60px;
}
- grid-row-gap行间距
- grid-column-gap列间距
- grid-gap行间距和列间距 的简写形式,如:grid-gap: <grid-row-gap> <grid-column-gap>;
/* 九宫格 */ .grid-container { display: grid; grid-template-columns: repeat(3, 60px); grid-template-rows: repeat(3, 60px); grid-gap: 10px 20px; }
#布局案例
#圣杯/三栏布局
<style>
body,
.content {
display: flex;
flex-direction: column;
}
.aside-left {
order: -1;
}
@media (min-width: 768px) {
.content {
flex-direction: row;
flex: 1;
}
main {
flex: 1;
}
.aside-left,
.aside-right {
flex: 0 0 12em;
}
}
</style>
<body>
<header>Header</header>
<div class="content">
<main>Main</main>
<aside class="aside-left">side-left</aside>
<aside class="aside-right">side-right</aside>
</div>
<footer>Footer</footer>
</body>
#粘性页脚
<style>
html,
body {
height: 100%;
/* reset def css */
margin: 0;
}
.def-layout {
height: fit-content;
min-height: 100%;
display: flex;
flex-direction: column;
}
.slot-wrap {
width: 100%;
flex: 1 0 auto;
}
footer {
width: 100%;
flex: 0 0 auto;
}
</>
<body>
<div class="def-layout">
<header>Header</header>
<div class="slot-wrap">
<main>Main</main>
</div>
<footer>Footer</footer>
</div>
</body>
#自适应 & 换行
<style>
.grid-container {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
margin: -0.5rem;
}
.grid-item {
height: 100px;
background: green;
margin: 0.5rem;
color: white;
}
.flex-container {
display: flex;
flex-wrap: wrap;
gap: 1rem;
}
.flex-item {
flex: 1 0 150px;
height: 100px;
background: purple;
color: white;
}
</style>
<h2>grid</h2>
<div class="grid-container">
<div class="grid-item">1</div>
<div class="grid-item">2</div>
<div class="grid-item">3</div>
<div class="grid-item">4</div>
<div class="grid-item">5</div>
</div>
<h2>flex</h2>
<div class="flex-container">
<div class="flex-item">1</div>
<div class="flex-item">2</div>
<div class="flex-item">3</div>
<div class="flex-item">4</div>
<div class="flex-item">5</div>
</div>
#场景案例
#元素水平垂直居中
- 不知道元素宽高大小仍能实现水平垂直居中
- flex + align-items、justify-content
- grid + align-items、justify-content
<style> .parent { display: flex; justify-content: center; align-items: center; /* width: 200px; height: 200px; */ } .child { /* width: 100px; height: 100px; */ } </style> <div class="parent"> <div class="child"></div> </div>- position + transform
<style> .parent { /* width: 200px; height: 200px; */ position: relative; } .son { /* width: 100px; height: 100px; */ position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } </style> <div class="parent"> <div class="child"></div> </div>- position + margin:auto
#字体小于 12px
- transform:scale()
<style>
.text-1 {
display: inline-block;
font-size: 12px;
transform: scale(0.8);
/*设置缩放中心*/
transform-origin: 0 0;
/* 视情况补上缩小的宽度 (1-0.8)+1 */
/* width: 120%; */
}
.text-2 {
display: inline-block;
font-size: 12px;
}
</style>
<span class="text-1">9.6px</span> <span class="text-2">12px</span>
#画一个 0.5px 的线
transform: scaleY(0.5);
#画一个三角形、梯形...
<style>
.clippath-triangle {
width: 100px;
height: 100px;
background: orange;
clip-path: polygon(0px 0px, 100px 0px, 50px 50px);
}
.border-triangle {
width: 0px;
height: 0px;
border: 50px solid;
border-color: olivedrab transparent transparent transparent;
}
.border-trapezoid {
width: 50px;
height: 50px;
border: 50px solid;
border-color: olivedrab transparent transparent transparent;
}
.border-parallelogram {
width: 100px;
height: 100px;
background: skyblue;
transform: skew(30deg);
}
</style>
<div class="clippath-triangle"></div>
<div class="border-triangle"></div>
<div class="border-trapezoid"></div>
<div class="border-parallelogram"></div>
#CSS工程化
#目的
- 优化CSS代码的组织、拆分、模块化等设计、提高构建速度、解决各浏览器兼容性问题等
#实践
- 预处理器:Less、Sass、Stylus,用以预编译 Sass、Less。
- 后处理器:PostCSS,为 CSS 属性添加私有前缀,解决兼容性问题
- CSS Modules:
- 局部作用域和模块依赖,使组件样式隔离
- 构建工具:css-loader 等
- CSS-in-JS
- 原子化CSS:一种 CSS 架构,对 class 极致的封装,最大程度提高复用性
- 命名规范:BEM,块(block)、元素(element)、修饰符(modifier),由 Yandex 团队提出的一种命名方法论
<div class="main"> <h2 class="main__title">Title</h2> <div class="main__links"> <a href="/" class="main__links--active">Active</a> </div> </div>