搜索框下拉栏
<html><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } ul{ list-style: none; } .search-box{ position: relative; width: 200px; margin: 20px; border-radius: 6px; } .search-box input{ width: 100%; height: 40px; font-size: 16px; line-height: 100%; border: 1px solid #65a8e2; outline: none; padding: 0 6px; border-radius: 6px; transition: all 0.3s; } .result-list{ width: 100%; position: absolute; top: 40px; border: 1px solid #65a8e2; height: auto; border-top: 0; background: rgba(200, 236, 243, 0.7); border-radius: 0 0 6px 6px; display: none; } .result-list li{ height: auto; } .result-list a{ transition: all 0.3s; text-decoration: none; color: #363636; padding: 5px 10px; display: block; font-size: 14px; } .result-list a:hover{ background-color: rgba(210, 210, 210, 0.9); } </style></head><body> <div class="search-box"> <input type="search" placeholder="输入搜索内容"> <ul class="result-list"> <li><a href="#">搜索词1</a></li> <li><a href="#">搜索词2</a></li> <li><a href="#">搜索词3</a></li> <li><a href="#">搜索词4</a></li> <li><a href="#">搜索词5</a></li> <li><a href="#">搜索词6</a></li> </ul> </div> <script> const input = document.querySelector('input'); const list = document.querySelector('.result-list'); input.addEventListener('focus',()=>{ list.style.display = "block"; input.style.borderRadius = '6px 6px 0 0' }); input.addEventListener('blur',()=>{ list.style.display = "none"; input.style.borderRadius = '6px' }); </script></body></html>评论发布、字数统计
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { box-sizing: border-box; }
.comment-box { display: flex; width: 500px; position: relative; transition: all 0.3s; }
.comment-avatar { border-radius: 50%; width: 50px; height: 50px; background: url('https://cdn.qcqx.cn/img/head.webp') no-repeat center / cover; margin-right: 15px; }
#comment-tx { outline: none; border-color: transparent; resize: none; background: #f5f5f5; border-radius: 4px; flex: 1; padding: 10px; transition: all 0.3s; font-size: 12px; height: 60px; }
#comment-tx:focus { border-color: #e4e4e4; background: #fff; height: 85px; }
.comment-box button { background: #00aeec; color: #fff; border: none; border-radius: 4px; margin-left: 10px; width: 70px; cursor: pointer; transition: all 0.3s; }
.comment-count { width: 500px; height: auto; display: flex; justify-content: flex-end; }
.comment-count span { margin-right: 80px; color: #999; margin-top: 5px; transition: all 0.3s; opacity: 0; }
.content-list { display: flex; width: 500px; position: relative; transition: all 0.3s; flex-direction: column; flex-wrap: nowrap; }
.content-item { display: flex; border-bottom: 1px solid #e4e4e4; padding-bottom: 10px; flex-direction: row; flex-wrap: wrap; align-items: flex-start; margin-bottom: 15px; }
.content-avatar { border-radius: 50%; width: 50px; height: 50px; background: url('https://cdn.qcqx.cn/img/head.webp') no-repeat center / cover; margin-right: 15px; }
.content-warp { width: calc(100% - 65px); padding-right: 8px; }
.content-name { font-size: 16px; margin-bottom: 6px; }
.content-comment { font-size: 18px; white-space: normal; word-break: break-all; word-wrap: break-word; text-overflow: ellipsis; } </style></head>
<body> <div class="comment-box"> <div class="comment-avatar"></div> <textarea id="comment-tx" placeholder="发一条友善的评论,回车发布评论" maxlength="200"></textarea> <button>发布</button> </div> <div class="comment-count"> <span>0/200字</span> </div> <div class="content-list"> <div class="content-item"> <div class="content-avatar"></div> <div class="content-warp"> <div class="content-name">chuckle</div> <div class="content-comment">评论一</div> </div> </div> <div class="content-item"> <div class="content-avatar"></div> <div class="content-warp"> <div class="content-name">chuckle</div> <div class="content-comment">22222222222222222222222222222222222222222222222222222222222222222222222222 </div> </div> </div> </div> <script> // 评论输入框 const count = document.querySelector('.comment-count span'); const tx = document.querySelector('#comment-tx'); tx.addEventListener('focus', () => { count.style.opacity = 1; }); tx.addEventListener('blur', () => { count.style.opacity = 0; }); tx.addEventListener('input', () => { count.innerHTML = `${tx.value.length}/200字` }); // 评论展示 const contentList = document.querySelector('.content-list'); function applyComment() { let comment = tx.value; let html = `<div class="content-item"> <div class="content-avatar"></div> <div class="content-warp"> <div class="content-name">chuckle</div> <div class="content-comment">${comment}</div> </div> </div>`; contentList.insertAdjacentHTML('afterbegin', html); } tx.addEventListener('keyup', (e) => { if (e.key == 'Enter') { if (tx.value.trim()) { applyComment(); } tx.value = ''; count.innerHTML = `${tx.value.length}/200字` } }) const button = document.querySelector('.comment-box button'); button.addEventListener('click', () => { if (tx.value.trim()) { applyComment(); } tx.value = ''; count.innerHTML = `${tx.value.length}/200字` }) </script></body></html>轮播图
当然还是直接用插件方便swiper
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .rot-box { max-width: 560px; height: 400px; overflow: hidden; border-radius: 12px; box-shadow: 0 3px 8px 6px rgba(7, 17, 27, 0.05); margin: 10px; }
.rot-img { width: 100%; height: 80%; display: flex; flex-direction: row; flex-wrap: wrap; justify-content: center; position: relative; }
.rot-img img { width: 100%; height: 100%; object-fit: cover; }
.rot-footer { height: 20%; background-color: rgb(100, 67, 68); padding: 12px 12px 0 12px; position: relative; }
.rot-toggle { position: absolute; right: 10px; top: 15px; display: flex; }
.rot-toggle button { margin-right: 12px; width: 28px; height: 28px; appearance: none; border: none; background: rgba(255, 255, 255, 0.1); color: #fff; border-radius: 4px; cursor: pointer; transition: all 0.3s; }
.rot-toggle button:hover { background: rgba(255, 255, 255, 0.2); }
.rot-title { margin: 0; color: #fff; font-size: 18px; margin-bottom: 10px; margin-left: 10px; }
ul.rot-select { margin: 0; padding: 0; list-style: none; display: flex; align-items: center; margin-left: 10px; height: 12px; }
ul.rot-select li { width: 8px; height: 8px; margin: 4px; border-radius: 50%; background: #fff; opacity: 0.4; cursor: pointer; transition: all 0.3s; }
ul.rot-select li.active { width: 12px; height: 12px; opacity: 1; } @media screen and (max-width:500px) { .rot-box { height: 320px; } } </style></head>
<body> <div class="rot-box"> <div class="rot-img"> <img src="https://cdn.qcqx.cn/images/41-1.webp"> </div> <div class="rot-footer"> <div class="rot-title">标题零</div> <ul class="rot-select"> <li class="active"></li> </ul> <div class="rot-toggle"> <button class="rot-prev"><</button> <button class="rot-next">></button> </div> </div> </div> <script> const rotDate = [ { url: 'https://cdn.qcqx.cn/images/43-1.webp', title: '标题一' }, { url: 'https://cdn.qcqx.cn/images/42-1.webp', title: '标题二' }, { url: 'https://cdn.qcqx.cn/images/41-1.webp', title: '标题三' }, { url: 'https://cdn.qcqx.cn/images/38-1.webp', title: '标题四' }, { url: 'https://cdn.qcqx.cn/images/39-1.webp', title: '标题五' }, ]; //生成[0,arr长度)的随机整数 function getRandom(arr) { return parseInt(Math.random() * arr.length); } const rotSelect = document.querySelector('.rot-select'); // 数组中有多少对象加几个li rotSelect.innerHTML = '';// 先清空ul的内容 for (let i = 0; i < rotDate.length; i++) { rotSelect.innerHTML += '<li></li>'; } //让第一个li变成小白点 document.querySelector('.rot-select li:first-child').classList.toggle('active'); // 一开始随机选一张 // 获取要操作的元素 const img = document.querySelector('.rot-img img'); const title = document.querySelector('.rot-title'); const rot_li = document.querySelectorAll('.rot-select li'); // 数据数组长度 const dateLength = rotDate.length; // 轮播展示序号,默认第一个 var num = 0; // 轮播的对象,默认第一个 var rot = rotDate[num]; // 修改轮播容器的内容 function applyDate() { //换标题和图片 rot = rotDate[num]; img.src = rot.url; title.innerHTML = rot.title; //移除之前的小白点,给当前li添加小白点 if (document.querySelector('.rot-select .active')) { document.querySelector('.rot-select .active').classList.remove('active'); } rot_li[num].classList.toggle('active'); } // 随机展示一个 function ranDate(){ var random = getRandom(rotDate); rot = rotDate[random]; num = random; applyDate(); } // 上一张 function prevDate() { num > 0 ? --num : num = dateLength - 1; applyDate(); } // 下一张 function nextDate() { //控制下一张是哪个 num = ++num % dateLength; applyDate(); } //获取两个按钮 const rotPrev = document.querySelector('.rot-prev'); const rotNext = document.querySelector('.rot-next'); //注册事件 rotPrev.addEventListener('click', () => { prevDate(); }) rotNext.addEventListener('click', () => { nextDate(); }) // 点击小圆点切换展示 rot_li.forEach((item, index, arr) => { item.addEventListener('click', () => { //让轮播展示序号变为当前点击的li的序号 num = index; applyDate(); }); }); // 鼠标悬停停止轮播 const rotBox = document.querySelector('.rot-box'); rotBox.addEventListener('mouseenter',()=>{ clearInterval(itv); console.log('暂停轮播'); }); // 鼠标移出恢复轮播 rotBox.addEventListener('mouseleave',()=>{ //未确保不重复定时,先清除一次 clearInterval(itv); itv = setInterval(nextDate, 1000); console.log('恢复轮播'); }); // 一开始随机展示一个,注释掉则默认展示第一个 //ranDate(); // 定时器轮播 var itv = setInterval(nextDate, 1000);
</script></body></html>tab切换
1、for循环注册鼠标悬停版:
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
.tab-box { width: 500px; border-radius: 6px; overflow: hidden; }
.tab-nav { width: 100%; height: 40px; display: flex; background: rgb(233, 233, 233); justify-content: center; border-bottom: 1px solid #333; }
.tab-nav ul { list-style: none; display: flex; align-items: flex-end; }
.tab-nav ul li { margin: 0 5px; padding: 2px 15px 0; font-size: 18px; border-radius: 6px 6px 0 0; transition: all 0.3s; border-bottom: 1px solid #333; margin-bottom: -1px; } .tab-nav ul li.active { background: rgb(220, 220, 220); border-bottom: 1px solid rgb(220, 220, 220); } .tab-nav ul li a { text-decoration: none; color: #333; height: 30px; display: block; }
.tab-content { width: 100%; height: 100px; background: rgb(220, 220, 220); } .tab-item{ display: none; } .tab-item.active{ display: block; text-align: center; padding: 10px; font-size: 20px; } </style></head>
<body> <div class="tab-box"> <div class="tab-nav"> <ul> <li class="active"><a href="javascript:;">栏1</a></li> <li><a href="javascript:;">栏2</a></li> <li><a href="javascript:;">栏3</a></li> <li><a href="javascript:;">栏4</a></li> <li><a href="javascript:;">栏5</a></li> </ul> </div> <div class="tab-content"> <div class="tab-item active">项目一</div> <div class="tab-item">项目二</div> <div class="tab-item">项目三</div> <div class="tab-item">项目四</div> <div class="tab-item">项目五</div> </div> </div> <script> const tabNav = document.querySelectorAll('.tab-nav ul li'); const tabItem = document.querySelectorAll('.tab-item'); tabNav.forEach((item,index)=>{ item.addEventListener('mouseenter',()=>{ document.querySelector('.tab-nav .active').classList.remove('active'); document.querySelector('.tab-content .active').classList.remove('active'); item.classList.add('active'); tabItem[index].classList.add('active'); }); }); </script></body><div id="tab-sandbox"></div></html>2、事件委托鼠标点击版:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
.tab-box { width: 500px; border-radius: 6px; overflow: hidden; margin: 10px; }
.tab-nav { width: 100%; height: 40px; display: flex; background: rgb(233, 233, 233); justify-content: center; border-bottom: 1px solid #333; }
.tab-nav ul { list-style: none; display: flex; align-items: flex-end; }
.tab-nav ul li { margin: 0 5px; font-size: 18px; border-bottom: 1px solid transparent; margin-bottom: -1px; }
.tab-nav ul li a.active { background: rgb(220, 220, 220); border-bottom: 1px solid rgb(220, 220, 220); }
.tab-nav ul li a { text-decoration: none; color: #333; height: 33px; display: block; padding: 2px 15px; border-radius: 6px 6px 0 0; transition: all 0.3s; }
.tab-content { width: 100%; height: 100px; background: rgb(220, 220, 220); }
.tab-item { display: none; }
.tab-item.active { display: block; text-align: center; padding: 10px; font-size: 20px; } </style></head>
<body> <div class="tab-box"> <div class="tab-nav"> <ul> <li><a href="javascript:;" data-id="0" class="active">栏1</a></li> <li><a href="javascript:;" data-id="1">栏2</a></li> <li><a href="javascript:;" data-id="2">栏3</a></li> <li><a href="javascript:;" data-id="3">栏4</a></li> <li><a href="javascript:;" data-id="4">栏5</a></li> </ul> </div> <div class="tab-content"> <div class="tab-item active">项目一</div> <div class="tab-item">项目二</div> <div class="tab-item">项目三</div> <div class="tab-item">项目四</div> <div class="tab-item">项目五</div> </div> </div> <script> const tabNav = document.querySelector('.tab-nav ul'); const tabItem = document.querySelectorAll('.tab-item'); //利用事件委托减少注册 tabNav.addEventListener('click', (e) => { let tag = e.target.tagName; if (tag === 'A') { document.querySelector('.tab-nav .active').classList.remove('active'); document.querySelector('.tab-content .active').classList.remove('active'); e.target.classList.add('active'); tabItem[e.target.dataset.id].classList.add('active') } }); </script></body>
</html>表单全选反选
<!DOCTYPE html><html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
table { border-collapse: collapse; border-spacing: 0; border: 1px solid #c0c0c0; width: 500px; text-align: center; }
th { background-color: rgb(40, 170, 220); font: bold 16px; color: #fff; height: 22px; } td { border: 1px solid #d0d0d0; color: #363636; padding: 6px 10px; background: #f9f9f9; } tr td:not(:first-child){ min-width: 50px; } tr th:first-child{ width: 70px; } </style></head>
<body> <table> <tr> <th> <input type="checkbox" id="check-all"> <span>全选</span> </th> <th>书名</th> <th>作者</th> <th>价格</th> </tr> <tr> <td> <input type="checkbox" class="check-one"> </td> <td>毛泽东选集</td> <td>毛泽东</td> <td>56</td> </tr> <tr> <td> <input type="checkbox" class="check-one"> </td> <td>资本论</td> <td>马克思</td> <td>129</td> </tr> <tr> <td> <input type="checkbox" class="check-one"> </td> <td>三体</td> <td>刘慈欣</td> <td>46</td> </tr> </table> <script> const checkAll = document.querySelector('#check-all'); const checks = document.querySelectorAll('.check-one'); checkAll.addEventListener('click',()=>{ checks.forEach((item)=>{ item.checked = checkAll.checked; }); }); checks.forEach((item)=>{ item.addEventListener('click',()=>{ checkAll.checked = document.querySelectorAll('.check-one:checked').length === checks.length; }) }) </script></body>
</html>导航栏、电梯导航、哔哩tab
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { padding-bottom: 500px; }
.tab-box { width: 500px; height: auto; border-radius: 6px; overflow: hidden; margin: 10px; }
.tab-nav { display: flex; list-style: none; border-bottom: 1px solid #333; background: rgb(233, 233, 233); height: 40px; flex-direction: row; flex-wrap: nowrap; justify-content: center; align-items: center; position: relative; }
.tab-nav a { margin: 5px; padding: 0 10px; text-decoration: none; color: #000; height: 40px; line-height: 40px; }
.tab-nav a.active { color: rgb(23, 180, 215); }
.tab-bar { position: absolute; width: 40px; height: 3px; background: rgb(23, 180, 215); bottom: -1px; transition: all 0.3s; }
.item-box { background: rgb(220, 220, 220); }
.item { text-align: center; padding: 10px; display: none; }
.item.active { display: block; height: 100px; }
/* 导航栏 */ #nav { width: 100%; height: 50px; text-align: center; line-height: 50px; background: rgba(120, 182, 191, 0.5); font-size: 20px; position: fixed; top: -50px; transition: all 0.3s; z-index: 9999; }
.box { margin-top: 10px; width: 200px; height: 200px; background: rgb(144, 193, 230); margin-bottom: 200px; border-radius: 6px; }
/* 电梯导航 */ .ele-nav { position: fixed; bottom: 20%; background: rgb(233, 233, 233); right: 10%; border: 1px solid #333; border-bottom: 0; border-radius: 6px; overflow: hidden; transition: all 0.3s; opacity: 0; z-index: -99; } .ele-item.active{ color: rgb(23, 180, 215); background: rgb(252, 200, 200); } .ele-item, .back-top { padding: 10px; border-bottom: 1px solid #333; user-select: none; transition: all 0.3s; } .ele-item:hover, .back-top:hover{ color: rgb(23, 180, 215); } </style></head>
<body> <div id="nav">导航栏</div> <div class="tab-box"> <div class="tab-nav"> <a href="javascript:;" class="active">栏1</a> <a href="javascript:;">栏2</a> <a href="javascript:;">栏3</a> <a href="javascript:;">栏4</a> <a href="javascript:;">栏114514</a> <div class="tab-bar"></div> </div>
<div class="item-box"> <div class="item active">项目一</div> <div class="item">项目二</div> <div class="item">项目三</div> <div class="item">项目四</div> <div class="item">项目114514</div> </div> </div> <div class="ele-nav"> <div class="ele-item">去第一个</div> <div class="ele-item">去第二个</div> <div class="ele-item">去第三个</div> <div class="ele-item">去第四个</div> <div class="back-top">回到顶部</div> </div> <div class="box">第一个盒子,滚动到此(往上55像素)显示导航栏和电梯导航</div> <div class="box">第二个盒子</div> <div class="box">第三个盒子</div> <div class="box">第四个盒子</div> <script> //网页导航栏,还有电梯导航的显示和隐藏 const nav = document.querySelector('#nav'); const box = document.querySelectorAll('.box'); const ele_nav = document.querySelector('.ele-nav'); window.addEventListener('scroll', () => { let n = window.scrollY; let m = box[0].offsetTop; let tf = n >= m-55;//减去55像素,不让电梯导航点击去第一个后消失 nav.style.top = tf ? '0px' : '-50px'; ele_nav.style.opacity = tf ? '1' : '0'; ele_nav.style.zIndex = tf ? '99' : '-99'; }); //bilibili导航 const bar = document.querySelector('.tab-bar'); const tabNav = document.querySelector('.tab-nav'); const tab_a = document.querySelectorAll('.tab-nav a'); const item = document.querySelectorAll('.item-box .item'); //给每个a依次添加data-id tab_a.forEach((item, index) => { item.dataset.id = index; }); //将a的点击事件委托给tab-nav tabNav.addEventListener('click', (e) => { let tag = e.target.tagName; if (tag === 'A') { //tab导航切换 document.querySelector('.tab-nav a.active').classList.remove('active'); document.querySelector('.item.active').classList.remove('active'); e.target.classList.add('active'); item[e.target.dataset.id].classList.add('active'); //bar移动和动态改变宽度 bar.style.width = `${e.target.offsetWidth}px`; bar.style.left = `${e.target.offsetLeft}px`; } }); tab_a[0].click();//先初始化一次bar的位置 //电梯导航 //给每个电梯导航依次添加data-name document.querySelectorAll('.ele-item').forEach((item, index) => { item.dataset.name = `b${index+1}`; }); //给每个box依次添加电梯导航对应的自定义属性的class box.forEach((item, index) => { item.classList.add(`b${index+1}`); }); //移除ele的active function reactive(){ let ele_active = document.querySelector('.ele-item.active'); if(ele_active){ //如果有,先清除 ele_active.classList.remove('active'); } } //去指定盒子,事件委托 ele_nav.addEventListener('click', (e) => { let cname = e.target.className; if (cname === 'ele-item'||cname === 'ele-item active') { reactive(); //给点击的item添加active e.target.classList.add('active'); //去对应的盒子 //通过自定义属性获取对应的盒子class名 let box = document.querySelector(`.${e.target.dataset.name}`); // 其实监听滚动后,没必要再手动去给active,但想点击后导航立刻变色的话,可以取消下面的注释 // //先立刻移除页面滚动监听 // window.removeEventListener('scroll', scroll_light_ele); // //一秒后重新监听 // setTimeout(() => { // //防止重复注册,先移除页面滚动监听 // window.removeEventListener('scroll', scroll_light_ele); // window.addEventListener('scroll', scroll_light_ele); // }, 800); //更新当前页面在哪个盒子的范围位置 box_num = e.target.dataset.name.replace(/[^\d]/g, " "); //滚动到指定位置 window.scrollTo({ top: box.offsetTop - 50, left: 0, behavior: 'smooth' }); } //点击返回顶部 if (cname === 'back-top') { reactive(); window.scrollTo({ top: 0, left: 0, behavior: 'smooth' }); box_num = -1; } }); //获取盒子的高度数组减去55px const box_top_arr = Array.from(box).map((item)=>{ return item.offsetTop-55; }) var box_num = -1;//记录当前在哪个盒子范围内 //页面滚动到对应box让电梯导航对应导航高亮 function scroll_light_ele(){ let n = window.scrollY; let num = box_top_arr.reduce((prev, item, index)=>{ return n >= item ? index : prev; },-1); if(num === box_num){ //说明还在这个盒子范围内,直接返回 return; }else{ //更新位置 box_num = num; } if(num > -1){ reactive(); document.querySelector(`[data-name="b${num+1}"]`).classList.add('active'); }else{ box_num = -1; } } window.addEventListener('scroll', scroll_light_ele); </script></body>
</html>倒计时
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { padding: 0; margin: 0; box-sizing: border-box; }
.time-box { padding: 20px 15px; background: rgb(30, 171, 210); width: fit-content; border-radius: 6px; overflow: hidden; margin: 10px; font-size: 18px; }
.time-now { width: 100%; text-align: center; }
.time-title { font-size: 26px; text-align: center; width: 100%; margin: 6px 0; }
.clock { display: flex; width: 100%; justify-content: center; flex-direction: row; flex-wrap: wrap; align-content: center; margin: 10px 0; } .hour,.minutes,.second{ font-size: 20px; margin: 2px; padding: 2px 3px; border-radius: 4px; background: rgba(36, 36, 36, 0.65); color: #fff; } .colon{ font-size: 20px; font-weight: bolder; padding: 2px; } .target{ width: 100%; text-align: center; margin: 6px 0 0; } </style></head>
<body> <div class="time-box"> <div class="time-now">今天是1970年1月1日</div> <div class="time-title">倒计时</div> <div class="clock"> <div class="hour">00</div> <div class="colon">:</div> <div class="minutes">00</div> <div class="colon">:</div> <div class="second">00</div> </div> <div class="target">目标时间00:00:00</div> </div>
<script> const hour = document.querySelector('.hour'); const minutes = document.querySelector('.minutes'); const second = document.querySelector('.second'); const time_now = document.querySelector('.time-now'); const target = document.querySelector('.target'); const now = new Date(); const time = '18:00:00'; const targetTime = `${now.getFullYear()}-${now.getMonth() + 1}-${now.getDate()} 18:00:00`; const last = new Date(targetTime); let count = (last.getTime() - now.getTime()) / 1000; function countDown() { let h = parseInt(count / 60 / 60 % 24); h = h < 10 ? '0' + h : h; let m = parseInt(count / 60 % 60); m = m < 10 ? '0' + m : m; let s = parseInt(count % 60); s = s < 10 ? '0' + s : s; hour.innerHTML = h; minutes.innerHTML = m; second.innerHTML = s; count--; if (count == 0) { count = 0; } } time_now.innerHTML = `今天是${now.getFullYear()}年${now.getMonth() + 1}月${now.getDate()}日`; target.innerHTML = `目标时间${time}` countDown(); setInterval(countDown, 1000); </script></body>
</html>学生信息表
学生信息表(旧演示页已随 Hexo 站迁移下线)
本地存储,数据驱动,刷新不丢失
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
a { text-decoration: none; color: rgb(226, 14, 14); }
.info-box { width: 800px; margin: 0 auto; position: relative; }
h1 { text-align: center; margin: 20px; user-select: none; }
.info { width: 100%; text-align: center; margin: 40px 0; }
.ipt-name { width: fit-content; display: inline-block; line-height: 25px; font-size: 16px; }
.info input, .info select { width: 70px; outline: none; border-radius: 5px; border: 1px solid #b8daff; height: 25px; padding: 0 5px; margin: 0 15px 0 2px; }
input.sname { width: 80px; }
input.age { width: 40px; }
.info button { width: 60px; height: 25px; border-radius: 5px; cursor: pointer; background: rgb(82, 191, 231); outline: none; border: 1px solid rgb(98, 98, 98); color: #fff; font-size: 15px; }
table { margin: 0 auto; width: 100%; padding: 0 20px; color: #363636; border-collapse: collapse; border-spacing: 0; }
th { padding: 5px 10px; background: #cfe5ff; font-size: 20px; font-weight: 400; }
td, th { border: 1px solid #b8daff; }
td { padding: 5px 10px; text-align: center; font-size: 16px; }
tbody tr { background: #fff; }
tbody tr:hover { background: #e1ecf8; } .info-num{ right: 10px; width: fit-content; position: absolute; margin-top: -20px; } </style></head>
<body> <div class="info-box"> <h1>新增学生信息</h1> <form class="info" autocomplete="off"> <div class="ipt-name">姓名</div> <input type="text" class="sname" name="sname"> <div class="ipt-name">年龄</div> <input type="text" class="age" name="age"> <div class="ipt-name">性别</div> <select class="gender" name="gender"> <option value="男">男</option> <option value="女">女</option> </select> <div class="ipt-name">年级</div> <select class="grade" name="grade"> <option value="大一">大一</option> <option value="大二">大二</option> <option value="大三">大三</option> <option value="大四">大四</option> </select> <div class="ipt-name">专业</div> <select class="major" name="major"> <option value="计科">计科</option> <option value="机械">机械</option> <option value="会计">会计</option> </select> <button class="add-info">录入</button> </form> <h1>学生信息</h1> <div class="info-num">共有0条数据</div> <table> <thead> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> <th>年级</th> <th>专业</th> <th>操作</th> </tr> </thead> <tbody></tbody> </table> </div> <script> var arr = [ { name: '张三', age: 19, gender: '男', grade: '大一', major: '计科' }, { name: '李四', age: 18, gender: '男', grade: '大二', major: '机械' }, { name: '李丽', age: 18, gender: '女', grade: '大三', major: '会计' } ]; const info = document.querySelector('.info'); const items = document.querySelectorAll('.info [name]'); const tbody = document.querySelector('tbody'); const infoNum = document.querySelector('.info-num'); info.addEventListener('submit', (e) => { e.preventDefault(); let i = Array.from(items).reduce((prev, item) => { return item.value === '' ? prev : prev += 1; }, 0); console.log(i); if (i != items.length) { return alert('输入内容不能为空'); } let obj = { name: info.children[1].value, age: info.children[3].value, gender: info.children[5].value, grade: info.children[7].value, major: info.children[9].value } console.log(obj); //更新数据 arr.push(obj); //重置表单 info.reset(); //信息本地存储 localStorage.setItem('info', JSON.stringify(arr)); //调用渲染函数 render(); }); function render() { tbody.innerHTML = ''; let trArr = arr.map((item, index) => { return `<tr> <td>${index + 1}</td> <td>${item.name}</td> <td>${item.age}</td> <td>${item.gender}</td> <td>${item.grade}</td> <td>${item.major}</td> <td><a href="javascript:">删除</a></td> </tr>` }); tbody.innerHTML = trArr.join(''); infoNum.innerHTML = `共有${arr.length}条数据`; } //删除,事件委托 tbody.addEventListener('click', (e) => { let target = e.target; if (target.tagName === 'A') { let num = e.target.parentNode.parentNode.firstElementChild.innerHTML //拿到序号,删除一个 let tf = confirm(`确认删除第 ${num} 个学生信息吗?`); if (tf) { arr.splice(num - 1, 1); localStorage.setItem('info', JSON.stringify(arr)); render(); } } }); function infoInit() { //先获取本地数据 let info = JSON.parse(localStorage.getItem('info')); if (info) { arr = info; } render(); } //初始化 infoInit(); </script></body>
</html>注册界面
注册界面(旧演示页已随 Hexo 站迁移下线)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
input { outline: none; }
a { text-decoration: none; }
.reg-box { margin: 0 auto; width: auto; height: auto; background: rgb(244, 242, 242); position: absolute; top: 50%; left: 50%; border-radius: 6px; transform: translate(-50%, -50%); border: 1px solid #e4e4e4; }
.reg-box .reg-title { width: 100%; text-align: center; margin: 15px 0; font-size: 22px; font-weight: bolder; color: #363636; }
.reg-form { margin: 10px; }
.form-item { display: flex; position: relative; width: 300px; flex-direction: row; flex-wrap: wrap; padding-bottom: 25px; justify-content: space-between; letter-spacing: 0.6px; }
.form-item input { width: 100%; border: 1px solid #e4e4e4; height: 40px; font-size: 16px; padding: 10px 16px; border-radius: 6px; }
.form-item .msg { position: absolute; line-height: 1; width: 100%; font-size: 12px; color: rgb(255, 79, 126); bottom: 9px; padding-left: 5px; }
.code-box { display: flex; }
.form-item [name="code"] { flex-shrink: 1; }
.form-item a.code { width: fit-content; height: 40px; line-height: 40px; background: rgb(120, 187, 233); text-align: center; border-radius: 6px; color: #fff; margin-left: 10px; padding: 0 10px; flex-shrink: 0; display: block; transition: all 0.3s; user-select: none; }
.agree-check { margin: 0 auto; width: fit-content; }
.form-item .agree { width: 20px; height: 20px; cursor: pointer; }
.form-item .agree:checked { background: #9decbe; }
.agreement { width: calc(100% - 20px); padding-left: 10px; color: #363636; line-height: 20px; height: 20px; }
.agreement a { color: #6a9adf; }
.reg-submit { margin: 0 auto; display: block; width: calc(100% - 40px); height: 40px; border-radius: 8px; outline: none; border: none; background: #9decbe; font-size: 18px; color: #363636; margin-bottom: 15px; transition: all 0.3s; cursor: pointer; user-select: none; }
.reg-submit:hover { background: #86ebb0; }
.form-item .see { position: absolute; width: fit-content; height: auto; right: 10px; line-height: 1; cursor: pointer; font-size: 14px; top: 12px; color: #ababab; transition: all 0.3s; user-select: none; }
.form-item .see:hover { color: #6a9adf; } </style></head>
<body> <div class="reg-box"> <div class="reg-title">新用户注册</div> <form class="reg-form"> <div class="form-item"> <input name="uname" type="text" placeholder="设置用户名" maxlength="12" autocomplete="off"> <div class="msg"></div> </div> <div class="form-item"> <input name="phone" type="text" placeholder="输入手机号" maxlength="11" autocomplete="off"> <div class="msg"></div> </div> <div class="form-item"> <div class="code-box"> <input name="code" type="text" placeholder="输入验证码" maxlength="6" autocomplete="off"> <div class="msg"></div> <a href="javascript:;" class="code">发送验证码</a> </div> </div> <div class="form-item"> <input name="password" type="password" placeholder="输入密码" maxlength="20" autocomplete="off"> <div class="msg"></div> <div class="see">显示</div> </div> <div class="form-item"> <input class="password-again" type="password" placeholder="再次输入密码" maxlength="20" autocomplete="off"> <div class="msg"></div> <div class="see">显示</div> </div> <div class="form-item agree-check"> <input type="checkbox" class="agree" autocomplete="off"> <div class="msg"></div> <div class="agreement">已阅读并同意<a href="#">《用户协议》</a></div> </div> <button class="reg-submit">提交</button> </form> </div>
<script> const code = document.querySelector('.code-box .code'); var code_flag = true;//控制点击有没有效果 const codeTime = 30;//验证码发送间隔时间,默认30秒 //验证码间隔验证的初始化 function codeInit() { //如果验证码间隔倒计时还没30秒,就继续倒计时 let code_time = localStorage.getItem('code_time'); if (code_time) { let time = codeTime - parseInt((new Date().getTime() - code_time) / 1000); //小于0说明间隔已经满足 if (time > 0) { //执行控制验证码间隔函数 code_limit_time(time); } } // 发送短信验证码 code.addEventListener('click', () => { if (code_flag) { //存入点击发送验证码时的时间戳 localStorage.setItem('code_time', new Date().getTime()); code_flag = false;//可以点击 code_limit_time(); //这里就可以去做请求短信接口 } }); } // 控制验证码发送间隔函数 function code_limit_time(i = codeTime) { code.innerHTML = `${i}秒后重新获取`; code.style.pointerEvents = 'none'; code.style.background = '#c6c6c6'; var stv = setInterval(() => { i--; code.innerHTML = `${i}秒后重新获取`; if (i === 0) { code_flag = true; code.innerHTML = `重新获取`; code.style.pointerEvents = 'auto'; code.style.background = 'rgb(120, 187, 233)'; clearInterval(stv); //倒计时完成移除时间戳 localStorage.removeItem('code_time'); } }, 1000) } //输入框验证函数 function input_verification(input, rex, msg) { let div = input.nextElementSibling; if (rex.test(input.value)) { div.innerHTML = ""; return true; } else { div.innerHTML = msg; return false; } }
// 输入框内容检查 const uname = document.querySelector('.form-item input[name="uname"]'); const phone = document.querySelector('.form-item input[name="phone"]'); const code_input = document.querySelector('.form-item input[name="code"]'); const password = document.querySelector('.form-item input[name="password"]'); const password_again = document.querySelector('input.password-again'); const agree = document.querySelector('.agree-check .agree'); //用户名验证 function inspect_uname() { return input_verification(uname, /^\w{4,12}$/g, "4到12位用户名,只能包含数字、字母、下划线") ? true : false; } //手机号验证 function inspect_phone() { return input_verification(phone, /^1[3-9][0-9]{9}$/g, "11位手机号") ? true : false; } //检查验证码是否是6位数字 function inspect_code() { return input_verification(code_input, /^\d{6}$/g, "6位数字验证码") ? true : false; } //密码验证,开头必须是字母,6到20位 function inspect_password() { return input_verification(password, /^(?=.*[a-z])(?=.*\d)[a-z\d]{6,20}$/gi, "6到20位密码,必须包含数字和字母") ? true : false; } //验证两次密码输入是否相同 function inspect_password_again() { let div = password_again.nextElementSibling; if (password_again.value === password.value) { div.innerHTML = ""; return true; } else { div.innerHTML = "两次密码不一致"; return false; } } // 检查协议是否同意 function inspect_agree() { let div = agree.nextElementSibling; if (agree.checked) { div.innerHTML = ""; return true; } else { div.innerHTML = "请同意协议"; return false; } } //监听各个输入框内容是否改变 uname.addEventListener('change', () => { inspect_uname(); }); phone.addEventListener('change', () => { inspect_phone(); }); code_input.addEventListener('change', () => { inspect_code(); }); password.addEventListener('change', () => { inspect_password(); if (password_again.value) { inspect_password_again(); } }); password_again.addEventListener('change', () => { inspect_password_again(); }); //密码点击查看隐藏 const see_psw = document.querySelectorAll('.form-item .see') see_psw.forEach((item, index) => { item.addEventListener('click', () => { let input = item.parentNode.firstElementChild; if (input.type === "password") { item.innerHTML = "隐藏"; input.type = "text"; } else { item.innerHTML = "显示"; input.type = "password"; } }); }); //点击提交表单 const btn_submit = document.querySelector('.reg-submit'); const reg_form = document.querySelector('.reg-form'); reg_form.addEventListener('submit', (e) => { //提交前再次把所有输入框检查一遍 if (!inspect_uname()) { e.preventDefault(); } if (!inspect_phone()) { e.preventDefault(); } if (!inspect_code()) { e.preventDefault(); } if (!inspect_password()) { e.preventDefault(); } if (!inspect_password_again()) { e.preventDefault(); } if (!inspect_agree()) { e.preventDefault(); } }) //初始化函数 function regInit() { codeInit(); } //执行初始化 regInit(); </script></body>
</html>登陆界面
登录界面(旧演示页已随 Hexo 站迁移下线)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> * { margin: 0; padding: 0; box-sizing: border-box; }
input { outline: none; }
a { text-decoration: none; }
.login-box { margin: 0 auto; width: auto; height: auto; background: rgb(244, 242, 242); position: absolute; top: 50%; left: 50%; border-radius: 6px; transform: translate(-50%, -50%); border: 1px solid #e4e4e4; }
.login-box .login-title { width: 100%; text-align: center; margin: 12px 0; font-size: 22px; font-weight: bolder; color: #363636; }
.login-tab { display: flex; width: 100%; justify-content: center; flex-direction: row; flex-wrap: wrap; align-content: center; align-items: center; user-select: none; }
.login-tab-line { width: 1px; height: 20px; background: rgb(30, 110, 140); }
.login-tab-item { margin: 0px 10px; transition: all 0.2s; }
.login-tab-item.active { color: #4b98db; }
.login-form { margin: 10px; }
.form-item { display: flex; position: relative; width: 300px; flex-direction: row; flex-wrap: wrap; padding-bottom: 25px; justify-content: space-between; letter-spacing: 0.6px; }
.form-item input { width: 100%; border: 1px solid #e4e4e4; height: 40px; font-size: 16px; padding: 10px 16px; border-radius: 6px; }
.form-item .msg { position: absolute; line-height: 1; width: 100%; font-size: 12px; color: rgb(255, 79, 126); bottom: 9px; padding-left: 5px; }
.code-box { display: flex; }
.form-item [name="code"] { flex-shrink: 1; }
.form-item a.code { width: fit-content; height: 40px; line-height: 40px; background: rgb(120, 187, 233); text-align: center; border-radius: 6px; color: #fff; margin-left: 10px; padding: 0 10px; flex-shrink: 0; display: block; transition: all 0.3s; user-select: none; }
.agree-check { margin: 0 auto; width: fit-content; }
.form-item .agree { width: 20px; height: 20px; cursor: pointer; }
.form-item .agree:checked { background: #9decbe; }
.agreement { width: calc(100% - 20px); padding-left: 10px; color: #363636; line-height: 20px; height: 20px; }
.agreement a { color: #6a9adf; }
.login-submit { margin: 0 auto; display: block; width: calc(100% - 40px); height: 40px; border-radius: 8px; outline: none; border: none; background: #9decbe; font-size: 18px; color: #363636; margin-bottom: 15px; transition: all 0.3s; cursor: pointer; user-select: none; }
.login-submit:hover { background: #86ebb0; }
.form-item .see { position: absolute; width: fit-content; height: auto; right: 10px; line-height: 1; cursor: pointer; font-size: 14px; top: 12px; color: #ababab; transition: all 0.3s; user-select: none; }
.form-item .see:hover { color: #6a9adf; }
.login-form { display: none; }
.login-form.active { display: block; } </style></head>
<body> <div class="login-box"> <div class="login-title">登陆</div> <div class="login-tab"> <div class="login-tab-item active" data-id="0">密码登陆</div> <div class="login-tab-line"></div> <div class="login-tab-item" data-id="1">短信登陆</div> </div> <div class="form-box"> <form class="login-form active"> <div class="form-item"> <input name="uname" type="text" placeholder="用户名 / 手机号" maxlength="13" autocomplete="off" required> <div class="msg"></div> </div> <div class="form-item"> <input name="password" type="password" placeholder="密码" maxlength="20" autocomplete="off" required> <div class="msg"></div> <div class="see">显示</div> </div> <button class="login-submit">登录</button> </form> <form class="login-form"> <div class="form-item"> <input name="phone" type="text" placeholder="输入手机号" maxlength="11" autocomplete="off" required> <div class="msg"></div> </div> <div class="form-item"> <div class="code-box"> <input name="code" type="text" placeholder="输入验证码" maxlength="6" autocomplete="off" required> <div class="msg"></div> <a href="javascript:;" class="code">发送验证码</a> </div> </div> <button class="login-submit">登录</button> </form> <div class="form-item agree-check"> <input type="checkbox" class="agree" autocomplete="off"> <div class="msg"></div> <div class="agreement">已阅读并同意<a href="#">《用户协议》</a></div> </div> </div> </div>
<script> const login_tab = document.querySelector('.login-tab'); const login_form = document.querySelectorAll('.login-form'); const code = document.querySelector('.code-box .code'); const agree = document.querySelector('.agree-check .agree'); const uname = document.querySelector('.form-item input[name="uname"]'); const phone = document.querySelector('.form-item input[name="phone"]'); login_tab.addEventListener('click', (e) => { let class_name = e.target.className; if (class_name === 'login-tab-item') { document.querySelector('.login-tab-item.active').classList.remove('active'); e.target.classList.add('active'); //切换登录方式清空input document.querySelectorAll('.login-form.active input').forEach((item) => { item.value = ''; }) document.querySelector('.login-form.active').classList.remove('active'); login_form[e.target.dataset.id].classList.add('active'); } }); //短信模块 var code_flag = true;//控制点击有没有效果 const codeTime = 30;//验证码发送间隔时间,默认30秒 function codeClick() { if (code_flag) { //存入点击发送验证码时的时间戳 localStorage.setItem('code_time', new Date().getTime()); code_flag = false;//可以点击 code_limit_time(); //这里就可以去做请求短信接口 } } //验证码间隔验证的初始化 function codeInit() { //如果验证码间隔倒计时还没30秒,就继续倒计时 let code_time = localStorage.getItem('code_time'); if (code_time) { let time = codeTime - parseInt((new Date().getTime() - code_time) / 1000); //小于0说明间隔已经满足 if (time > 0) { //执行控制验证码间隔函数 code_limit_time(time); } } // 发送短信验证码 code.addEventListener('click', codeClick); } // 控制验证码发送间隔函数 function code_limit_time(i = codeTime) { code.innerHTML = `${i}秒后重新获取`; code.style.pointerEvents = 'none'; code.style.background = '#c6c6c6'; var stv = setInterval(() => { i--; code.innerHTML = `${i}秒后重新获取`; if (i === 0) { code_flag = true; code.innerHTML = `重新获取`; code.style.pointerEvents = 'auto'; code.style.background = 'rgb(120, 187, 233)'; clearInterval(stv); //倒计时完成移除时间戳 localStorage.removeItem('code_time'); } }, 1000) } //密码点击查看隐藏 const see_psw = document.querySelector('.form-item .see') see_psw.addEventListener('click', () => { let input = see_psw.parentNode.firstElementChild; if (input.type === "password") { see_psw.innerHTML = "隐藏"; input.type = "text"; } else { see_psw.innerHTML = "显示"; input.type = "password"; } }); // 检查协议是否同意 function inspect_agree() { console.log(11); let div = agree.nextElementSibling; if (agree.checked) { div.innerHTML = ""; return true; } else { div.innerHTML = "请同意协议"; return false; } } function subInit() { login_form.forEach((item, index) => { item.addEventListener('submit', (e) => { e.preventDefault(); if (!inspect_agree()) { return; } //存储用户名或手机号 localStorage.setItem('user', uname.value||phone.value); //这里作跳转 // location.href = '/' }); }) } //初始化函数 function loginInit() { codeInit(); subInit(); } //执行初始化 loginInit(); </script></body></html>
评论