博文状态:✅

专案知识点学习

【Udemy 排名第一的高级 CSS 课程】Advanced CSS and Sass

专案练习

效果演示:https://wu-honghao.github.io/outdoors/

代码仓库:https://outdoors.hellozero.site/

技术介绍:HTML5 + CSS3 + SCSS(布局 position + float + media)

以下是实现的思路分析

运用技术:

  • 背景:background-position background-size clip-path
  • 居中标题:@keyframes & animation transform
  • 了解我:pseudo-classes box-shadow transform

代码链接:https://codepen.io/wu-honghao/pen/jOzdKBq

Section-about

运用技术:

  • 二级标题
    • _utilities/ 自定义实现 .u-center-text .u-margin-bottom-8 (作用:是使块元素中文字居中和 底部margin8rem
    • 文字渐变效果 (background-image:linear-gradient()+background-clip:text + color:transparent)
    • 文字变形-倾斜 (transform:skewX() skewY())
    • 文字阴影效果 (text-shadow)。
  • 左右布局:Q11 自定义网格系统 (一行两列)
  • 右图片集合
    • 实现图片摆放:绝对定位 position:absolute
    • 图片立体阴影 :box-shadow
    • 图片 hover 时的绿色边框效果:设置轮廓 outline 与设置轮廓与元素之间的间距 outline-offset
    • 一张图片 hover 后其余图片缩小:设置起共同父元素 hover 时,指定的元素缩小
      • css 中选择器选择 .composition:hover .composition__photo:not(:hover){}
      • 上面代码翻译:当.composition 被选中的时候,.composition__photo 除了目前处于 hover 的状态的其他元素被选中。

git 代码版本号:41d8d49

Section-feature

运用技术:

  • 背景倾斜效果
    • translate:skewY 将 Section-feature 整体倾斜 7deg,然后子代元素再次倾斜回来即可
  • 卡片
    • box-shadow 做出阴影效果 + background-color
  • 图标
    • linea.io 官网 免费图标寻找并使用

git 代码版本号:e493c7f

Section-stories

运用技术:

  • 简单动态视频:coverr.co 官网,免费的自然风景动态视频获取。

  • 背景视频:使用的 video 标签和 及其内容为 source 写法

    1
    2
    3
    4
    <video class="bg-video__content" autoplay muted loop>
    <source src="/image/video.mp4" type="video/mp4" />
    <source src="/image/video.webm" type="video/webm" />
    </video>
  • 文字环形环绕:shape-outside 定义了一个可以是非矩形的形状,相邻的内联内容应围绕该形状进行包装

  • 鼠标 hover 时 story__shape 元素模糊效果:使用 filter 将模糊或颜色偏移等图形效果应用于元素。滤镜通常用于调整图像、背景和边框的渲染。目前效果:filter: blur(3px) brightness(80%);

git 代码版本号:257f476

Section-book

运用技术:

  • 背景渐变:background-image: linear-gradient(105deg, rgba($color-white, 0.9) 0%, rgba($color-white, 0.9) 50%, transparent 50%),url(../image/nat-10.jpg); 渐变效果在背景上面所以写在前面。
  • 单选框效果
    • 通过 label 的 for 属性将 label 和 input 绑定起来,当点击 label 的时候 input 也会被选中。
    • 在 label 中 自定义按钮 效果,代码中 &__radio-input:checked ~ &__radio-label &__radio-button::after 的意思是当 radio 被选中时去选中 radio-button 的里层小圆圈,就成功激活啦。
  • 文本输入框输入文字后 placeholder 下沉效果:首先这个下沉的元素并不是 placeholder ,只是一种视觉上的效果而已。其真正的实现靠的是自定义的 label,通过 transform 的 translate 在垂直方向做了平移而已,然后在用 opacity 透明度去骗过用户的眼睛。
    • 那么如何监听 placeholder 的变化呢?答案是 :placeholder-shown CSS 伪类 在 input textarea 元素显示 placeholder text 时生效。

运用技术:

  • navigation-icon 的表现实现:使用 before 和 after 伪类去制作上下两条杠。
  • navigation-button 点击时 navigation__icon 切换三条杠和 X 的效果:使用的是 checkbox input + label for 的方法,当 checkbox 处于 checked 时在 css 中去影响 navigation__icon 的状态,设置 icon 也就是中间那一条杠的颜色为 transparent,icon 上下两条杠变形为旋转 45deg 即可。
  • navigation 打开状态的背景颜色:初始是一个渐变圆圈,当按钮激活后则将圆圈放大到铺满整屏,使用 transform:scale()
  • navigation-item 的水晶效果:设置纯色渐变 background-image: linear-gradient(120deg, transparent 0%, transparent 50%, $color-white 50%);,将 item 铺满初始状态铺满 200% 使透明和白色渐变各占 100% 的大小。当 item 被 hover 时,使用 background-position 将白色部分移动过来即可。
  • 切换 navigation 时 nav 本身淡入淡出效果:初始宽度设置为 0,在激活时 navigation 时调整 nav 宽度为 100% 即可,再加上过渡动画的效果就可以了。

运用技术:

  • 点击 book now 按钮时弹出详情窗口:使用的是锚点链接,通过锚点跳转,再设置瞄点所指的详情窗口中伪类 :target 的状态样式即可。

  • popup 左、右块元素垂直对齐:设置父元素 display:table,本身元素设置为 display: table-cell,再用 vertical-align: center 使其居中对齐。

  • 段落文本分栏排列

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    .text {
    // 设置文字的列数
    column-count: 2;
    // 列间距
    column-gap: 4rem;
    // 列间分割线
    column-rule: 1px solid #eee;
    // 告知浏览器在换行时如何使用连字符连接单词 (设置连字符)
    hyphens: auto;
    }

技术详细介绍

Q1:响应式布局

方案一:媒体查询 + rem

描述:给 html 根设置 font-size,往后用 px 的地方改用换算后的 rem 单位。设置媒体查询适配每一个宽度时去改变 font-size 的大小,一般设置 html 根的 font-size 为 5px(移动端),往后适配更多的像素比可以在媒体查询中修改(pc 端各大小)。

ps.在使用媒体查询时,一定要保证媒体查询的位置要放在 CSS 样式的最后面。这是因为为元素设置 CSS 样式时,假如与媒体查询中的样式是相同属性权重时,下面的 CSS 样式会覆盖上面的 CSS 样式,如果不将媒体查询放在最后,它的样式将不会生效。

使用技术:原生 @media

demo 演示(效果请用浏览器缩放来实现):rem + media 演示

改进方案一:自定义媒体查询管理器 + 桌面端优先策略

描述:桌面端优先策略或移动端优先策略(大体上先通过媒体查询修改对应根节点的 font-size 大小去影响使用 rem 单位的元素,先适配其中的一个分辨率,其他分辨率下的再去做微小调整)

使用技术:scss + 自定义媒体查询管理器(详细看 技术详细介绍 Q13

使用场景:先以桌面端优先布局,后根据各分辨率需要调整局部的布局

Q2:box-sizing 属性值

CSS 中的 box-sizing 属性定义了 user agent 应该如何计算一个元素的总宽度和总高度。

  1. content-box:content,例如设置width:100px (则 content 区域就是 100px)
  2. border-box:+border+padding+content,例如设置width:100px (则 content+border+padding 区域总大小就是 100px,实际 content 区域大小用 100px 减去其他两个)
  3. inherit:继承父元素

Q3:%,em,rem,vh,vw

换算规律如下

example how to convert to pixels result in pixels
%(fonts) 150% x% * parent’s computed font-size 24px
%(lengths) 10% x% * parent’s computed width 100px
em(font) 3em x * parent computed font-size 72px(3*24)
em(lengths) 2em x * current element computed font-size 48px
rem 10rem x * root computed font-size 160px
vh 90vh x * 1% of viewport height 90% of the current viewport heigth
vw 80vw x * 1% of viewport width 80% of the current viewport width

Q4:属性继承

继承将一些特定属性的值从父级传递给子级

继承与文本相关的属性:字体族、字体大小、颜色等;

只有在没有人为该属性声明值的情况下,该属性的继承才有效;

inherit 关键字强制继承某个属性;

initial 关键字将属性重置为初始值。

Q5:CSS — BEM 命名规范

使用 BEM 命名规范,理论上讲,每行 css 代码都只有一个选择器。

BEM 代表 “块(block),元素(element),修饰符(modifier)”,我们常用这三个实体开发组件。

在选择器中,由以下三种符号来表示扩展的关系:

  • 中划线 - :仅作为连字符使用,表示某个块或者某个子元素的多单词之间的连接记号。
  • 双下划线 __:双下划线用来连接块和块的子元素
  • 双中划线 _:单下划线用来描述一个块或者块的子元素的一种状态

参考:https://github.com/Tencent/tmt-workflow/wiki/%E2%92%9B-[%E8%A7%84%E8%8C%83]--CSS-BEM-%E4%B9%A6%E5%86%99%E8%A7%84%E8%8C%83

Q6:SCSS 入门

  • 变量声明和使用
  • mixin 混合声明和使用
  • function 函数声明和使用
  • extend 继承声明和使用

以下案例 codepen:https://codepen.io/wu-honghao/pen/XWEQeXX

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
//变量声明
$color-primary:#f9ed69;
$color-secondary:#f08a5d;
$color-tertiary:#b83b5e;

*{
margin:0;
padding:0;
}

//函数声明
@function divide($a,$b){
@return $a / $b
}

//混合声明
@mixin clearfix{
&::after{
content:"";
display:table;
clear:both;
}
}

nav{
//变量使用
background-color:$color-primary;
//混合使用
@include clearfix;

a{
text-decoration:none;
color:black
}

.navigation{
//函数的使用
margin:divide(30,2) * 1px;
background-color:#fbeb41;
>li{
float:left;
padding:10px 20px;
list-style:none;
}
}

//声明继承
%btn-placeholder{
border-radius:10px;
color:white;
}

.buttons{
float:right;
margin-right:40px;
a{
display:inline-block;
padding:10px 40px;
}

.btn-main{
//继承使用语法 @extend 变数名
@extend %btn-placeholder;
background-color:$color-secondary;

&:hover{
background-color:darken($color-tertiary,15%);
}
}

.btn-hot{
@extend %btn-placeholder;
background-color:$color-tertiary;

&:hover{
background-color:lighten($color-secondary,15%);
}
}
}
}

Q7:npm 包管理器使用

是什么?npm 是 Node.js 标准的软件包管理器。

有什么用?用来下载你之前 cdn 引入的那些第三方插件的。

怎么安装?

第一步:首先你需要有 node 环境,下载官网:http://nodejs.cn/

第二步:打开 window/mac 命令行工具,cd 进入到自己的项目中。

第三步:在项目根目录下使用 npm init 一直下一步最终会生成一个 package.json 的描述文件就证明你成功了。

Q8:live-server 安装使用

是什么?:一个具有实时加载功能的小型服务器,可以使用它来破解 html/css/javascript,但是不能用于部署最终站点。也就是说我们可以在项目中实时用 live-server 作为一个实时服务器实时查看开发的网页或项目效果。

有什么用?:简单来说这个工具可以在你 html/css/javascript 编写保存后,帮你自动刷新界面,不用你手动刷新。

怎么安装?在项目根目录下运行 npm install live-server -g (解释:-g 是全局安装)

怎么使用?在项目根目录下运行 live-server 后自动帮你将项目的 index.html 用浏览器打开,端口为 127.0.0.0。

Q9:node-sass 安装使用

是什么? sass 的一个相关库

有什么用?它会帮用户快速将.scss 文件通过连接中间件自动编译为 css。

怎么安装?npm install node-sass --save-dev (解释:–save-dev 是在开发环境中安装)

怎么使用?

第一步:在 package.json 文件中的 scripts 下编写 compile:sass 命令。

第二部:在项目根目录下运行 npm run compile:sass

1
2
3
4
"scripts": {
//这里编写了一个 npm 命令,具体执行的操作是用 node-sass 库将 sass/main.scss 编译文件生成到 css/main.css -w,-w是持续监听的意思。
"compile:sass": "node-sass sass/main.scss css/main.css -w"
},

Q10:scss archtecture

是什么?编写 scss 人员的规范化操作,架构思想是迈向高级程序员的第一步。

有什么用?提高维护性,可读性。

框架/怎么使用?
  • abstracts/ 放抽象文件,如函数,混合,变量等..
  • base/ 放一些公用代码,如动画,公用,文字排版,工具。
  • component/ 放一些组件
  • layout/ 放一些布局相关的,如 header,footer,main
  • pages/ 主要是放页面的其他样式。
  • main.scss 是所有文件的入口,应将所有带有“”的文件引入

注:此处的 ““ 前缀文件都是通过引入使用,不直接参与编译

image-20220830204754550

Q11:如何自定义网格系统

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<section class="grid">
<div class="row">
<div class="col-1-of-2">col-1-of-2</div>
<div class="col-1-of-2">col-1-of-2</div>
</div>

<div class="row">
<div class="col-1-of-3">col-1-of-3</div>
<div class="col-1-of-3">col-1-of-3</div>
<div class="col-1-of-3">col-1-of-3</div>
</div>

<div class="row">
<div class="col-1-of-3">col-1-of-3</div>
<div class="col-2-of-3">col-2-of-3</div>
</div>

<div class="row">
<div class="col-1-of-4">col-1-of-4</div>
<div class="col-1-of-4">col-1-of-4</div>
<div class="col-1-of-4">col-1-of-4</div>
<div class="col-1-of-4">col-1-of-4</div>
</div>

<div class="row">
<div class="col-1-of-4">col-1-of-4</div>
<div class="col-1-of-4">col-1-of-4</div>
<div class="col-2-of-4">col-2-of-4</div>
</div>

<div class="row">
<div class="col-1-of-4">col-1-of-4</div>
<div class="col-3-of-4">col-3-of-4</div>
</div>
</section>
1
2
3
4
5
6
// sass/abstracts/_variables.scss

//设置网格的大小,网格间水平、垂直间距
$grid-width: 114rem;
$gutter-vertical: 8rem;
$gutter-horizontal: 6rem;
1
2
3
4
5
6
7
8
9
10
// sass/abstracts/_mixins.scss

//清除浮动带来的高度塌陷
@mixin clearfix {
&::after {
content: '';
display: table;
clear: both;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// sass/layout/_grid.scss
.row {
max-width: $grid-width;
margin: 0 auto;

&:not(:last-child) {
margin-bottom: $gutter-vertical;
}

//使用混合函数(use @mixin)
@include clearfix;

// class 以 col- 开头
[class^='col-'] {
float: left;

&:not(:last-child) {
margin-right: $gutter-horizontal;
}
}

.col-1-of-2 {
//calc()是 css 中的计算属性,可以在多个 css unit 转换,
// #{$gutter-horizontal} 是在 calc 函数中使用 scss 语法中的变量
width: calc((100% - #{$gutter-horizontal}) / 2);
}

.col-1-of-3 {
width: calc((100% - 2 * #{$gutter-horizontal}) / 3);
}

.col-2-of-3 {
width: calc(2 * ((100% - 2 * #{$gutter-horizontal}) / 3) + #{$gutter-horizontal});
}

.col-1-of-4 {
width: calc((100% - 3 * #{$gutter-horizontal}) / 4);
}

.col-2-of-4 {
width: calc(2 * ((100% - 3 * #{$gutter-horizontal}) / 4) + #{$gutter-horizontal});
}

.col-3-of-4 {
width: calc(3 * ((100% - 3 * #{$gutter-horizontal}) / 4) + 2 * #{$gutter-horizontal});
}
}

Q12:如何制作翻转展示卡片

思路

  1. 通过设置 translate 的 rotateY 属性沿着 Y 轴去做 180deg 的翻转,可以实现一个元素的翻转效果
  2. 要想实现正反面,需要用两个卡片元素去制作,将两个元素通过绝对定位叠放在一起,将两个元素的背面隐藏。记得要设置元素的大小,不然会出现塌陷问题。置于反面元素设置初始的 transform:rotate 为 180deg,在用户 hover 时将元素的 rotate 设置为 0 deg。
  3. 基本上就实现了,内容自己填充即可。

Q13:scss 媒体查询管理器

实现:通过混合实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
$breakpoint 传入响应式的设备名称
可选值:phone,tab-port,tab-land,big-desktop
0 - 600px: phone
600px - 900px: tablet portrait/tab-port
900px - 1200px: tablet landscape/tab-land
1200px - 1800px is where our normal styles apply
1800px +: big desktop
*/
@mixin response($breakpoint) {
// 当满足传入实参为 phone 时匹对且应用代码块中的规则
@if $breakpoint == phone {
@media screen and (max-width: 37.5em) {
// width < 600px ?
// @content 是在使用中代码块中的内容,会帮你放进来
@content;
}
}

@if $breakpoint == tab-port {
@media screen and (max-width: 56.25em) {
// width < 900px ?
@content;
}
}

@if $breakpoint == tab-land {
@media screen and (max-width: 75em) {
// width < 1200px ?
@content;
}
}

@if $breakpoint == big-desktop {
@media screen and (min-width: 112.5em) {
// width < 1800px ?
@content;
}
}
}

使用实例:在根节点应用媒体查询管理器,桌面端优先策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
html {
/*
!! 要注意媒体查询代码块优先级问题
举例:如 700px 应用以下哪一个规则呢?是小于等于 1200px 的规则还是小于等于 900px 的规则?
答案:如果有冲突,当然是后编写的代码生效,所以是匹配 900px 的规则。但你如果把 tab-land 和 tab-port 反过来写那就会应用 1200px 的规则。
*/

@include response(tab-land) {
// width < 1200px ?
font-size: 56.25%;
}

@include response(tab-port) {
// width < 900px ?
font-size: 50%;
}

@include response(big-desktop) {
// width < 1800px ?
font-size: 75%;
}
}

响应式图像

实现响应式图像的四种技术策略:https://github.com/xitu/gold-miner/blob/master/article/2021/responsive-images-different-techniques-and-tactics.md

检测 CSS 属性值是否可用

网站:caniuse.com

踩坑记录

  1. transform:skew(-7deg) (单位是 deg 而不是其他的,因为涉及到的是倾斜变形)

  2. 传统布局的水平居中方式

    其他居中方式可参考:https://www.cnblogs.com/coco1s/p/4444383.html

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    .father {
    position:relative > son {
    // 注意子元素要有高度才能奏效,如果父元素是100%height那么不声明高度则自动继承父元素高度
    height: 50%;
    position: absolute;
    margin: auto;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    }
    }
  3. 字体颜色渐变效果设置

    使用 autoprefixer 可以完美解决前缀不全的写法(工程化项目中使用:http://chenqichun.com/articleDetails/615159c99e58dfeb349bed64)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 渐变效果是以图片的形式设置的
    background-image: linear-gradient(
    //渐变的方向:从左到右 第一种颜色 -> 第二种颜色(箭头是逐渐过渡的意思)
    to right,
    $color-primary-light,
    $color-primary-dark
    );
    //-webkit代表safari、chrome私有属性。一般用于标准还未生成的实验属性。表示该内核以支持。同时也可用于兼容老版本的浏览器
    -webkit-background-clip: text;
    //将背景被裁剪成文字的前景色。
    background-clip: text;
    color: transparent;
  4. transform translate rotate : 平移和旋转

  5. 背景视频覆盖超出屏幕

    因为背景视频是使用的 可替换元素-video ,因此可以使用 object-fit 来指定其内容在元素盒区域中的填充方式。类似于 background-size

  6. border 对齐,将这个元素转换成行内块元素即可:display:inline-blockimage-20220915125504963

  7. transform: rotate() 属性没有 X , Y 轴的旋转区分。

  8. 以下语句的意思:

    1
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />

    width=device-width部分设置页面的宽度以跟随设备的屏幕宽度(这将因设备而异)。

    initial-scale=1.0部分设置浏览器首次加载页面时的初始缩放级别。