# CSS
# 1 两种隐藏元素方式 display: none;
与 visibility: hidden;
的区别
display: none;
会让元素完全从渲染树中消失,渲染的时候不占据任何空间;visibility: hidden;
不会让元素从渲染树消失,渲染树元素继续占据空间,只是内容不可见。display:none;
是非继承属性,子孙节点消失由于元素从渲染树消失造成,通过修改子孙节点属性无法显示;visibility: hidden;
是继承属性,子孙节点消失由于继承来hidden,通过设置visibility: visible;
可以让子孙节点显式。- 修改常规流中元素的
display
通常会造成文档重排。修改visibility
属性只会造成本元素的重绘。 - 读屏器不会读取
display: none;
元素内容;会读取visibility: hidden;
元素内容。
# 2 盒模型
页面渲染时, dom
元素所采用的布局模型。可通过 box-sizing
进行设置。根据计算宽高的区域可分为
content-box
(W3C标准盒模型)border-box
(IE盒模型)padding-box
margin-box
(浏览器未实现)
# 3 BFC
块级格式化上下文,是一个独立的渲染区域,让处于 BFC
内部的元素与外部的元素相互隔离, 使内外元素的定位不会相互影响。
触发条件
- 根元素
- position: absolute / fixed
- display: inline-block / table
- float 元素
- overflow !== visible
规则:
- 属于同一个
BFC
的两个相邻Box
垂直排列 - 属于同一个
BFC
的两个相邻Box
的margin
会发生重叠 BFC
中子元素的margin box
的左边,与包含块(BFC)border box
的左边相接触(子元素absolute
除外)BFC
的区域不会与float
的元素区域重叠- 计算
BFC
的高度时,浮动子元素也参与计算 - 文字层不会被浮动层覆盖,环绕于周围
应用:
- 阻止
margin
重叠 - 可以包含浮动元素 ———— 清除内部浮动(清楚浮动的原理是两个
div
都位于同一个BFC
区域之中) - 自适应两栏布局
- 可以阻止元素被浮动元素覆盖
# 4 居中布局
局中布局
- 行内元素:text-align:center;
- 块级元素:margin: 0 auto;
- absolute + transform;
- flex + justify-content: center;
垂直布局
- line-height: height;
- absolute + transform;
- flex + align-items: center;
- table;
水平垂直居中
- absolute + transform;
- flex + justify-centent + align-items;
# 5 选择器以及优先级
- 1.id选择器(#fq)
- 2.类选择器(.fq)
- 3.标签选择器(div, p, h1 ...)
- 4.相邻选择器(h1 + p)
- 5.子选择器(ul > li)
- 6.后代选择器(li a)
- 7.通配符选择器(*)
- 8.属性选择器(a[rel = "external"])
- 9.伪类选择器(a:hover,li:nth-child)
!important > 行内样式 > #id > .class > tag > * > 继承 > 默认
选择器
从右往左
解析,可参考 blog.csdn.net/SJ1551/article/details/109765993
# 6 弹性盒子中 flex: 0 1 auto 分别表示什么
三个参数分别对应的是 flex-grow
, flex-shrink
和 flex-basis
, 默认值为 0 1 auto
。
flex-grow
属性定义项目的放大比例,默认为0, 即如果存在剩余空间,也不放大。flex-shrink
属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小。flex-basis
属性定义了在分配多余空间之前,该项目占据的主轴空间(main size)。
# 7 link 与 @import 的区别
link
功能较多,可以定义RSS
, 定义Rel
等作用, 而@import
只能用于加载css
- 当解析到
link
时,页面会同步
加载所引起的css
, 而@import
所引用的css
会等到页面加载完才会被加载,相当于异步
。 @import
需要IE5以上才能使用link
可以使用js
动态引入,@import
不行
# 8 伪类和伪元素
css
引入伪类和伪元素概念是为了格式化文档树以外的信息。也就是说,伪类和伪元素都是用来修饰不在文档树中的部分。
伪类 伪类存在的意义是为了通过选择器找到那些不存在DOM树中的信息以及不能被常规CSS选择获取到的信息。
- 获取不存在与DOM树中的信息。比如
a
标签的:link
、:visited
等, 这些信息不存在与 DOM 树结构中, 只能通过 CSS 选择器来获取。 - 获取不能被常规 CSS 选择器获取的信息。 比如: 要获取第一个子元素,我们无法用常规的 CSS 选择器获取,但可以通过
:first-child
获取到。
伪元素
伪元素用于创建一些不存在文档树中的元素,并为其添加样式。比如说,我们可以通过 :before
来在一个元素前增加一些文本,并为这些文本添加样式。虽然用户可以看到这些文本,但是这些文本实际上不在文档树中。常见的伪元素有: ::before
, ::after
, ::first-line
, ::first-letter
, ::selection
, ::placeholder
等。
因此,伪类和伪元素的区别在于:有没有创建一个文档树之外的元素。
::after和:after的区别
在实际的开发工作中,我们会看到有人把伪元素写成 :after
, 这实际是 CSS2 和 CSS3 新旧标准的规定不同而导致的。 CSS2 中的伪元素使用1个冒号,在 CSS3 中,为了区分伪类和伪元素,规定伪元素使用2个冒号。所以,对于 CSS2 标准的老伪元素,比如 :first-line
, :first-letter
, :before
, :after
, 写一个冒号浏览器也能识别,但对于 CSS3 标准的新伪元素,比如 ::selection
,就必须要写2个冒号了。
CSS3新增伪类有那些?
p:first-of-type
选择属于其父元素的首个<p>
元素的每个<p>
元素。p:last-of-type
选择属于其父元素的最后<p>
元素的每个<p>
元素。p:only-of-type
选择属于其父元素唯一的<p>
元素的每个<p>
元素。p:only-child
选择属于其父元素的唯一子元素的每个<p>
元素。p:nth-child(2)
选择属于其父元素的唯一子元素的每个<p>
元素。:after
在元素之前添加内容,也可以用来做清除浮动。:before
在元素之后添加内容。:not(elem)
选择非 elem 元素的每个元素。:enabled
控制表单控件的禁用状态。:disabled
控件表单控件的禁用状态。:checked
单选框或复选框被选中。
# 9 ::before 和 :after 中双冒号和单冒号 有什么区别?
单冒号 :
用于 CSS3 伪类, 双冒号 ::
用于 CSS3 伪元素。(伪元素由双冒号和伪元素名称组成)双冒号是在当前规范中引入的,用于区分伪类和伪元素。不过浏览器需要同时支持旧的已经存在的伪元素写法,比如 :first-line
、:first-letter
、:before
、:after
等, 而新的在 CSS3 中引入的伪元素则不允许再支持旧的单冒号的写法。
想让插入的内容出现在其他现在内容前,使用 ::before
, 否则, 使用 ::after
; 在代码顺序上, ::after
生成的内容也比 ::before
生成的内容靠后。如果按推栈视角,::after
生成的内容会在 :: before
生成的内容之上。
# 10 filter: grayscale(100%) 实现全局灰白色
利用css一个属性实现网站灰白色,永远铭记12.13,勿忘国耻,振我中华。
南京大屠杀死难者国家公祭日是中国政府设立的纪念日,以国家公祭的方式,祭奠在南京大屠杀中死亡的30多万同胞
各大网站利用自身技能来表达自己对同胞的缅怀, 对国耻的重新认识,不忘初心, 为人民服务,为振兴我大中华而努力奋斗。
接下来是 利用 css
的 filter: grayscale(100%)
来实现。
想必各位都是骨骼惊奇,万中无一的奇才, 希望学技术知识的同时也要做一名爱国的人。
# 11 css 实现透明盒子+滚动边框
- 利用
clip: rect(0, 5px, 5px, 0)
也能实现滚动的边框,但是实现不了透明的盒子 + 滚动边框(并且转弯距离还要动态计算)。 - 不规则图像最好使用一张背景底图(不带边框)与一张只有边框的图片实现,当然头发多可以自己做出来。
clip-path:circle([半径] at [x] [y])
或clip-path: inset(0 0 99% 0)
来实现透明盒子 + 边框circle
圆角切割转弯处会变慢,inset
则不会。
# 核心动画
# 圆形切割
@keyframes clippath {
0%,to {
clip-path: circle(100px at 0 0);
}
25% {
clip-path: circle(100px at 0 100%);
}
50% {
clip-path: circle(100px at 100% 100%);
}
75% {
clip-path: circle(100px at 100% 0);
}
}
# 方形切割
@keyframes clip {
0%,to {
clip-path: inset(0 0 99% 0);
}
25% {
clip-path: inset(0 99% 0 0);
}
50% {
clip-path: inset(99% 0 0 0);
}
75% {
clip-path: inset(0 0 0 99%);
}
}
# 此页面代码
<template>
<div class="scroll-border">
<h2>不规则图像</h2>
<div class="row">
<div class="box" :style="{'background-image': src}">
<div class="border-img" :style="{'background-image': src1}"></div>
</div>
<div class="box" :style="{'background-image': src}">
<div class="border-img fff" :style="{'background-image': src1}"></div>
</div>
</div>
<h2>边框实现</h2>
<h3>圆形切割</h3>
<div class="row">
<div class="box box-bd"></div>
<div class="box box-bd fff"></div>
</div>
<h3>方形切割</h3>
<div class="row">
<div class="box box-wh"></div>
<div class="box box-wh fff"></div>
</div>
</div>
</template>
<script>
export default {
name: 'scroll-border',
data () {
return {
src: `url(https://cdn.jsdelivr.net/gh/tomiaa12/kuangyx.cn-public/img/文章/前端/css实现不规则透明盒子滚动边框/0.png)`,
src1: `url(https://cdn.jsdelivr.net/gh/tomiaa12/kuangyx.cn-public/img/文章/前端/css实现不规则透明盒子滚动边框/1.png)`
}
}
}
</script>
<style lang="scss" scoped>
.scroll-border {
background: linear-gradient(90deg, #355C7D, #6C5B7B, #C06C84);
padding: 1em;
}
h2,h3 {
color: white;
}
.row {
display: flex;
.box {
position: relative;
width: 50%;
height: 20rem;
background-repeat: no-repeat;
background-size: 100% 100%;
.border-img {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
animation: clippath 10s infinite linear;
background-repeat: no-repeat;
background-size: 100% 100%;
}
&+.box {
margin-left: 0.5em;
}
}
.box-bd,.box-wh {
background-color: rgba(0, 0, 0, $alpha: .3);
border-radius: 5px;
&::after, &::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
border-radius: inherit;
}
&::after {
border: 1px solid #fff;
animation: clippath 10s infinite linear;
}
}
.box-wh {
&::after {
animation: clip 10s infinite linear;
}
&::before {
border: 1px solid #fff;
animation: clip1 10s infinite linear;
}
&.fff::before {
background-color: inherit;
}
}
}
.fff {
background-color: rgba(255, 255, 255, $alpha: .5);
&::after {
background-color: inherit;
}
}
@keyframes clippath {
0%, to {
clip-path: circle(100px at 0 0);
}
25% {
clip-path: circle(100px at 0 100%);
}
50% {
clip-path: circle(100px at 100% 100%);
}
75% {
clip-path: circle(100px at 100% 0);
}
}
@keyframes clip {
0%, to {
clip-path: inset(0 0 99% 0);
}
25% {
clip-path: inset(0 99% 0 0);
}
50% {
clip-path: inset(99% 0 0 0);
}
75% {
clip-path: inset(0 0 0 99%);
}
}
@keyframes clip1 {
0%, to {
clip-path: inset(99% 0 0 0);
}
25% {
clip-path: inset(0 0 0 99%);
}
50% {
clip-path: inset(0 0 99% 0);
}
75% {
clip-path: inset(0 99% 0 0);
}
}
</style>
# 12 JavaScript 提取一张图片的主题色
想必都见过网易云和QQ音乐播放器界面的背景,这种背景都是利用css属性filter进行高斯模糊处理的。
当然也有在图片加载之前,背景为这种图片的主题色。又或者更好一些则更好一些则再图片由模糊到清晰的记载过程显示。
取得图片的主色调步骤主要分为:
- 1.获取图片绘制在 canvas 画布上
- 2.获取图片每个像素点的rgba值
- 3.对所有像素点rgba值统计
- 4.对统计的数据排序
接下来以这种图为例:
<style>
img {
width: 300px;
}
</style>
<body>
<img src="./0.png" id="img">
</body>
# 一、获取图片并绘制在 canvas 上
src 图片的加载是异步的,获取图片的宽高要等图片加载完成之后(onload)再获取,否则宽高都会是0。
const oImg = document.getElementById('img');
oImg.onload = function () {
const w = this.width;
const h = this.height;
// 创建画布
const canvas = document.createElement('canvas');
canvas.width = w;
canvas.height = h;
// 绘制图片在画布上
const context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
}
# 二、获取像素点 rgba 数据
// onload 内
let pxArr = context.getImageData(0, 0, w, h).data;
pxArr = Array.from(pxArr);
此时打印 pxArr 是这样的:
每隔4个数字为一组,分别为r、g、b、a 以此类推。
# 三、对px像素颜色数据统计
接下来只需要对数据进行每4个为一组的进行统计,统计出每个rgba颜色的次数。
// onload 内
const colorList = {}
let i = 0;
while (i < pxArr.length) {
const r = pxArr[i];
const g = pxArr[i+1];
const b = pxArr[i+2];
const a = pxArr[i+3];
i = i+4; // 最后 +4 比每次 i++ 快 10ms 左右性能
const key = [r,g,b,a].join(',')
key in colorList ? ++colorList[key] : (colorList[key] = 1)
}
此时 colorList 打印是这样的:
注意
不能用数据的 splice 来取四位数,这样会对原数组进行改变而影响性能
# 四、对统计的数据进行排序
// onload 内
let arr = [];
for(let key in colorList) {
arr.push({
rgba: `rgba(${key})`,
num: colorList[key]
})
}
arr = arr.sort((a, b) => b.num - a.num);
再打印 arr 查看图片的主色调: