共计 19056 个字符,预计需要花费 48 分钟才能阅读完成。
快速入门 HTML + CSS + JS
HTML
HTML 是网页内容的标准标记语言,用于定义网页的结构和内容。它由一系列的元素(elements)组成,这些元素可以包含文本、图片、链接以及其他媒体内容。
1. 简单案例
DOCTYPE html>
html lang="en">
head>
meta charset="UTF-8">
meta name="viewport" content="width=device-width, initial-scale=1.0">
title>Documenttitle>
head>
body>
h1>Hello Html!h1>
body>
html>
2. 常用标签
-
标题标签:
h1>我是一个一级标题h1> h2>我是一个二级标题h2> h3>我是一个三级标题h3> h4>我是一个四级标题h4> h5>我是一个五级标题h5> h6>我是一个六级标题h6>
-
修饰标签
b>我是 b 标签,用于加粗b> br> i>我是 i 标签,用于斜体i> br> u>我是 u 标签,用于下划线u> hr> strong>我是 strong 标签,用于强调strong> br> em>我是 em 标签,用于斜体em>
-
列表标签
ul> li>无序列表li> li>元素 1 li> li>元素 2 li> ul> ol> li>有序列表li> li>元素 1 li> li>元素 2 li> ol>
-
表格属性
table border="1"> tr> th>标题 1 th> th>标题 2 th> th>标题 3 th> tr> tr> td>元素 11td> td>元素 12td> td>元素 13td> tr> tr> td>元素 21td> td>元素 22td> td>元素 23td> tr> table>
-
链接标签
a href="https://www.baidu.com/" target="_blank">点击链接到 => 百度a>
-
图片标签
img src="./Forest.png" alt="很抱歉,图片无法显示" width="960px">
-
容器标签
div id="10" class="div-class" style="color: aqua;"> p>我是一个段落标签p> p>我会自动分段p> div> div> p>b>我在第二个容器中b>p> div>
-
行内容器标签
span>我是一个行内容器,用于将部分行内元素进行包裹,以便进行统一管理。span> span>我是第二个行内容器,行内元素之间不会分段span>
-
表单容器
form action="#"> label for="username">用户名称:label> input id="username" type="text"> br> label for="password">用户密码:label> input id="password" type="password"> br> input type="text" placeholder="我是隐式提示"> br> input type="text" value="我是显示提示"> br> input type="radio" name="fix1" id="option1"> label for="option1">选项 1 label> input type="radio" name="fix1" id="option2"> label for="option2">选项 2 label> input type="radio" name="fix1" id="option2"> label for="option3">选项 2 label> br> input type="checkbox" name="fix2" id="checkopt1"> label for="checkopt1">选项 1 label> input type="checkbox" name="fix2" id="checkopt2"> label for="checkopt1">选项 2 label> input type="checkbox" name="fix2" id="checkopt3"> label for="checkopt1">选项 3 label> br> input type="submit" value="提交按钮"> form>
3. 案例练习 — — 爱好选择表单
DOCTYPE html>
html lang="en">
head>
meta charset="UTF-8">
meta name="viewport" content="width=device-width, initial-scale=1.0">
title>爱好选择表单title>
head>
body>
h1>爱好选择表单h1>
p>请在下方选择或填写您的爱好。p>
form action="#" method="post">
fieldset>
legend>请选择您的爱好(可多选):legend>
label>
input type="checkbox" name="hobby" value="reading">
阅读
label>
br>
label>
input type="checkbox" name="hobby" value="sports">
运动
label>
br>
label>
input type="checkbox" name="hobby" value="music">
音乐
label>
br>
label>
input type="checkbox" name="hobby" value="art">
艺术
label>
fieldset>
br>
label for="other_hobby">其他爱好:label>
input type="text" id="other_hobby" name="other_hobby" placeholder="请输入其他爱好">
br>
fieldset>
legend>选择您的主要爱好:legend>
label>
input type="radio" name="main_hobby" value="reading">
阅读
label>
br>
label>
input type="radio" name="main_hobby" value="sports">
运动
label>
br>
label>
input type="radio" name="main_hobby" value="music">
音乐
label>
fieldset>
input type="submit" value="提交">
form>
footer>
p>© 2024 爱好选择表单p>
footer>
body>
html>
CSS
CSS 用于设置 HTML 元素的样式和布局,它不是编程语言,而是一种样式表语言,用于描述 HTML 文档的呈现方式。
CSS 语法
选择器 {
属性 1 : 属性值 1 ;
属性 2 : 属性值 2 ;
}
实例:
p{
color: blue;
font-size: 16px;
}
CSS 的三种导入方式
- 内联样式
- 内部样式表
- 外部样式表
优先级:内联样式 > 内部样式表 > 外部样式表
1. 内联样式
h1 style="clolr: red;">红色的一级标题h1>
2. 内部样式表
通常在 标签里添加
标签,并在
标签里定义样式:
head>
style>
h2 {
color: green;
}
style>
head>
3. 外部样式表
-
创建 CSS 文件,如:
test.css
-
在
test.css
文件中编写样式:h3 { color: purple; }
-
在
html
文件中进行导入:- 在
标签中添加
标签:
- 在
-
标签下编写
标签即可应用该样式。
选择器
- 元素选择器
- 类选择器
- ID 选择器
- 通用选择器
- 子元素选择器
- 后代选择器(又称:包容选择器)
- 并集选择器(又称:兄弟选择器)
- 伪选择器
1. 元素选择器
h2 {
color: aqua;
}
2. 类选择器
.highlight {
background-color: yellow;
}
3. ID 选择器
#header{
font-size: larger;
}
4. 通用选择器
* {
font-family: 'KaiTi';
}
5. 子元素选择器
.father > .son{
color: yellowgreen;
}
6. 后代选择器
.father p{
color: brown;
font-size: larger;
}
7. 并集选择器
h3 + p {
background-color: red;
}
8. 伪选择器
#element: hover {
background-color: blueviolet;
}
常用的还有:
first-child
:选中第一个子元素nth-child()
:选中第n
个元素active
:链接状态
伪元素选择器:
创建一个虚拟元素样式化,而不是选择实际存在的元素
例:
::after
:选中元素后插入虚拟内容::befor
:选中元素前插入虚拟内容
CSS 常用属性
-
font
复合属性h1 style="font: bolder 50px 'KaiTi';">样式一级标题h1>
-
行高属性
p style="line-height: 40px">行高为 40pxp>
- 行内元素:不会换行的标签,不能设置宽度和高度,不能包含其他元素,如:
、
标签。- 块元素:默认换行的标签,能设置宽度和高度,可以包含行内元素,如:
、
、
标签。- 行内块元素:水平方向上排列,但可以设置宽度、高度、内外边距等块级元素的属性。行内块元素可以包含其他行内元素或块级元素。
转换属性
div sytle="display: inline-block;">div>
盒子模型
- 内容(content):盒子包含的实际内容,比如文本、图片等。
- 内边距(padding):围绕在内容的内部,是内容与边框之间的空间。可以使用 padding 属性来设置。
- 边框(border):围绕在内边距的外部,是盒子的边界。可以使用 border 属性来设置。
- 外边距(margin):围绕在边框的外部,是盒子与其他元素之间的空间。可以使用 margin 属性来设置。
例:
.demo { border: 5px solid yellowgreen; } .border-demo { border-style: solid; border-width: 10px 0 20px 40px; border-color: blueviolet; } .fs{ padding: 50px; margin: 40px; }
定位
- 相对定位:相对于元素在文档流中的正常位置进行定位。
- 绝对定位:相对于其最近的已定位祖先元素进行定位,不占据文档流。
- 固定定位:相对于浏览器窗口进行定位。不占据文档流,固定在屏幕上的位置,不随滚动二移动。
例:
.box-relative { width: 100px; height: 100px; background-color: pink; position: relative; left: 120px; top: 40px; } .box-fixed { width: 100px; height: 100px; background-color: brown; position: fixed; right: 0; top: 300px; } .box-absolute { width: 100px; height: 100px; background-color: yellowgreen; position: absolute; left: 120px; }
网页布局方式:
- 标准流(普通流、文档流):网页按照元素的书写顺序依次排序。
- 浮动
- 定位
Flexbox
和Grid
(自适应布局)浮动
CSS 中的浮动(Float)是一种布局技术,用于将元素从文档的正常流动中取出,并将其向左或向右移动,直到它的外边缘碰到父元素的边缘或另一个浮动元素。浮动元素会脱离常规文档流,这意味着它们不会占用文档中的位置,从而允许文本和内联元素环绕它们。
浮动属性用于创建浮动框,将其移动到一边,直到左边缘或右边缘触及包含块或另一个浮动框的边缘,这样即可使得元素进行浮动。
语法
选择器: { float: left/right/none; }
注意:浮动是相对于父元素浮动,只会在父元素的内部移动。
浮动的三大特性
脱离文档流:浮动元素会从常规文档流中脱离出来,这意味着它不再占据文档流中的正常位置,周围的元素会根据浮动元素的位置进行布局。
环绕效果:浮动元素允许文本和内联元素环绕在其周围。这种特性使得内容可以更加灵活地布局,例如在图片周围添加文字描述。
- 清除浮动 :当一个元素设置为
clear
属性时,它会移动到浮动元素的下方,并且不会与浮动元素在同一行。clear
属性可以设置为left
、right
或both
,分别表示清除左侧浮动、右侧浮动或两侧的浮动例:
.father { background-color: aquamarine; height: 150px; border: 3px solid brown; } .left-son { width: 100px; height: 100px; background-color: yellowgreen; float: left; } .right-son { width: 100px; height: 100px; background-color: yellow; float: right; }
消除浮动
在父级元素样式中添加:
overflow: hidden;
伪元素选择器法:
为父元素添加伪元素选择器
.father::after { content: ""; display: table; clear: both; }
Flex 盒子模型
主要概念:
- 容器(Container):使用
display: flex;
或display: inline-flex;
声明的元素,它将变成一个 Flex 容器。- 项目(Item):容器内的直接子元素,它们自动成为 Flex 项目。
- 轴(Axis):Flexbox 有两个轴,一个是主轴(main axis),另一个是交叉轴(cross axis)。主轴的默认方向是行(row),从左到右布局项目;交叉轴垂直于主轴。
- 对齐(Alignment):Flexbox 提供了丰富的对齐方式,可以对容器内的项目进行水平和垂直对齐
1.
flex-direction
属性用于决定主轴的方向(即项目的排列方向)
属性值 含义 row(默认值)
主轴为水平方向,起点在左端(项目从左往右排列) row-reverse
主轴为水平方向,起点在右端(项目从右往左排列) column
主轴为垂直方向,起点在上沿(项目从上往下排列) column-reverse
主轴为垂直方向,起点在下沿(项目从下往上排列) 2.
flex-wrap
属性用于决定换行方式
属性值 含义 nowrap(默认值)
不换行或列 wrap
主轴为横向时,从上到下换行
主轴为纵向时,从左到右换行wrap-reverse
主轴为横向时,从下到上换行
主轴为纵向时,从右到左换行
flex-flow
是一个复合属性,是flex-direction
与flex-wrap
属性的简写。3.
justify-content
属性决定项目在主轴上的对齐方式
属性值 含义 flex-start(默认值)
与主轴的起点对齐 flex-end
与主轴的终点对齐 center
与主轴的中点对齐 space-betweed
两端对齐主轴的起点与终点,项目之间的间隔都相等 space-around
每个项目两侧的间隔相等,项目之间的间隔比项目与边框的间隔大一倍 4.
align-items
属性用于定义项目在交叉轴上如何对齐
属性值 含义 flex-start
交叉轴的起点对齐 flex-end
交叉轴的终点对齐 center
交叉轴的中点对齐 baseline
项目的第一行文字的基线对齐 stretch(默认值)
如果项目中未设置高度或设为 auto
,项目将占满整个容器的高度。5.
align-content
属性该属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。
属性值 含义 flex-start
与交叉轴的起点对齐 flex-end
与交叉轴的终点对齐 center
与交叉轴的中点对齐 space-between
与交叉轴两端对齐,轴线之间的间隔平均分布 space-around
每根轴线两侧的间隔都相等,轴线之间的间隔比轴线与边框的间隔大一倍 stretch(默认值)
主轴线占满整个交叉轴 示例
.container { display: flex; background-color: aqua; flex-direction: colum; } .container { display: flex; justify-content: space-around; } .item { flex: 1; } .container { display: flex; flex-direction: column; align-items: center; }
案例练习 — — 个人博客设计
blog.html
DOCTYPE html> html lang="en"> head> meta charset="UTF-8"> meta name="viewport" content="width=device-width, initial-scale=1.0"> title>Personal Blogtitle> link rel="stylesheet" href="blog.css"> head> body> header class="site-header"> nav class="main-nav"> ul> li>a href="#home">Homea>li> li>a href="#about">Abouta>li> li>a href="#archive">Archivea>li> li>a href="#contact">Contacta>li> ul> nav> header> section class="hero"> div class="hero-content"> h1>Welcome to My Blogh1> p>A place to share thoughts, ideas, and experiences.p> a href="#posts" class="btn">Explore Postsa> div> section> main class="site-content"> section class="posts"> article class="post"> img src="Forest.png" alt="Post Image" class="post-img"> h2 class="post-title">Post Title Hereh2> p class="post-excerpt">Lorem ipsum dolor sit amet, consectetur adipiscing elit...p> a href="#" class="btn">Read Morea> article> section> aside class="sidebar"> div class="sidebar-widget"> h3>Categoriesh3> ul> li>a href="#">Technologya>li> li>a href="#">Lifestylea>li> li>a href="#">Travela>li> ul> div> div class="sidebar-widget"> h3>Latest Postsh3> ul> li>a href="#">Post Title Onea>li> li>a href="#">Post Title Twoa>li> li>a href="#">Post Title Threea>li> ul> div> div class="sidebar-widget"> h3>Tagsh3> div class="tags"> span class="tag">CSSspan> span class="tag">HTMLspan> span class="tag">JavaScriptspan> div> div> aside> main> section class="comments-section" id="comments"> h2>Leave a Commenth2> form class="comment-form"> label for="name">Name:label> input type="text" id="name" placeholder="Your name" required> label for="email">Email:label> input type="email" id="email" placeholder="Your email" required> label for="comment">Comment:label> textarea id="comment" placeholder="Your comment" required>textarea> button type="submit" class="btn">Submit Commentbutton> form> section> footer class="site-footer"> p>© 2024 Personal Blog. All rights reserved.p> footer> body> html>
blog.css
body, h1, h2, h3, p, ul, li, figure, figcaption { margin: 0; padding: 0; } body { font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; color: #333; } a { text-decoration: none; color: #333; } a.btn { display: inline-block; padding: 0.5rem 1rem; background: #007BFF; color: #fff; border-radius: 5px; transition: background 0.3s; } a.btn:hover { background: #0056b3; } .site-header { background: #fff; padding: 1rem; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .main-nav ul { list-style: none; display: flex; justify-content: space-around; align-items: center; } .hero { background: url('Forest.png') no-repeat center center/cover; color: #fff; height: 60vh; display: flex; align-items: center; justify-content: center; } .hero-content { text-align: center; } .site-content { display: grid; grid-template-columns: 3fr 1fr; gap: 1rem; padding: 2rem; } .post { background: #fff; padding: 1rem; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .post-img { width: 100%; height: 200px; object-fit: cover; border-radius: 5px; } .sidebar-widget { margin-bottom: 2rem; } .tags .tag { display: inline-block; background: #007BFF; color: #fff; padding: 0.3rem 0.8rem; border-radius: 1rem; margin-right: 0.5rem; margin-bottom: 0.5rem; } .comment-form { background: #f9f9f9; padding: 2rem; border-radius: 5px; box-shadow: 0 2px 4px rgba(0,0,0,0.1); } .comment-form label { display: block; margin-bottom: 0.5rem; } .comment-form input, .comment-form textarea { width: 100%; padding: 0.5rem; margin-bottom: 1rem; border-radius: 5px; border: 1px solid #ddd; } .site-footer { background: #333; color: #fff; text-align: center; padding: 1rem 0; } @media (max-width: 768px) { .site-content { grid-template-columns: 1fr; } .sidebar-widget { margin-bottom: 1rem; } } .post-title::before { content: "Post Title Generated by CSS"; } .post-excerpt::before { content: "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."; } .tag::before { content: "Tag"; }
JS(JavaScript)
JavaScript 是一种脚本语言,通常用于网页上实现交互功能,也可以用于服务器端(如 Node.js)。
JavaScript 的作用
- 客户端脚本:用于再用户浏览器中执行,实现动态效果和用户交互。
- 网页开发:与
HTML
和CSS
协同工作,使得网页具有更强的交互性和动态性。- 后端开发:使用
Node.js
,JavaScript
也可以再服务器端运行,实现服务器端应用的开发JS 的导入方式
内联样式:
直接在
或
标签中写
标签,然后在
标签中写入执行语句。
DOCTYPE html> html lang="en"> head> meta charset="UTF-8"> meta name="viewport" content="width=device-width, initial-scale=1.0"> title>Documenttitle> head> body> script>console.log("Hello, JS!");script> script>alert("你好,内联样式弹窗!");script> body> html>
外联样式:
写一个
js
文件,然后在js
文件中写执行执行语句,然后再在HTML
文件中的中使用
导入即可。
head> script src="xxx.js">script> head>
变量
var x; let y = 5; const PI = 3.14; let name = '张三'; let empty_value = null; var bool_1 = false; var bool_2 = Boolean(1); var arr = [1, 2, 3]; var obj = {name: "张三"};
var
与let
的区别:
var
与let
都用于声明变量,并且都可以进行赋初值,var
与let
的主要区别在于作用域,var
具有函数作用域,let
具有块级作用域,通常定义变量的时候,使用let
来声明变量是更安全的。条件语句
if(condition1) { ...; } else if(condition2){ ...; } else { ...; }
例:
let score = 79; if(score >= 90){ console.log("评级为:A"); } else if(80 score 90){ console.log("评级为:B"); } else if(70 score 80){ console.log("评级为:C"); } else{ console.log("评级为:D"); }
循环语句
for
循环:for (初始化条件表达式;循环条件;迭代器){ ...; }
while
循环:while (循环条件) { ...; }
break
:用于结束循环;
continue
:用于跳出当前循环,继续执行下一次的循环;例:
const number = 100; let ans_ou = 0; let ans_ji = 0; for(let i = 1; i number; i++){ if(i % 2 == 0){ ans_ou += i; continue; } ans_ji += i; } console.log(number,"以及的奇数之和为:", ans_ji); console.log(number,"以及的偶数之和为:", ans_ou);
const border = 100; let num = 2; let ans_z = [2]; while(num border){ let num_sq = Math.ceil(Math.sqrt(num)); let num_i = 2; while(num_i num_sq){ if(num % num_i == 0){ break; } num_i ++; } if(num_i > num_sq) ans_z.push(num); num ++; } console.log(ans_z)
函数
function 函数名 ( 参数1, 参数2, 参数3, ...) { ...; return 返回值; }
例:
function factorial(n) { if (n === 0) return 1; return n * factorial(n - 1); } console.log(factorial(5));
事件
常用事件
函数名称 触发条件 onclick
点击事件 onmouseover
鼠标经过 onchange
文本内容改变事件 onselect
文本框选中 onfocus
光标聚集 onblur
移开光标 onkeydown
键盘按键被按下 onkeyup
键盘按键被释放 button onclick="alert('Button was clicked!')">Click Mebutton> input type="text" onkeydown="alert('Key was pressed!')">
事件绑定
HTML
属性DOM
属性addEventListerner
方法HTML 属性
button onclick="click_event()">事件button> script> function click_evnet(){ alert("点击事件触发了"); } script>
DOM 属性
DOM,全称为文档对象模型(Document Object Model),是一种编程接口,用于将网页结构化表示为一个树形结构,从而允许 Web 页面的脚本(如 JavaScript)能够动态地访问和更新网页的内容、结构和样式。
DOM
允许开发者通过JS
与HTML
文档进行交互,动态的改变文档的结构、样式和内容。script> var element_id = document.getElementById('value'); var element_class = document.getElementByClassName('value'); var element_tag = document.getElementByTagName('value')[n]; element_id.innerHTML = 'value'; element_calss.innerText = 'value'; element_tag.style.color = 'red'; element_tag.style.fontSize = '20px'; script>
DOM 绑定事件
button_element.onclick = function(){ alert('value'); } button_element.addEventListerner('click', function(){ alert("value"); })
DOM 对象常用方法
函数名称 含义 appendChild()
把新的子节点添加到指定节点 removeChild()
删除子节点 replaceChile()
替换子节点 insertBefore()
在指定的节点前面插入新的子节点 createAttribute()
创建属性节点 createElement()
创建元素节点 createTexNode()
创建文本节点 getAttribute()
返回指定的属性值 响应式布局实现方式
- 通过
rem
,vm/vh
等单位,实现在不同设备上显示相同比例而实现适配。- 响应式布局,通过媒体查询
@media
实现一套HTML
配合多套CSS
实现适配第一种实现方式
rem
是一个倍数单位,它是基于html
标签中的font-size
属性值的倍数。style> .box-rem { width: 5rem; height: 3rem; background-color: aqua; } style> script> function resetHtmlFontSize(){ document.documentElement.style.fontSize = screen.width / 10 + 'px'; } resetHtmlFontSize(); window.onresize = resetHtmlFontSize; script>
第二种实现方式
标签中的
viewport
meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale = 1.0, maximun-scale = 1.0, user-scalable = no">
width=device-width
:将视口的宽度设置为设备的宽度。这确保网页内容不会被缩放,而是按照设备的实际宽度进行布局。initial-scale=1.0
:设置初始的缩放级别为1.0
。这也有助于确保网页在加载时以原始大小显示,而不是被缩放。minimum-scale = 1.0
:最小缩放比例为1.0
。maximun-scale = 1.0
:最大缩放比例为1.0
。user-scalable = no
:不允许用户缩放。案例三 — — 计数器
index.html
DOCTYPE html> html lang="en"> head> meta charset="UTF-8"> meta name="viewport" content="width=device-width, initial-scale=1.0"> title>计数器title> link rel="stylesheet" href="count.css"> head> body> div class="counter-container"> h1>计数器h1> div class="counter"> button class="decrement-btn">-button> span class="counter-value">0span> button class="increment-btn">+button> div> div> script src="count.js">script> body> html>
count.css
* { margin: 0; padding: 0; box-sizing: border-box; } body, html { height: 100%; font-family: 'Arial', sans-serif; display: flex; justify-content: center; align-items: center; background: #f7f7f7; } .counter-container { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); text-align: center; } h1 { color: #333; margin-bottom: 20px; } .counter { display: flex; justify-content: space-around; align-items: center; margin-bottom: 20px; gap: 20px; } .counter-value { font-size: 2em; padding: 10px 20px; border: 1px solid #ddd; border-radius: 5px; width: 100px; text-align: center; margin: 0 10px; } button { padding: 10px 20px; font-size: 1em; color: #fff; background-color: #5cb85c; border: none; border-radius: 5px; cursor: pointer; transition: background-color 0.3s; } button:hover { background-color: #4cae4c; } button:active { background-color: #449d44; } .decrement-btn { background-color: #d9534f; } .decrement-btn:hover { background-color: #c9302c; } .decrement-btn:active { background-color: #ac2925; }
count.js
document.addEventListener('DOMContentLoaded', function() { const counterValue = document.querySelector('.counter-value'); const incrementBtn = document.querySelector('.increment-btn'); const decrementBtn = document.querySelector('.decrement-btn'); let count = 0; incrementBtn.addEventListener('click', function() { count++; counterValue.textContent = count; }); decrementBtn.addEventListener('click', function() { count--; if (count 0) { count = 0; } counterValue.textContent = count; }); });
案例四 — — TODO-LIST
index.html
DOCTYPE html> html lang="en"> head> meta charset="UTF-8"> meta name="viewport" content="width=device-width, initial-scale=1.0"> title>Todo List Apptitle> link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.1/css/all.min.css"> link rel="stylesheet" href="todo.css"> head> body> div id="todo-app" class="container"> h1>Todo Listh1> div class="input-container"> input type="text" id="new-todo" placeholder="Add a new todo..." /> button id="add-todo">Addbutton> div> ul id="todo-list">ul> div> script src="todo.js">script> body> html>
todo.css
body, html { height: 100%; margin: 0; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; background: url('Forest.png') no-repeat center center fixed; background-size: cover; display: flex; align-items: center; justify-content: center; } .container { width: 80%; max-width: 800px; margin: 0 auto; padding: 20px; background: rgba(255, 255, 255, 0.8); border-radius: 8px; box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1); text-align: center; } h1 { color: #333; margin-bottom: 20px; } .input-container { display: flex; justify-content: space-between; margin-bottom: 20px; } #new-todo { padding: 10px; border: 1px solid #ccc; border-radius: 4px; width: 75%; } #add-todo { padding: 10px 20px; background-color: #5cb85c; color: white; border: none; border-radius: 4px; cursor: pointer; transition: background-color 0.3s; } #add-todo:hover { background-color: #4cae4c; } #todo-list { width: 100%; list-style: none; padding: 0; background: rgba(255, 255, 255, 0.9); border-radius: 8px; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); } .todo-item { display: flex; justify-content: space-between; align-items: center; padding: 15px; border-bottom: 1px solid #e6e6e6; background: #f9f9f9; margin: 10px 0; border-radius: 4px; transition: all 0.3s ease; } .todo-item:first-child { margin-top: 0; } .todo-item:last-child { border-bottom: none; } .todo-item:hover { box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); } .todo-item button { background: #e74c3c; color: #ffffff; border: none; font-size: 16px; cursor: pointer; padding: 8px 15px; border-radius: 20px; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; } .todo-item button:hover { background: #c0392b; transform: scale(1.1); } .todo-item button:active { transform: scale(0.9); } .todo-item button:focus { outline: none; box-shadow: 0 0 0 2px #fff, 0 0 0 4px #e74c3c; } .todo-item button:before { content: "Delete"; font-family: 'FontAwesome'; margin-right: 5px; } .completed { text-decoration: line-through; color: #888; }
todo.js
document.addEventListener('DOMContentLoaded', function() { const input = document.getElementById('new-todo'); const addBtn = document.getElementById('add-todo'); const list = document.getElementById('todo-list'); let todos = []; function loadTodos() { const storedTodos = localStorage.getItem('todos'); if (storedTodos) { todos = JSON.parse(storedTodos); todos.forEach(renderTodo); } } function addTodo() { const todoText = input.value.trim(); if (todoText) { const newTodo = { text: todoText, completed: false }; todos.push(newTodo); renderTodo(newTodo); saveTodos(); input.value = ''; } } function renderTodo(todo) { const listItem = document.createElement('li'); listItem.className = 'todo-item'; listItem.textContent = todo.text; const deleteBtn = document.createElement('button'); deleteBtn.className = 'delete-btn'; deleteBtn.innerHTML = ''; deleteBtn.onclick = function() { removeTodo(listItem, todo); }; listItem.appendChild(deleteBtn); listItem.onclick = function() { todo.completed = !todo.completed; listItem.classList.toggle('completed'); saveTodos(); }; list.appendChild(listItem); } function removeTodo(element, todo) { const index = todos.indexOf(todo); todos.splice(index, 1); element.remove(); saveTodos(); } function saveTodos() { localStorage.setItem('todos', JSON.stringify(todos)); } addBtn.addEventListener('click', addTodo); input.addEventListener('keypress', function(event) { if (event.key === 'Enter') addTodo(); }); loadTodos(); });
原文地址: 快速入门 HTML CSS JS(附带简单案例)