案例来源于:https://github.com/bradtraversy/50projects50days,部分资源需要科学上网加载使用,往后不再赘述。
合集链接,欢迎订阅:
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkwODY2OTA5NA==&action=getalbum&album_id=3618277165223084032#wechat_redirect
部分动态图:
0、开始项目
(1)实现效果
开始项目显示效果如下,无其他特效,仅将Project Starter居中显示。
(2)代码解读
HTML代码
<!DOCTYPE html>
<!-- <!DOCTYPE> 声明向浏览器提供有关所期望的文档类型的“信息”。 -->
<!-- 定义语言 -->
<html lang="en">
<!-- <head> 元素是所有头部元素的容器。 -->
<head>
<!-- 规定 HTML 文档的字符编码 -->
<meta charset="UTF-8" />
<!--定义了网页在浏览器上的视口设置,确保网页的宽度与设备屏幕宽度相匹配,并设置初始缩放比例为1.0 -->
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 引入了一个外部的CSS样式表 -->
<link rel="stylesheet" href="style.css" />
<!-- 定义网页title -->
<title>My Project</title>
</head>
<!-- 定义了网页的主体内容,即用户在浏览器中看到的部分 -->
<body>
<!-- 定义一级标题内容 -->
<h1>Project Starter</h1>
<!-- <script>标签用于引入JavaScript文件或直接编写JavaScript代码 -->
<script src="script.js"></script>
</body>
</html>
CSS代码
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
/* 一个@import规则,用于从Google Fonts导入Roboto字体 */
/* 通用选择器*,将box-sizing属性设置为border-box。元素的宽度和高度会包括边框border和内边距padding,避免在布局中出现意外的尺寸问题。 */
* {
box-sizing: border-box;
}
body {
/* font-family设置为Roboto字体,如果Roboto字体无法加载,则会回退到无衬线字体。 */
font-family: 'Roboto', sans-serif;
/* 将body元素设置为一个弹性容器 */
display: flex;
/* 定义了弹性容器的主轴方向为垂直方向 */
flex-direction: column;
/* 将弹性容器内的项目在水平和垂直方向上居中对齐。 */
align-items: center;
justify-content: center;
/* 将body的高度设置为视口高度的100% */
height: 100vh;
/* 避免溢出,隐藏超出的部分 */
overflow: hidden;
/* 移除了body元素的外边距 */
margin: 0;
}
JS代码
未使用JS
(3)知识点
这个小项目的知识点较为基础,包括如何@import
的用法、内容居中显示等。
1)@import
规则通常放在CSS文件的顶部,在CSS中用于导入外部样式表,常用的语法便是:@import url('url')
;2)内容居中显示主要是使用:display: flex
将body
元素设置为一个弹性容器,flex-direction: column
定义弹性容器的主轴方向为垂直方向(这句有时候可以忽略),align-items: center
和justify-content: center
将弹性容器内的项目在水平和垂直方向上居中对齐。
1、3D盒子背景动态分解效果
(1)实现效果
加载小黄人动态图片,点击Magic按钮实现动态分解/合并的效果。
(2)代码解读
HTML代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<!-- 使用font-awesome图标库,Font Awesome是一个图标字体和CSS框架,提供可缩放矢量图标 -->
<!-- rel="stylesheet":指定这是样式表,href:指定样式表的URL-->
<!-- integrity:用于指定资源的完整性校验,确保加载的资源未被篡改 -->
<!-- crossorigin:指定资源是否允许跨域请求,anonymous表示请求不携带凭证 -->
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css"
integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog=="
crossorigin="anonymous"
/>
<link rel="stylesheet" href="style.css" />
<title>3D Boxes Background</title>
</head>
<body>
<!-- 定义按钮元素,用来触发事件,这里的元素内容使用了一个魔术帽的表情符号 -->
<button id="btn" class="magic">Magic 🎩</button>
<!-- 添加容器,用来放置具体的内容 -->
<div id="boxes" class="boxes big"></div>
<script src="script.js"></script>
</body>
</html>
CSS代码
@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;700&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Poppins&display=swap');
/* 引入了两种字体,Roboto和Poppins */
/* 还是使用*通用选择器匹配页面所有元素,将box-sizing属性设置为border-box改变元素盒模型的计算方式,使元素的宽度和高度包括内容、内边距(padding)和边框(border) */
* {
box-sizing: border-box;
}
/* 设置body元素样式 */
body {
/* 设置背景色 */
background-color: #fafafa;
/* 设置字体,如果roboto字体不能用则使用sans-serif字体 */
font-family: 'Roboto', sans-serif;
/* 弹性容器 */
display: flex;
/* 主轴为垂直方向 */
flex-direction: column;
/* 垂直方向居中 */
align-items: center;
/* 水平居中 */
justify-content: center;
height: 100vh;
/* 隐藏超出部分 */
overflow: hidden;
}
/* 设置magic按钮样式 */
.magic {
background-color: #f9ca24;
/* 字体颜色 */
color: #fff;
font-family: 'Poppins', sans-serif;
/* 无框线 */
border: 0;
/* 边框圆角为3像素 */
border-radius: 3px;
/* 字号 */
font-size: 16px;
/* 设置内边距垂直内边距为12px,水平内边距20px */
padding: 12px 20px;
/* 鼠标悬停时,光标为 pointer指针小手的样式,暗示可以点击*/
cursor: pointer;
/* 将元素相对于视窗进行定位,即元素的位置保持不变*/
position: fixed;
/* 设置元素距离其包含块顶部20像素,也就是浏览器顶部 */
top: 20px;
/* 字母之间的间距 */
letter-spacing: 1px;
/* 盒子阴影效果 */
box-shadow: 0 3px rgba(249, 202, 36, 0.5);
/* 元素的堆叠顺序 */
z-index: 100;
}
/* 定义两个伪类选择器,用于改变元素在特定交互状态下的样式*/
.magic:focus {
/* 移除当.magic类的元素获得焦点时浏览器默认的轮廓线(outline),感觉可以省略 */
outline: none;
}
.magic:active {
/* 移除当.magic类的元素被按下(活跃状态)时的阴影效果,给用户一种按钮被按下的视觉反馈*/
box-shadow: none;
/* 使用CSS变换(transform)属性将元素向下移动2像素,给用户一种按钮被按下的视觉效果 */
transform: translateY(2px);
}
/* 先定义boxes类的效果,这是效果图第二张图时的设置 */
.boxes {
display: flex;
/* 允许子元素换行显示 */
flex-wrap: wrap;
/* 在主轴上平均分布子元素,每个元素两侧的间隔相等 */
justify-content: space-around;
/* 设置高和宽 */
height: 500px;
width: 500px;
/* 相对定位 */
position: relative;
/* 为尺寸变化设置一个0.4秒的渐变动画效果 */
transition: 0.4s ease;
}
/* 盒子分散后的尺寸设置 */
.boxes.big {
width: 600px;
height: 600px;
}
/* .box由JS函数创建 */
.boxes.big .box {
/* 子元素.box在.boxes.big容器中会被旋转360度 */
transform: rotateZ(360deg);
}
/* 设置16个子元素.box的样式 */
.box {
/* 添加背景图为小黄人动图 */
background-image: url('https://media.giphy.com/media/EZqwsBSPlvSda/giphy.gif');
/* 确保背景图像不重复平铺 */
background-repeat: no-repeat;
/* 背景图尺寸 */
background-size: 500px 500px;
/* 相对定位 */
position: relative;
/* 设置.box元素的尺寸 */
height: 125px;
width: 125px;
/* 变换设置一个0.4秒的渐变动画效果 */
transition: 0.4s ease;
}
/* 定义了.box元素的两个伪元素::after和::before的样式,形成分割后的小图片三维景深的效果*/
/* 小图片右侧的黄色矩形 */
.box::after {
/* 必须提供非空的content属性值来创建伪元素 */
content: '';
background-color: #f6e58d;
/* 相对于其最近的已定位(非static)祖先元素为绝对定位 */
position: absolute;
/* 将伪元素从其包含元素的顶部向下偏移8像素 */
top: 8px;
/* 向左偏移15像素 */
right: -15px;
/* 高度为其包含元素的高度的100% */
height: 100%;
/* 设置伪元素的宽度为15像素 */
width: 15px;
/* 沿着Y轴将伪元素倾斜45度 */
transform: skewY(45deg);
}
/* 小图片下面的黄色矩形 */
.box::before {
content: '';
background-color: #f9ca24;
position: absolute;
/* 向上偏移15px */
bottom: -15px;
/* 向右偏移8px */
left: 8px;
/* 高15px */
height: 15px;
/* 宽100% */
width: 100%;
/* 沿着x轴将伪元素倾斜45度 */
transform: skewX(45deg);
}
JS代码
const boxesContainer = document.getElementById('boxes')
// 上句获取html文件中ID为boxes的元素的引用
const btn = document.getElementById('btn')
// 上句获取html文件中ID为btn的元素的引用
// 下面为按钮添加一个点击事件监听器,点击按钮时,切换boxesContainer的big类。
// 点击magic按钮后big类被添加,根据CSS样式改变 boxes也就是boxesContainer 的尺寸
btn.addEventListener('click', () => boxesContainer.classList.toggle('big'))
// 生成一个4x4的网格布局,每个格子是一个带有box类的div元素。
function createBoxes() {
// 两次循环,生成4*4的小盒子
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
// 使用document.createElement方法创建div
const box = document.createElement('div')
// 为创建的div添加box
box.classList.add('box')
// 设置每个box的背景位置,分别是向左偏移-j*125px即向右偏移j*125,和向上偏移-i*125px
box.style.backgroundPosition = `${-j * 125}px ${-i * 125}px`
// 将创建的box元素添加到boxesContainer中
boxesContainer.appendChild(box)
}
}
}
createBoxes()
(3)知识点
可以通过在浏览器中F12打开控制台,查看一些代码勾选与否的效果,通过对比能够更容易明白一些代码的作用。
Html文件中还增加了一些之前未接触过的设置,例如crossorigin
属性在HTML中用于指定是否应该在请求外部资源时发送凭据(如cookies、授权头等)。这个属性通常与图片、字体、脚本等资源的加载有关,特别是在使用CDN或跨域请求资源时。anonymous
是默认值,表示请求不会携带任何凭据,即不会发送cookies或HTTP认证信息。这适用于大多数情况,特别是访问不需要受保护的资源时。
这里涉及了CDN和跨域的概念,CDN是全称是Content Delivery Network,即内容分发网络,其基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输得更快、更稳定。按我的理解,简单来说就是一个数据,黑龙江和西藏的用户都要访问,但是如果放在黑龙江的服务器上,西藏用户访问慢;放在西藏服务器,黑龙江用户慢。所以使用CDN将数据放在了全国各地的服务器上,黑龙江用户访问黑龙江服务器上的数据,西藏用户也就近访问西藏服务器上的用户。跨域请求也很简单,你在自己的网站中使用别人网站发布数据的链接时,就发生了跨域访问。
2、动画倒计时
合集链接,欢迎订阅:
https://mp.weixin.qq.com/mp/appmsgalbum?__biz=MzkwODY2OTA5NA==&action=getalbum&album_id=3618277165223084032#wechat_redirect