├── 1.打字特效 ├── index.html └── style.css ├── 10.两种主题的右键菜单 ├── icon │ ├── iconfont.css │ ├── iconfont.js │ ├── iconfont.json │ └── iconfont.ttf ├── index.html ├── script.js └── style.css ├── 11.加载特效(一)—模糊加载效果 ├── index.html └── style.css ├── 12.图片放大镜效果 ├── image │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── 4.jpg │ ├── 5.jpg │ └── 6.jpg ├── index.html ├── script.js └── style.css ├── 13.消失的导航栏-IntersectionObserver ├── image │ ├── bg1.jpg │ ├── bg2.jpg │ ├── bg3.jpg │ └── bg4.jpg ├── index.html ├── script.js └── style.css ├── 14.canvas水印效果 ├── index.html ├── script.js └── style.css ├── 15.MutationObserver变动观察器 ├── index.html ├── script.js ├── script2.js └── style.css ├── 16.音乐播放器-1 ├── font │ └── JosefinSans-Light.ttf ├── icon │ ├── iconfont.css │ ├── iconfont.js │ ├── iconfont.json │ └── iconfont.ttf ├── image │ ├── 1.jpg │ ├── 2.jpg │ ├── 3.jpg │ ├── bg1.jpg │ └── bg2.jpg ├── index.html ├── music │ ├── Celebrity.mp3 │ ├── The Rain.mp4 │ └── 天空之城.mp4 ├── script.js └── style.css ├── 17.响应式页面模板 ├── README.md ├── font │ └── Merienda-Regular.ttf ├── icon │ ├── iconfont.css │ ├── iconfont.js │ ├── iconfont.json │ └── iconfont.ttf ├── image │ ├── Jisoo.jpg │ ├── bg-1.jpg │ ├── bg-2.jpg │ ├── chetaixian.jpg │ ├── dingyiyu.jpg │ └── luowenji.jpg ├── index.html ├── script.js └── style.css ├── 2.樱花飞舞 ├── image │ ├── bg1.jpg │ └── sakura.png ├── index.html ├── script.js └── style.css ├── 3.3D卡片翻转效果-王心凌爱你 ├── font │ └── IndieFlower.ttf ├── image │ ├── wxl-1.jpg │ └── wxl-3.jpg ├── index.html └── style.css ├── 4.高考加油 ├── image │ └── bg.jpg ├── index.html ├── style.css └── 图解1.png ├── 5.新拟态登录界面 ├── icon │ ├── iconfont.css │ ├── iconfont.js │ ├── iconfont.json │ └── iconfont.ttf ├── index.html ├── script.js └── style.css ├── 6.主题切换 ├── css │ ├── reset.css │ ├── theme-blue.css │ ├── theme-dark.css │ ├── theme-red.css │ └── theme-white.css ├── index.html └── script.js ├── 7.可拖动半透明弹框dialog ├── image │ └── longmao.jpg ├── index.html ├── script.js └── style.css ├── 8.仿css-tricks的卡片抽出效果 ├── image │ ├── avatar-Jennie.png │ ├── avatar-Jisoo.png │ ├── avatar-Jisoo2.png │ ├── avatar-Lisa2.png │ └── avatar-Rose.png ├── index.html └── style.css ├── 9.炎炎夏日送你一场雪 ├── image │ ├── 1.jpg │ └── 3.jpg ├── index.html ├── script.js └── style.css ├── README.md └── 【粉丝问题解答-第1期】飘落樱花背景的页面 ├── image ├── petal.png └── sakura2.jpg ├── index.html ├── script.js └── style.css /1.打字特效/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 打字特效 9 | 10 | 11 |
12 | LITTLE YAO EATS TOO MUCH 13 |
14 | 15 | -------------------------------------------------------------------------------- /1.打字特效/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | /* */ 5 | /* box-sizing: border-box; */ 6 | box-sizing: content-box; 7 | } 8 | 9 | body { 10 | height: 100vh; 11 | background: #000; 12 | } 13 | 14 | .text { 15 | width: 100%; 16 | height: 100%; 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | color: #1eff00; 21 | } 22 | 23 | /* 24 | ch是一个新的单位,表示 "0" 的宽度 25 | */ 26 | .text span { 27 | font-size: 54px; 28 | font-weight: 700; 29 | width: 24ch; 30 | white-space: nowrap; 31 | overflow: hidden; 32 | /* Monaco, monospace, Consolas */ 33 | font-family: 'Consolas'; 34 | /* 35 | steps 函数,指定了一个阶跃函数 36 | steps() 第一个参数 number 为指定间隔数,即把动画分为 n 步阶段性展示 37 | */ 38 | animation: typing 6s steps(24), 39 | caret 1s steps(1) infinite; 40 | border-right: 2px solid; 41 | /* 用户无法选择:用来消除真实的鼠标光标 */ 42 | user-select: none; 43 | } 44 | 45 | @keyframes typing { 46 | from { 47 | width: 0px; 48 | } 49 | } 50 | 51 | @keyframes caret { 52 | 50% { 53 | border-color: transparent; 54 | } 55 | } -------------------------------------------------------------------------------- /10.两种主题的右键菜单/icon/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "iconfont"; /* Project id */ 3 | src: url('iconfont.ttf?t=1658137482552') format('truetype'); 4 | } 5 | 6 | .iconfont { 7 | font-family: "iconfont" !important; 8 | font-size: 16px; 9 | font-style: normal; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | .icon-xiazaidaoru:before { 15 | content: "\e8c6"; 16 | } 17 | 18 | .icon-jianqie:before { 19 | content: "\e648"; 20 | } 21 | 22 | .icon-fuzhi:before { 23 | content: "\e8b0"; 24 | } 25 | 26 | .icon-shanchu:before { 27 | content: "\e8b6"; 28 | } 29 | 30 | .icon-niantie:before { 31 | content: "\e64d"; 32 | } 33 | 34 | -------------------------------------------------------------------------------- /10.两种主题的右键菜单/icon/iconfont.js: -------------------------------------------------------------------------------- 1 | !function(e){var t,a,n,o,i,c='',d=(d=document.getElementsByTagName("script"))[d.length-1].getAttribute("data-injectcss"),s=function(e,t){t.parentNode.insertBefore(e,t)};if(d&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(e){console&&console.log(e)}}function h(){i||(i=!0,n())}function l(){try{o.documentElement.doScroll("left")}catch(e){return void setTimeout(l,50)}h()}t=function(){var e,t=document.createElement("div");t.innerHTML=c,c=null,(t=t.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",t=t,(e=document.body).firstChild?s(t,e.firstChild):e.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(t,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),t()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(n=t,o=e.document,i=!1,l(),o.onreadystatechange=function(){"complete"==o.readyState&&(o.onreadystatechange=null,h())})}(window); -------------------------------------------------------------------------------- /10.两种主题的右键菜单/icon/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "name": "", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "1727452", 10 | "name": "218下载、导入", 11 | "font_class": "xiazaidaoru", 12 | "unicode": "e8c6", 13 | "unicode_decimal": 59590 14 | }, 15 | { 16 | "icon_id": "2404486", 17 | "name": "剪切", 18 | "font_class": "jianqie", 19 | "unicode": "e648", 20 | "unicode_decimal": 58952 21 | }, 22 | { 23 | "icon_id": "11372665", 24 | "name": "复制", 25 | "font_class": "fuzhi", 26 | "unicode": "e8b0", 27 | "unicode_decimal": 59568 28 | }, 29 | { 30 | "icon_id": "11372693", 31 | "name": "删除", 32 | "font_class": "shanchu", 33 | "unicode": "e8b6", 34 | "unicode_decimal": 59574 35 | }, 36 | { 37 | "icon_id": "12323416", 38 | "name": "粘贴", 39 | "font_class": "niantie", 40 | "unicode": "e64d", 41 | "unicode_decimal": 58957 42 | } 43 | ] 44 | } 45 | -------------------------------------------------------------------------------- /10.两种主题的右键菜单/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/10.两种主题的右键菜单/icon/iconfont.ttf -------------------------------------------------------------------------------- /10.两种主题的右键菜单/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 两种主题的右键菜单 10 | 11 | 12 |
13 | 14 | 15 |
16 |
Light Menu
17 | 40 |
41 | 42 | 43 | 44 | 45 |
46 |
Dark Menu
47 | 70 |
71 | 72 |
73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /10.两种主题的右键菜单/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | /* 白色主题 */ 4 | // 获取左侧元素 5 | const light = doc.querySelector('.light'); 6 | // 获取菜单元素 7 | const lightMenuList = doc.querySelector('.light-menu-list'); 8 | // 获取菜单选项 9 | const lightMenuItemList = doc.querySelectorAll('.light-menu-list li'); 10 | 11 | // 监听右击事件 12 | light.addEventListener('contextmenu', (e) => { 13 | // 阻止右键默认事件发生 14 | e.preventDefault(); 15 | 16 | // 相对于用户浏览器左上角的xy坐标 17 | const { clientX, clientY } = e; 18 | 19 | // 获取菜单的宽高,保存为自定义类型 --width --height 20 | lightMenuList.setAttribute('style', `--width: ${ lightMenuList.scrollWidth }; --height: ${ lightMenuList.scrollHeight }`); 21 | 22 | lightMenuList.style.top = clientY + 'px'; 23 | lightMenuList.style.left = clientX + 'px'; 24 | 25 | lightMenuList.classList.add('menu-show'); 26 | lightMenuItemList.forEach(li => { 27 | li.classList.add('menu-item-show'); 28 | }); 29 | }); 30 | 31 | // 点击其他区域或者点击菜单选项,关闭菜单 32 | doc.addEventListener('click', (e) => { 33 | lightMenuList.classList.remove('menu-show'); 34 | lightMenuItemList.forEach(li => { 35 | li.classList.remove('menu-item-show'); 36 | }); 37 | }); 38 | 39 | 40 | 41 | 42 | /* 黑色主题 */ 43 | // 获取左侧元素 44 | const dark = doc.querySelector('.dark'); 45 | // 获取菜单元素 46 | const darkMenuList = doc.querySelector('.dark-menu-list'); 47 | // 获取菜单选项 48 | const darkMenuItemList = doc.querySelectorAll('.dark-menu-list li'); 49 | 50 | // 监听右击事件 51 | dark.addEventListener('contextmenu', (e) => { 52 | // 阻止右键默认事件发生 53 | e.preventDefault(); 54 | 55 | // 相对于用户浏览器左上角的xy坐标 56 | const { clientX, clientY } = e; 57 | 58 | // 获取菜单的宽高,保存为自定义类型 --width --height 59 | darkMenuList.setAttribute('style', `--width: ${ darkMenuList.scrollWidth }; --height: ${ darkMenuList.scrollHeight }`); 60 | 61 | darkMenuList.style.top = clientY + 'px'; 62 | darkMenuList.style.left = clientX + 'px'; 63 | 64 | darkMenuList.classList.add('menu-show'); 65 | darkMenuItemList.forEach(li => { 66 | li.classList.add('menu-item-show'); 67 | }); 68 | }); 69 | 70 | // 点击其他区域或者点击菜单选项,关闭菜单 71 | doc.addEventListener('click', (e) => { 72 | darkMenuList.classList.remove('menu-show'); 73 | darkMenuItemList.forEach(li => { 74 | li.classList.remove('menu-item-show'); 75 | }); 76 | }); -------------------------------------------------------------------------------- /10.两种主题的右键菜单/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | height: 100vh; 9 | overflow: hidden; 10 | } 11 | 12 | .container { 13 | width: 100%; 14 | height: 100%; 15 | display: flex; 16 | } 17 | 18 | .light, 19 | .dark { 20 | height: 100%; 21 | position: relative; 22 | } 23 | 24 | .light { 25 | width: 50%; 26 | background-color: #fff; 27 | } 28 | 29 | .dark { 30 | flex: 1; 31 | background-color: #000; 32 | } 33 | 34 | .light .light-title, 35 | .dark .dark-title { 36 | position: absolute; 37 | top: 50%; 38 | left: 50%; 39 | transform: translate(-50%, -50%); 40 | font-size: 24px; 41 | font-weight: 700; 42 | user-select: none; 43 | } 44 | 45 | .light .light-title { 46 | color: #000; 47 | } 48 | 49 | .dark .dark-title { 50 | color: #fff; 51 | } 52 | 53 | /* 【白色主题】菜单公共样式 */ 54 | .light-menu-list { 55 | list-style: none; 56 | background: linear-gradient( 57 | 45deg, 58 | rgba(255, 255, 255, 0.45) 0%, 59 | rgba(255, 255, 255, 0.85) 100% 60 | ); 61 | border: none; 62 | border-radius: 6px; 63 | backdrop-filter: blur(5px); 64 | overflow: hidden; 65 | position: fixed; 66 | top: 100px; 67 | left: 100px; 68 | z-index: 999; 69 | box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 70 | 0 2px 2px rgb(0 0 0 / 3%), 71 | 0 4px 4px rgb(0 0 0 / 4%), 72 | 0 10px 8px rgb(0 0 0 / 5%), 73 | 0 15px 15px rgb(0 0 0 / 6%), 74 | 0 30px 30px rgb(0 0 0 / 7%), 75 | 0 70px 65px rgb(0 0 0 / 9%); 76 | transform-origin: top left; 77 | transform: scale(0.5); 78 | height: 0; 79 | transition: transform .2s ease-in-out, 80 | height .3s ease-in-out, 81 | opacity .3s ease-in-out; 82 | } 83 | 84 | /* 菜单中的选项 */ 85 | .light-menu-list li:not(.divider) { 86 | border-radius: 4px; 87 | padding: 10px 30px 9px 11px; 88 | font-size: 14px; 89 | user-select: none; 90 | cursor: pointer; 91 | color: rgb(63, 57, 57); 92 | } 93 | 94 | .light-menu-list li:not(.divider) span { 95 | margin-left: 4px; 96 | } 97 | 98 | /* 悬浮色 */ 99 | .light-menu-list li:not(.divider):hover { 100 | background-color: rgba(10, 20, 28, 0.1); 101 | } 102 | 103 | /* 分割线 */ 104 | .light-menu-list li.divider { 105 | height: 1px; 106 | background-color: rgba(0, 0, 0, 0.1); 107 | user-select: none; 108 | } 109 | 110 | .light-menu-list li { 111 | opacity: 0; 112 | transform: translateX(-30px); 113 | transition: opacity .2s ease-in-out, 114 | transform .3s ease-in-out; 115 | } 116 | 117 | /* 显示菜单的样式 */ 118 | .light-menu-list.menu-show { 119 | opacity: 1; 120 | height: var(--height); 121 | transform: scale(1); 122 | border: 1px solid rgba(0, 0, 0, 0.1); 123 | } 124 | 125 | .light-menu-list li.menu-item-show { 126 | opacity: 1; 127 | transform: translateX(0px); 128 | } 129 | 130 | 131 | 132 | 133 | 134 | /* 【黑色色主题】菜单公共样式 */ 135 | .dark-menu-list { 136 | list-style: none; 137 | background: linear-gradient( 138 | 45deg, 139 | rgba(10, 20, 28, 0.2) 0%, 140 | rgba(10, 20, 28, 0.7) 100% 141 | ); 142 | border: none; 143 | border-radius: 6px; 144 | backdrop-filter: blur(5px); 145 | overflow: hidden; 146 | position: fixed; 147 | top: 100px; 148 | left: 100px; 149 | z-index: 999; 150 | box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 151 | 0 2px 2px rgb(0 0 0 / 3%), 152 | 0 4px 4px rgb(0 0 0 / 4%), 153 | 0 10px 8px rgb(0 0 0 / 5%), 154 | 0 15px 15px rgb(0 0 0 / 6%), 155 | 0 30px 30px rgb(0 0 0 / 7%), 156 | 0 70px 65px rgb(0 0 0 / 9%); 157 | transform-origin: top left; 158 | transform: scale(0.5); 159 | height: 0; 160 | transition: transform .2s ease-in-out, 161 | height .3s ease-in-out, 162 | opacity .3s ease-in-out; 163 | } 164 | 165 | /* 菜单中的选项 */ 166 | .dark-menu-list li:not(.divider) { 167 | border-radius: 4px; 168 | padding: 10px 30px 9px 11px; 169 | font-size: 14px; 170 | user-select: none; 171 | cursor: pointer; 172 | color: #fff; 173 | } 174 | 175 | .dark-menu-list li:not(.divider) span { 176 | margin-left: 4px; 177 | } 178 | 179 | /* 悬浮色 */ 180 | .dark-menu-list li:not(.divider):hover { 181 | background-color: rgba(255, 255, 255, 0.1); 182 | } 183 | 184 | /* 分割线 */ 185 | .dark-menu-list li.divider { 186 | height: 1px; 187 | background-color: rgba(255, 255, 255, 0.1); 188 | user-select: none; 189 | } 190 | 191 | .dark-menu-list li { 192 | opacity: 0; 193 | transform: translateX(-30px); 194 | transition: opacity .2s ease-in-out, 195 | transform .3s ease-in-out; 196 | } 197 | 198 | /* 显示菜单的样式 */ 199 | .dark-menu-list.menu-show { 200 | opacity: 1; 201 | height: var(--height); 202 | transform: scale(1); 203 | border: 1px solid rgba(255, 255, 255, 0.1); 204 | } 205 | 206 | .dark-menu-list li.menu-item-show { 207 | opacity: 1; 208 | transform: translateX(0px); 209 | } -------------------------------------------------------------------------------- /11.加载特效(一)—模糊加载效果/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 加载效果-模糊效果 9 | 10 | 11 |
Loading
12 | 13 | -------------------------------------------------------------------------------- /11.加载特效(一)—模糊加载效果/style.css: -------------------------------------------------------------------------------- 1 | /* 样式初始化 */ 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | } 7 | 8 | body { 9 | height: 100vh; 10 | background-color: #000; 11 | /* flex布局,水平垂直方向居中 */ 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | } 16 | 17 | .loading { 18 | font-size: 32px; 19 | font-weight: 700; 20 | color: #fff; 21 | /* 字间距 */ 22 | letter-spacing: 3px; 23 | /* 24 | 动画 25 | animate: 自定义动画名 26 | 1.5s: 动画持续时长 27 | infinite: 动画无限循环 28 | alternate: 动画在奇数次数正向播放,在偶数次反向播放 29 | ease-in-out: 动画以低速开始额结束 30 | */ 31 | animation: animate 1.5s infinite alternate ease-in-out; 32 | /* 字体用户无法选中 */ 33 | user-select: none; 34 | } 35 | 36 | @keyframes animate { 37 | to 38 | { 39 | opacity: 0.08; 40 | /* 滤镜:模糊效果 */ 41 | filter: blur(5px); 42 | letter-spacing: 8px; 43 | } 44 | } -------------------------------------------------------------------------------- /12.图片放大镜效果/image/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/12.图片放大镜效果/image/1.jpg -------------------------------------------------------------------------------- /12.图片放大镜效果/image/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/12.图片放大镜效果/image/2.jpg -------------------------------------------------------------------------------- /12.图片放大镜效果/image/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/12.图片放大镜效果/image/3.jpg -------------------------------------------------------------------------------- /12.图片放大镜效果/image/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/12.图片放大镜效果/image/4.jpg -------------------------------------------------------------------------------- /12.图片放大镜效果/image/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/12.图片放大镜效果/image/5.jpg -------------------------------------------------------------------------------- /12.图片放大镜效果/image/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/12.图片放大镜效果/image/6.jpg -------------------------------------------------------------------------------- /12.图片放大镜效果/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 图片的放大镜效果 9 | 10 | 11 | 12 |
13 | 14 |
15 | 16 | 17 |
18 | 19 |
20 | 21 | 22 | -------------------------------------------------------------------------------- /12.图片放大镜效果/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | const image = doc.querySelector('.image'); // 获取图片容器的元素 4 | const zoom = doc.querySelector('.zoom'); // 获取放大镜区域的元素 5 | const zoomImage = doc.querySelector('.zoom-image'); // 获取放大镜区域中的img元素 6 | const imagesSrc = doc.querySelectorAll('img'); // 获取所有的img标签的元素 7 | 8 | let clearSrc; 9 | let zoomLevel = 1; // 放大的程度 10 | 11 | // 图片数组 12 | const images = [ 13 | './image/1.jpg', 14 | './image/2.jpg', 15 | './image/3.jpg', 16 | './image/4.jpg', 17 | './image/5.jpg', 18 | './image/6.jpg' 19 | ]; 20 | 21 | // 随机选择一张图片 22 | let img = images[Math.floor(Math.random() * images.length)]; 23 | // 将随机选出的图片放到图片区域显示 24 | imagesSrc[0].setAttribute('src', img); 25 | 26 | // 【鼠标事件】 27 | // 当鼠标移动到image上时,会触发 mouserover 事件 28 | image.addEventListener('mouseover', enterImage); 29 | // 当鼠标移出image时,会触发 mouseout 事件 30 | image.addEventListener('mouseout', leaveImage); 31 | // 当鼠标在image上移动时,会触发 mousemove 事件 32 | image.addEventListener('mousemove', move); 33 | // 在 image 上鼠标滚轮滚动时会触发 wheel 事件 34 | image.addEventListener('wheel', scrollWheel); 35 | 36 | /** 37 | * 鼠标进入到图片区域 38 | */ 39 | function enterImage(event) { 40 | // 显示 zoom 区域 41 | zoom.classList.add('show', 'loading'); 42 | 43 | clearTimeout(clearSrc); 44 | 45 | let x, y; 46 | // client: 客户端坐标 47 | x = event.clientX; 48 | y = event.clientY; 49 | // 设置放大区域的位置(offsetWidth: 放大区域的宽) 50 | zoom.style.left = `${ x - zoom.offsetWidth / 2 }px`; 51 | zoom.style.top = `${ y - zoom.offsetHeight / 2 }px`; 52 | 53 | // 设置放大区域的图片 54 | zoomImage.setAttribute('src', img); 55 | // 56 | zoomImage.onload = function() { 57 | setTimeout(() => { 58 | zoom.classList.remove('loading'); 59 | }, 500); 60 | } 61 | } 62 | 63 | /** 64 | * 鼠标离开图片区域 65 | */ 66 | function leaveImage(evnet) { 67 | zoom.style.transform = null; 68 | zoomLevel = 1; 69 | // 移除 show 样式 70 | zoom.classList.remove('show'); 71 | // 0.25s 之后移除放大镜图片 72 | clearSrc = setTimeout(() => { 73 | zoomImage.setAttribute('src', '') 74 | }, 250); 75 | } 76 | 77 | /** 78 | * 鼠标在图片区域移动 79 | */ 80 | function move(event) { 81 | event.preventDefault(); 82 | 83 | let x, y; 84 | // client: 客户端坐标 85 | x = event.clientX; 86 | y = event.clientY; 87 | 88 | // 设置放大区域的位置(offsetWidth: 放大区域的宽) 89 | zoom.style.left = `${ x - zoom.offsetWidth / 2 }px`; 90 | zoom.style.top = `${ y - zoom.offsetHeight / 2 }px`; 91 | 92 | // 这里求出的时鼠标所在位置的比例 鼠标的坐标 x - image区域坐标 x = 鼠标在图片区域中的一个相对x坐标 93 | // this 指向的是 image 94 | let zx = (x - this.offsetLeft) / this.offsetWidth, 95 | zy = (y - this.offsetTop) / this.offsetHeight; 96 | 97 | // 放大镜效果 98 | let zoomLeft = -zx * zoomImage.offsetWidth + (zoom.offsetWidth / 2), 99 | zoomTop = -zy * zoomImage.offsetHeight + (zoom.offsetHeight / 2); 100 | 101 | zoomImage.style.left = `${ zoomLeft }px`; 102 | zoomImage.style.top = `${ zoomTop }px`; 103 | } 104 | 105 | /** 106 | * 图片区域鼠标滚轮滚动 107 | */ 108 | function scrollWheel(event) { 109 | event.preventDefault(); 110 | 111 | // 设置放大级别 112 | event.deltaY > 0 ? zoomLevel-- : zoomLevel++; 113 | // 最小缩放到1倍 114 | if (zoomLevel < 1) { 115 | zoomLevel = 1; 116 | } 117 | // 最大放大倍数为5 118 | if (zoomLevel > 5) { 119 | zoomLevel = 5; 120 | } 121 | 122 | zoom.style.transform = `scale(${ zoomLevel })`; 123 | } -------------------------------------------------------------------------------- /12.图片放大镜效果/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | height: 100vh; 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | overflow: hidden; 13 | background-image: linear-gradient(-225deg, #e3fdf5 0%, #ffe6fa); 14 | } 15 | 16 | .image { 17 | width: 800px; 18 | height: 500px; 19 | background-color: #000; 20 | user-select: none; 21 | } 22 | 23 | .image img { 24 | width: 100%; 25 | height: 100%; 26 | object-fit: cover; 27 | } 28 | 29 | .img { 30 | cursor: none; 31 | } 32 | 33 | .zoom { 34 | width: 200px; 35 | height: 200px; 36 | border-radius: 50%; 37 | background-color: #fff; 38 | position: absolute; 39 | pointer-events: none; 40 | transition: transform .25s ease, 41 | opacity 0s linear .25s, 42 | background .25s ease; 43 | opacity: 0; 44 | transform: scale(0); 45 | transform-origin: 50% 50%; 46 | overflow: hidden; 47 | } 48 | 49 | .zoom.show { 50 | transform: scale(1); 51 | opacity: 1; 52 | transition: transform .25s ease, 53 | opacity 0s linear; 54 | } 55 | 56 | .zoom.loading { 57 | background: transparent; 58 | } 59 | 60 | .zoom.loading::before { 61 | display: block; 62 | animation: loading .5s ease infinite alternate; 63 | } 64 | 65 | @keyframes loading { 66 | 0% 67 | { 68 | transform: scale(0.1); 69 | box-shadow: inset 0 0 0 150px gold; 70 | } 71 | 50% 72 | { 73 | transform: scale(1); 74 | box-shadow: inset 0 0 0 140px gold; 75 | } 76 | 100% 77 | { 78 | box-shadow: inset 0 0 0 0px gold; 79 | } 80 | } 81 | 82 | .zoom-image { 83 | position: absolute; 84 | left: 0; 85 | top: 0; 86 | transition: opacity .25s ease; 87 | } -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/image/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/13.消失的导航栏-IntersectionObserver/image/bg1.jpg -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/image/bg2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/13.消失的导航栏-IntersectionObserver/image/bg2.jpg -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/image/bg3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/13.消失的导航栏-IntersectionObserver/image/bg3.jpg -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/image/bg4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/13.消失的导航栏-IntersectionObserver/image/bg4.jpg -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 消失的导航栏 9 | 10 | 11 |
12 | 13 | 23 | 24 | 25 |
26 | 27 | 28 |
29 | 35 |
36 |
37 | 38 | 39 |
40 | 41 | 42 |
43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | const navbar = doc.querySelector('#navbar'); 3 | const dd = doc.querySelector('#dd'); 4 | 5 | /* 6 | 7 | 回调函数,会触发俩次 8 | 9 | 第一次:当 dd 出现在视野范围内时触发 10 | 第二次:当 dd 消失在视野范围内触发 11 | 12 | */ 13 | function hiddenNavbar(entries) { 14 | // 拿到 IntersectionObserverEntry 对象 15 | const ddEntry = entries[0]; 16 | 17 | if (ddEntry.intersectionRatio !== 0) { 18 | navbar.classList.add('hidden'); 19 | } else { 20 | navbar.classList.remove('hidden'); 21 | } 22 | 23 | } 24 | 25 | // 使用[交叉观察器] 26 | const io = new IntersectionObserver(hiddenNavbar); 27 | 28 | // 监控 little-d 29 | io.observe(dd); -------------------------------------------------------------------------------- /13.消失的导航栏-IntersectionObserver/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | height: 100vh; 9 | } 10 | 11 | /* 隐藏滚动条 */ 12 | ::-webkit-scrollbar { 13 | width: 0; 14 | } 15 | 16 | .container { 17 | position: relative; 18 | } 19 | 20 | .page1, .page2, .page3, .page4 { 21 | width: 100%; 22 | height: 100vh; 23 | background-size: cover; 24 | } 25 | 26 | .page1 { 27 | background-image: url(./image/bg1.jpg); 28 | } 29 | 30 | .page2 { 31 | background-image: url(./image/bg2.jpg); 32 | } 33 | 34 | .page3 { 35 | background-image: url(./image/bg3.jpg); 36 | } 37 | 38 | .page4 { 39 | background-image: url(./image/bg4.jpg); 40 | } 41 | 42 | /* 导航栏样式 */ 43 | .navbar { 44 | height: 60px; 45 | opacity: 1; 46 | background-color: #262626; 47 | position: fixed; 48 | top: 0; 49 | left: 0; 50 | right: 0; 51 | z-index: 1; 52 | display: flex; 53 | align-items: center; 54 | justify-content: space-between; 55 | color: #fff; 56 | transition: opacity .3s ease-in-out, 57 | height .3s ease-in-out; 58 | } 59 | 60 | .navbar.hidden { 61 | opacity: 0; 62 | height: 0; 63 | } 64 | 65 | .navbar .logo { 66 | width: 200px; 67 | text-align: center; 68 | font-size: 30px; 69 | font-weight: 700; 70 | text-transform: uppercase; 71 | letter-spacing: 2px; 72 | cursor: pointer; 73 | user-select: none; 74 | } 75 | 76 | /* 菜单 */ 77 | .navbar .right { 78 | list-style: none; 79 | display: flex; 80 | justify-content: center; 81 | align-items: center; 82 | font-size: 18px; 83 | margin-right: 40px; 84 | } 85 | 86 | .navbar .right li { 87 | margin: 0 32px; 88 | cursor: pointer; 89 | user-select: none; 90 | } 91 | 92 | /* 93 | 侦察兵小d 94 | 95 | 设置位置 96 | 97 | */ 98 | .little-d { 99 | position: absolute; 100 | left: 500px; 101 | top: 180vh; 102 | bottom: 0; 103 | width: 10px; 104 | background-color: red; 105 | z-index: -1; 106 | } -------------------------------------------------------------------------------- /14.canvas水印效果/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | canvas-水印效果 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /14.canvas水印效果/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | class WaterMark { 4 | 5 | constructor() { 6 | this.pattern = doc.querySelector('#pattern'); 7 | this.waterMark = doc.querySelector('#water-mark'); 8 | // 获取 pattern 的上下文 9 | this.patternCtx = this.pattern.getContext('2d'); 10 | // 获取 water-mark 的上下文 11 | this.waterMarkCtx = this.waterMark.getContext('2d'); 12 | 13 | // 初始化 14 | this.init(); 15 | } 16 | 17 | /** 18 | * 初始化 19 | * 20 | * 1. 画 pattern 21 | * 2. 画 水印 22 | * 3. 屏幕尺寸自适应重绘 23 | */ 24 | init() { 25 | this.drawPattern(this.patternCtx); 26 | this.drawWaterMark(this.waterMarkCtx); 27 | this.resize(); 28 | } 29 | 30 | /** 31 | * drawPattern 32 | * 33 | * 画单个水印 34 | */ 35 | drawPattern(ctx) { 36 | // 单个水印的宽高 37 | const width = 120, height = 80; 38 | const text = 'yao大叔'; 39 | // 清空一块矩形区域,这块区域用来写单个水印的内容 40 | ctx.clearRect(0, 0, width, height); 41 | // 设置字体大小 42 | ctx.font = 'bold 32px Microsoft Yahei'; 43 | // 设置水印的颜色 44 | ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; 45 | // 旋转一定角度 46 | ctx.rotate(-Math.PI / 180 * 30); 47 | // 设置内容和坐标 48 | ctx.fillText(text, -10, 120); 49 | // 这单个水印不需要显示,隐藏 50 | this.pattern.style.display = 'none'; 51 | } 52 | 53 | /** 54 | * 将单个水印平铺到整个页面 55 | */ 56 | drawWaterMark(ctx) { 57 | // 获取 body 宽高 58 | const clientWidth = doc.body.clientWidth; 59 | const clientHeight = doc.body.clientHeight; 60 | 61 | this.waterMark.width = clientWidth; 62 | this.waterMark.height = clientHeight; 63 | 64 | // 绘图前先对区域内的内容进行情场(即 清除矩形区域内的内容) 65 | ctx.clearRect(0, 0, clientWidth, clientHeight); 66 | 67 | // createPattern: 在指定的方向内重复指定的元素。元素可以是图片、视频、或者其他 canvase 元素 68 | // 在这里的效果就是将我们单个的水印 pattern 平铺满整个屏幕 69 | const pattern = ctx.createPattern(this.pattern, 'repeat'); 70 | 71 | ctx.fillStyle = pattern; 72 | ctx.fillRect(0, 0, clientWidth, clientHeight); 73 | } 74 | 75 | /** 76 | * 监听浏览器窗口大小变化,重绘水印 77 | */ 78 | resize() { 79 | window.addEventListener('resize', () => { 80 | this.drawWaterMark(this.waterMarkCtx); 81 | }); 82 | } 83 | 84 | } 85 | 86 | new WaterMark(); -------------------------------------------------------------------------------- /14.canvas水印效果/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | height: 100vh; 9 | background-color: bisque; 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | #water-mark { 15 | position: absolute; 16 | z-index: -10; 17 | top: 0; 18 | bottom: 0; 19 | left: 0; 20 | right: 0; 21 | } -------------------------------------------------------------------------------- /15.MutationObserver变动观察器/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | MutationObserver监听DOM节点 9 | 10 | 11 |
12 | 13 |
Lemon
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 | -------------------------------------------------------------------------------- /15.MutationObserver变动观察器/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | class WaterMark { 4 | 5 | constructor() { 6 | this.pattern = doc.querySelector('#pattern'); 7 | this.waterMark = doc.querySelector('#water-mark'); 8 | // 获取 pattern 的上下文 9 | this.patternCtx = this.pattern.getContext('2d'); 10 | // 获取 水印区域 的上下文 11 | this.waterMarkCtx = this.waterMark.getContext('2d'); 12 | 13 | this.init(); 14 | } 15 | 16 | /** 17 | * 初始化 18 | * 1. 画 pattern 模式 19 | * 2. 画 水印 20 | * 3. 屏幕尺寸自适应重绘 21 | */ 22 | init() { 23 | this.drawPattern(this.patternCtx); 24 | this.drawWaterMark(this.waterMarkCtx); 25 | this.resize(); 26 | } 27 | 28 | /** 29 | * 画单个水印 30 | */ 31 | drawPattern(ctx) { 32 | // 单个水印的宽高 33 | const width = 120, height = 80; 34 | const text = 'yao大叔'; 35 | // 清空一块矩形区域,这块区域用来写单个水印的内容 36 | ctx.clearRect(0, 0, width, height); 37 | // 设置字体和大小 38 | ctx.font = 'bold 32px Microsoft Yahei'; 39 | // 设置水印颜色 40 | ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; 41 | // 旋转 42 | ctx.rotate(-Math.PI / 180 * 30); 43 | // 设置内容和坐标(0, 80) 44 | ctx.fillText(text, -10, 120); 45 | // 这个单个水印不需要显示,隐藏 46 | this.pattern.style.display = 'none'; 47 | } 48 | 49 | /** 50 | * 将单个水印平铺到整个页面 51 | */ 52 | drawWaterMark(ctx) { 53 | // 获取 宽高 54 | const clientWidth = doc.body.clientWidth; 55 | const clientHeight = doc.body.clientHeight; 56 | 57 | this.waterMark.width = clientWidth; 58 | this.waterMark.height = clientHeight; 59 | 60 | // 绘图前先对区域内的内容进行清场(即 清除矩形区域内的内容) 61 | ctx.clearRect(0, 0, clientWidth, clientHeight); 62 | 63 | // createPattern: 在指定的方向内重复指定的元素。元素可以是图片、视频,或者其他 元素。 64 | // 在这里的效果就是将我们单个的水印 pattern 平铺满整个屏幕 65 | const pattern = ctx.createPattern(this.pattern, 'repeat'); 66 | 67 | ctx.fillStyle = pattern; 68 | ctx.fillRect(0, 0, clientWidth, clientHeight); 69 | } 70 | 71 | /** 72 | * // 监听浏览器窗口大小变化,重绘水印 73 | */ 74 | resize() { 75 | window.addEventListener('resize', () => { 76 | this.drawWaterMark(this.waterMarkCtx); 77 | }); 78 | } 79 | 80 | 81 | 82 | 83 | } 84 | 85 | new WaterMark(); -------------------------------------------------------------------------------- /15.MutationObserver变动观察器/script2.js: -------------------------------------------------------------------------------- 1 | const doc2 = document; 2 | 3 | /* 4 | 5 | 变动观察器 (Mutation Observer) 6 | 7 | DOM规范中的MutationObsesrver接口,可以在DOM被修改时异步执行回调 8 | 9 | 不过,目标节点的删除它监控不到; 10 | 11 | 12 | */ 13 | 14 | // 拿到水印节点 15 | const waterMarkNode = doc2.querySelector('#water-mark'); 16 | const patternNode = doc2.querySelector('#pattern'); 17 | const bodyNode = doc2.querySelector('body'); 18 | 19 | let observer = new MutationObserver(handler); 20 | 21 | // attributes、subtree、characterData 中必须至少有一项为 true 22 | const options = { 23 | attributes: true, // 是否观察目标节点的属性变化,例如 style、class 24 | subtree: true, // 除了目标节点,是否观察目标节点的字数 25 | characterData: false, // 表示修改字符数据是否发生变化 26 | childList: true // 表示修改目标节点的子节点是否触发事件变化 27 | } 28 | 29 | observer.observe(waterMarkNode, options); 30 | observer.observe(bodyNode, options); 31 | observer.observe(patternNode, options); 32 | 33 | 34 | /** 35 | * 观察后的回调函数 36 | * 37 | * 每个回调函数会收到一个MutationRecord实例的数据 38 | * MutationRecord实例包含的信息包括发生了什么变化,以及DOM的哪一部分受到了影响 39 | * 40 | */ 41 | function handler(mutationRecordList) { 42 | console.log('触发了回调函数'); 43 | console.log(mutationRecordList); 44 | 45 | mutationRecordList.forEach(record => { 46 | // 情况一:如果通过删除 canvas 节点的方式移除水印,那么需要监听 water-mark 的父元素 body 47 | // 判断删除了 body 的儿子 water-mark 48 | if (record.target?.localName === 'body') { 49 | record.removedNodes.forEach(rn => { 50 | if (rn.id === 'water-mark') { 51 | bodyNode.innerHTML = '

谁删除了老子的水印?站出来!

'; 52 | } 53 | }); 54 | return; 55 | } 56 | 57 | // 情况二:如果是通过修改 water-mark 的 dom 节点属性移除水印,那么需要监听 water-mark 本身 58 | // TODO 59 | }); 60 | 61 | 62 | } -------------------------------------------------------------------------------- /15.MutationObserver变动观察器/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | height: 100vh; 9 | background-color: rgb(245, 251, 210); 10 | position: relative; 11 | overflow: hidden; 12 | } 13 | 14 | .container { 15 | width: 100%; 16 | height: 100%; 17 | overflow: auto; 18 | display: flex; 19 | justify-content: center; 20 | align-items: center; 21 | flex-direction: column; 22 | } 23 | 24 | .container .title { 25 | font-size: 24px; 26 | font-weight: 700; 27 | margin-bottom: 16px; 28 | color: darkolivegreen; 29 | } 30 | 31 | .container p { 32 | margin: 4px 0; 33 | font-size: 17px; 34 | font-weight: 700; 35 | color: darkolivegreen; 36 | } 37 | 38 | .wt-box { 39 | position: absolute; 40 | z-index: 100; 41 | top: 0; 42 | left: 0; 43 | } 44 | 45 | #water-mark { 46 | position: absolute; 47 | z-index: -10; 48 | top: 0; 49 | bottom: 0; 50 | left: 0; 51 | right: 0; 52 | } -------------------------------------------------------------------------------- /16.音乐播放器-1/font/JosefinSans-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/font/JosefinSans-Light.ttf -------------------------------------------------------------------------------- /16.音乐播放器-1/icon/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "iconfont"; /* Project id */ 3 | src: url('iconfont.ttf?t=1665812026095') format('truetype'); 4 | } 5 | 6 | .iconfont { 7 | font-family: "iconfont" !important; 8 | font-size: 16px; 9 | font-style: normal; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | .icon-jushoucang:before { 15 | content: "\e643"; 16 | } 17 | 18 | .icon-jushoucanggift:before { 19 | content: "\e684"; 20 | } 21 | 22 | .icon-iconstop:before { 23 | content: "\e69d"; 24 | } 25 | 26 | .icon-danlieliebiao:before { 27 | content: "\e6e4"; 28 | } 29 | 30 | .icon-tianjia:before { 31 | content: "\e622"; 32 | } 33 | 34 | .icon-xiayishou:before { 35 | content: "\e647"; 36 | } 37 | 38 | .icon-suiji:before { 39 | content: "\e60a"; 40 | } 41 | 42 | .icon-xunhuan:before { 43 | content: "\e6a9"; 44 | } 45 | 46 | .icon-diyiyeshouyeshangyishou:before { 47 | content: "\e76d"; 48 | } 49 | 50 | .icon-shengyin_shiti:before { 51 | content: "\eca5"; 52 | } 53 | 54 | .icon-shangyishou:before { 55 | content: "\e603"; 56 | } 57 | 58 | .icon-xiayishou1:before { 59 | content: "\e602"; 60 | } 61 | 62 | .icon-24gf-play:before { 63 | content: "\ea82"; 64 | } 65 | 66 | .icon-xiayishou2:before { 67 | content: "\e63e"; 68 | } 69 | 70 | .icon-shangyishou1:before { 71 | content: "\e61e"; 72 | } 73 | 74 | .icon-shunxu:before { 75 | content: "\e64f"; 76 | } 77 | 78 | .icon-volume-mute-fill:before { 79 | content: "\e625"; 80 | } 81 | 82 | -------------------------------------------------------------------------------- /16.音乐播放器-1/icon/iconfont.js: -------------------------------------------------------------------------------- 1 | window._iconfont_svg_string_='',function(i){var t=(t=document.getElementsByTagName("script"))[t.length-1],o=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var c,a,l,e,n,s=function(t,o){o.parentNode.insertBefore(t,o)};if(o&&!i.__iconfont__svg__cssinject__){i.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}c=function(){var t,o=document.createElement("div");o.innerHTML=i._iconfont_svg_string_,(o=o.getElementsByTagName("svg")[0])&&(o.setAttribute("aria-hidden","true"),o.style.position="absolute",o.style.width=0,o.style.height=0,o.style.overflow="hidden",o=o,(t=document.body).firstChild?s(o,t.firstChild):t.appendChild(o))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(c,0):(a=function(){document.removeEventListener("DOMContentLoaded",a,!1),c()},document.addEventListener("DOMContentLoaded",a,!1)):document.attachEvent&&(l=c,e=i.document,n=!1,h(),e.onreadystatechange=function(){"complete"==e.readyState&&(e.onreadystatechange=null,d())})}function d(){n||(n=!0,l())}function h(){try{e.documentElement.doScroll("left")}catch(t){return void setTimeout(h,50)}d()}}(window); -------------------------------------------------------------------------------- /16.音乐播放器-1/icon/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "name": "", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "627569", 10 | "name": "聚收藏", 11 | "font_class": "jushoucang", 12 | "unicode": "e643", 13 | "unicode_decimal": 58947 14 | }, 15 | { 16 | "icon_id": "829167", 17 | "name": "聚收藏gift", 18 | "font_class": "jushoucanggift", 19 | "unicode": "e684", 20 | "unicode_decimal": 59012 21 | }, 22 | { 23 | "icon_id": "989480", 24 | "name": "暂停", 25 | "font_class": "iconstop", 26 | "unicode": "e69d", 27 | "unicode_decimal": 59037 28 | }, 29 | { 30 | "icon_id": "1046065", 31 | "name": "单列列表", 32 | "font_class": "danlieliebiao", 33 | "unicode": "e6e4", 34 | "unicode_decimal": 59108 35 | }, 36 | { 37 | "icon_id": "1304889", 38 | "name": "添加", 39 | "font_class": "tianjia", 40 | "unicode": "e622", 41 | "unicode_decimal": 58914 42 | }, 43 | { 44 | "icon_id": "1312005", 45 | "name": "下一首", 46 | "font_class": "xiayishou", 47 | "unicode": "e647", 48 | "unicode_decimal": 58951 49 | }, 50 | { 51 | "icon_id": "1488903", 52 | "name": "随机", 53 | "font_class": "suiji", 54 | "unicode": "e60a", 55 | "unicode_decimal": 58890 56 | }, 57 | { 58 | "icon_id": "1769930", 59 | "name": "循环", 60 | "font_class": "xunhuan", 61 | "unicode": "e6a9", 62 | "unicode_decimal": 59049 63 | }, 64 | { 65 | "icon_id": "6129086", 66 | "name": "48第一页、首页、上一首", 67 | "font_class": "diyiyeshouyeshangyishou", 68 | "unicode": "e76d", 69 | "unicode_decimal": 59245 70 | }, 71 | { 72 | "icon_id": "6776386", 73 | "name": "声音_实体", 74 | "font_class": "shengyin_shiti", 75 | "unicode": "eca5", 76 | "unicode_decimal": 60581 77 | }, 78 | { 79 | "icon_id": "7417086", 80 | "name": "上一首", 81 | "font_class": "shangyishou", 82 | "unicode": "e603", 83 | "unicode_decimal": 58883 84 | }, 85 | { 86 | "icon_id": "7417092", 87 | "name": "下一首", 88 | "font_class": "xiayishou1", 89 | "unicode": "e602", 90 | "unicode_decimal": 58882 91 | }, 92 | { 93 | "icon_id": "7594155", 94 | "name": "24gf-play", 95 | "font_class": "24gf-play", 96 | "unicode": "ea82", 97 | "unicode_decimal": 60034 98 | }, 99 | { 100 | "icon_id": "8341786", 101 | "name": "下一首", 102 | "font_class": "xiayishou2", 103 | "unicode": "e63e", 104 | "unicode_decimal": 58942 105 | }, 106 | { 107 | "icon_id": "16648567", 108 | "name": "上一首", 109 | "font_class": "shangyishou1", 110 | "unicode": "e61e", 111 | "unicode_decimal": 58910 112 | }, 113 | { 114 | "icon_id": "16913207", 115 | "name": "顺序", 116 | "font_class": "shunxu", 117 | "unicode": "e64f", 118 | "unicode_decimal": 58959 119 | }, 120 | { 121 | "icon_id": "23239238", 122 | "name": "声音关闭-fill", 123 | "font_class": "volume-mute-fill", 124 | "unicode": "e625", 125 | "unicode_decimal": 58917 126 | } 127 | ] 128 | } 129 | -------------------------------------------------------------------------------- /16.音乐播放器-1/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/icon/iconfont.ttf -------------------------------------------------------------------------------- /16.音乐播放器-1/image/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/image/1.jpg -------------------------------------------------------------------------------- /16.音乐播放器-1/image/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/image/2.jpg -------------------------------------------------------------------------------- /16.音乐播放器-1/image/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/image/3.jpg -------------------------------------------------------------------------------- /16.音乐播放器-1/image/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/image/bg1.jpg -------------------------------------------------------------------------------- /16.音乐播放器-1/image/bg2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/image/bg2.jpg -------------------------------------------------------------------------------- /16.音乐播放器-1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | Music Player 10 | 11 | 12 | 13 |
14 | 15 |
16 | 17 |
18 | 19 | 20 |
21 | 22 |
23 |
0:00
24 |
25 |
3:15
26 |
27 | 28 |
29 | 30 | 31 |
32 | 33 |
34 | 35 |
36 | 37 | 38 | 39 | 40 | 41 |
42 | 43 |
44 |
45 | 46 | 47 |
48 | 50 |
51 |
52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /16.音乐播放器-1/music/Celebrity.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/music/Celebrity.mp3 -------------------------------------------------------------------------------- /16.音乐播放器-1/music/The Rain.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/music/The Rain.mp4 -------------------------------------------------------------------------------- /16.音乐播放器-1/music/天空之城.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/16.音乐播放器-1/music/天空之城.mp4 -------------------------------------------------------------------------------- /16.音乐播放器-1/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | // 歌曲信息数组 4 | const songsList = [ 5 | { 6 | id: 'xxx-01', 7 | title: '天空之城', 8 | author: '久石让', 9 | path: './music/天空之城.mp4', 10 | bgPath: './image/1.jpg', 11 | time: 0 12 | }, 13 | { 14 | id: 'xxx-02', 15 | title: 'Celebrity', 16 | author: 'IU', 17 | path: './music/Celebrity.mp3', 18 | bgPath: './image/2.jpg', 19 | time: 0 20 | }, 21 | { 22 | id: 'xxx-03', 23 | title: 'The Rain', 24 | author: '久石让', 25 | path: './music/The Rain.mp4', 26 | bgPath: './image/3.jpg', 27 | time: 0 28 | } 29 | ]; 30 | 31 | // DOM元素 32 | const audio = doc.querySelector('#audio'); // 播放器 33 | const bgImg = doc.querySelector('#bg-img'); // 插图 34 | const controls = doc.querySelector('#controls'); // 按钮区域 35 | const title = doc.querySelector('#title'); // 歌曲标题 36 | const author = doc.querySelector('#author'); // 歌曲作者 37 | const playBtn = doc.querySelector('#play'); // 播放按钮 38 | const voiceBtn = doc.querySelector('#voice'); // 声音开关 39 | 40 | // 当前播放歌曲 41 | let curSongIndex = 1; 42 | // 是否在播放 43 | let isPlay = false; 44 | 45 | 46 | // 初始化 47 | function init() { 48 | render(songsList[curSongIndex]); 49 | } 50 | 51 | 52 | // 按钮事件 53 | controls.addEventListener('click', e => { 54 | switch (e.target?.id) { 55 | case 'list': // 歌曲列表 56 | // TODO 57 | break; 58 | case 'voice': // 声音开关 59 | voiceControl(); 60 | break; 61 | case 'pre': // 上一首 62 | preSong(); 63 | break; 64 | case 'play': // 播放/暂停 65 | togglePlay(); 66 | break; 67 | case 'next': // 下一首 68 | nextSong(); 69 | break; 70 | case 'mode': // 播放模式 71 | // TODO 72 | break; 73 | default: 74 | break; 75 | } 76 | }); 77 | 78 | // 播放 / 暂停 切换 79 | function togglePlay() { 80 | if (!isPlay) { 81 | // 暂停 图标切换 82 | songPlay(); 83 | } else { 84 | // 播放 图标切换 85 | songPause(); 86 | } 87 | } 88 | 89 | // 播放 90 | function songPlay() { 91 | isPlay = true; 92 | playBtn.classList.remove('icon-24gf-play'); 93 | playBtn.classList.add('icon-iconstop'); 94 | audio.play(); 95 | } 96 | 97 | // 暂停 98 | function songPause() { 99 | isPlay = false; 100 | playBtn.classList.remove('icon-iconstop'); 101 | playBtn.classList.add('icon-24gf-play'); 102 | audio.pause(); 103 | } 104 | 105 | // 上一首 106 | function preSong() { 107 | if (curSongIndex > 0) { 108 | curSongIndex--; 109 | render(songsList[curSongIndex]); 110 | songPlay(); 111 | } 112 | } 113 | 114 | // 下一首 115 | function nextSong() { 116 | if (curSongIndex < songsList.length - 1) { 117 | curSongIndex++; 118 | render(songsList[curSongIndex]); 119 | songPlay(); 120 | } 121 | } 122 | 123 | // 声音控制 124 | function voiceControl() { 125 | if (audio.volume > 0) { 126 | voiceOff(); 127 | } else { 128 | voiceOn(); 129 | } 130 | } 131 | 132 | // 声音开 133 | function voiceOn() { 134 | audio.volume = 1; 135 | voiceBtn.classList.remove('icon-volume-mute-fill'); 136 | voiceBtn.classList.add('icon-shengyin_shiti'); 137 | } 138 | 139 | // 声音关 140 | function voiceOff() { 141 | audio.volume = 0; 142 | voiceBtn.classList.remove('icon-shengyin_shiti'); 143 | voiceBtn.classList.add('icon-volume-mute-fill'); 144 | } 145 | 146 | 147 | // 内容渲染到页面 148 | function render(song) { 149 | title.innerHTML = song.title; 150 | author.innerHTML = song.author; 151 | bgImg.src = song.bgPath; // 插图 152 | audio.volume = 1; // 音量 0 ~ 1 153 | audio.src = song.path; // 音乐资源路径 154 | } 155 | 156 | 157 | init(); -------------------------------------------------------------------------------- /16.音乐播放器-1/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'JosefinSans Light'; 3 | src: url(./font/JosefinSans-Light.ttf); 4 | } 5 | 6 | * { 7 | margin: 0; 8 | padding: 0; 9 | box-sizing: border-box; 10 | } 11 | 12 | body { 13 | height: 100vh; 14 | display: flex; 15 | justify-content: center; 16 | align-items: center; 17 | font-family: 'JosefinSans Light'; 18 | background: url('./image/bg1.jpg'); 19 | background-size: cover; 20 | } 21 | 22 | .player { 23 | width: 380px; 24 | height: 280px; 25 | position: relative; 26 | overflow: hidden; 27 | border-radius: 5px; 28 | box-shadow: 5px 5px 15px rgb(54 79 60 / 40%); 29 | transition: all 0.5s ease-in-out; 30 | } 31 | 32 | .player .img { 33 | width: 100%; 34 | height: 100%; 35 | user-select: none; 36 | } 37 | 38 | .player .img img { 39 | width: 100%; 40 | height: 100%; 41 | object-fit: cover; 42 | user-select: none; 43 | transition: .5s all ease-in-out; 44 | } 45 | 46 | .player .info { 47 | width: 100%; 48 | height: 120px; 49 | background-color: #fff; 50 | opacity: 0.9; 51 | position: absolute; 52 | bottom: 0; 53 | transform: translateY(35px); 54 | transition: .5s all ease-in-out; 55 | } 56 | 57 | .player:hover .info { 58 | transform: translateY(0px); 59 | } 60 | 61 | .player:hover .img img { 62 | transform: scale(1.1); 63 | } 64 | 65 | .info .progress { 66 | height: 34px; 67 | display: flex; 68 | justify-content: center; 69 | align-items: center; 70 | user-select: none; 71 | } 72 | 73 | .info .progress #start, 74 | .info .progress #end { 75 | margin: 0 12px; 76 | user-select: none; 77 | } 78 | 79 | .info .progress #bar { 80 | width: 300px; 81 | height: 8px; 82 | border-radius: 4px; 83 | background-color: rgb(222, 230, 238); 84 | } 85 | 86 | .info .song-detail { 87 | display: flex; 88 | justify-content: center; 89 | align-items: center; 90 | flex-direction: column; 91 | } 92 | 93 | .info .song-detail span { 94 | margin: 4px 0; 95 | height: 16px; 96 | user-select: none; 97 | } 98 | 99 | .info .song-detail #title { 100 | font-size: 16px; 101 | font-weight: 900; 102 | letter-spacing: 2px; 103 | } 104 | 105 | .info .song-detail #author { 106 | letter-spacing: 1px; 107 | } 108 | 109 | .info .controls { 110 | margin-top: 12px; 111 | padding: 0 8px; 112 | display: flex; 113 | justify-content: space-between; 114 | align-items: center; 115 | } 116 | 117 | .info .controls .play { 118 | display: flex; 119 | justify-content: space-between; 120 | align-items: center; 121 | } 122 | 123 | .info .controls .play span { 124 | margin: 0 16px; 125 | cursor: pointer; 126 | } 127 | 128 | .info .controls span { 129 | user-select: none; 130 | } 131 | 132 | /* 隐藏audio */ 133 | .audio { 134 | position: absolute; 135 | z-index: -1; 136 | top: 0; 137 | left: 0; 138 | } 139 | -------------------------------------------------------------------------------- /17.响应式页面模板/README.md: -------------------------------------------------------------------------------- 1 | # 一、响应式页面出现的背景 2 | ## 几年前,我们看到的网站还都是固定宽度的,目标是让所有用户都拥有相同的体验。这种固定宽度(通常为960像素左右) 3 | ## 面对不断扩展的浏览器和设备,我们还是有应对方案的。这个方案就是基于HTML5和CSS3的响应式Web设计。 4 | ## 响应式Web设计可以让一个网站同时适配多种设备和多个屏幕,可以让网站的布局和功能随用户的使用环境(屏幕大小、输入方式、设备/浏览器能力)而变化。 5 |
6 | 7 | # 二、什么是响应式页面 8 | ## 所谓响应式Web设计,就是网页内容会随着访问它的视口及设备的不同而呈现不同的样式。 9 | ## 最初,响应式设计是从“桌面”、固定宽度设计开始的。然后,到了小屏幕上,内容会重排,或者根据情况隐藏部分内容。 10 | ## 可是,随着时间推移,人们发现,还是采用相反的设计思路更好,即先为小屏幕设计内容、样式,然后再向大屏幕扩展。 11 |
12 | 13 | # 三、实现响应式页面需要的几个条件 14 | ## 1. 弹性布局 15 | ## 2. 弹性图片 16 | ## 3. 媒体查询 17 |
18 | 19 | 20 | # 四、浏览器对于响应式Web设计的支持 21 | ## 浏览器支持一直是响应式Web设计面临的最大问题。 22 | ## 市面上如此多的浏览器和设备,要想一个不落地支持并不现实。有时候是时间问题,有时候是预算问题,有时候两方面问题都有。 23 | ## 能不能适配某个旧平台/版本不是问题,问题在于是否应该去适配它。 24 | ## 在通常情况下,我们写的网站必须在所有常用浏览器里表现正常。除了基本功能,有必要提前确定针对哪个平台要实现最强的功能,以便对其他平台上的视觉和功能作出相应取舍。 25 |
26 | 27 | 28 | # 四、相关书籍推荐 29 | ## 《响应式Web设计:HTML5和CSS3实战(第2版)》 30 |
31 | 32 | 33 | # 五、经典的响应式页面案例 34 |
-------------------------------------------------------------------------------- /17.响应式页面模板/font/Merienda-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/font/Merienda-Regular.ttf -------------------------------------------------------------------------------- /17.响应式页面模板/icon/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "iconfont"; /* Project id */ 3 | src: url('iconfont.ttf?t=1666183909082') format('truetype'); 4 | } 5 | 6 | .iconfont { 7 | font-family: "iconfont" !important; 8 | font-size: 16px; 9 | font-style: normal; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | .icon-menu2:before { 15 | content: "\e609"; 16 | } 17 | 18 | .icon-geren:before { 19 | content: "\e61d"; 20 | } 21 | 22 | .icon-geren1:before { 23 | content: "\e603"; 24 | } 25 | 26 | .icon-mulu:before { 27 | content: "\e62f"; 28 | } 29 | 30 | -------------------------------------------------------------------------------- /17.响应式页面模板/icon/iconfont.js: -------------------------------------------------------------------------------- 1 | window._iconfont_svg_string_='',function(n){var e=(e=document.getElementsByTagName("script"))[e.length-1],t=e.getAttribute("data-injectcss"),e=e.getAttribute("data-disable-injectsvg");if(!e){var o,i,c,s,d,a=function(e,t){t.parentNode.insertBefore(e,t)};if(t&&!n.__iconfont__svg__cssinject__){n.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(e){console&&console.log(e)}}o=function(){var e,t=document.createElement("div");t.innerHTML=n._iconfont_svg_string_,(t=t.getElementsByTagName("svg")[0])&&(t.setAttribute("aria-hidden","true"),t.style.position="absolute",t.style.width=0,t.style.height=0,t.style.overflow="hidden",t=t,(e=document.body).firstChild?a(t,e.firstChild):e.appendChild(t))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(c=o,s=n.document,d=!1,r(),s.onreadystatechange=function(){"complete"==s.readyState&&(s.onreadystatechange=null,l())})}function l(){d||(d=!0,c())}function r(){try{s.documentElement.doScroll("left")}catch(e){return void setTimeout(r,50)}l()}}(window); -------------------------------------------------------------------------------- /17.响应式页面模板/icon/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "name": "", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "2529702", 10 | "name": "目录、导航", 11 | "font_class": "menu2", 12 | "unicode": "e609", 13 | "unicode_decimal": 58889 14 | }, 15 | { 16 | "icon_id": "3376390", 17 | "name": "个人", 18 | "font_class": "geren", 19 | "unicode": "e61d", 20 | "unicode_decimal": 58909 21 | }, 22 | { 23 | "icon_id": "6289726", 24 | "name": "个人", 25 | "font_class": "geren1", 26 | "unicode": "e603", 27 | "unicode_decimal": 58883 28 | }, 29 | { 30 | "icon_id": "6582329", 31 | "name": "目录", 32 | "font_class": "mulu", 33 | "unicode": "e62f", 34 | "unicode_decimal": 58927 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /17.响应式页面模板/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/icon/iconfont.ttf -------------------------------------------------------------------------------- /17.响应式页面模板/image/Jisoo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/image/Jisoo.jpg -------------------------------------------------------------------------------- /17.响应式页面模板/image/bg-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/image/bg-1.jpg -------------------------------------------------------------------------------- /17.响应式页面模板/image/bg-2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/image/bg-2.jpg -------------------------------------------------------------------------------- /17.响应式页面模板/image/chetaixian.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/image/chetaixian.jpg -------------------------------------------------------------------------------- /17.响应式页面模板/image/dingyiyu.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/image/dingyiyu.jpg -------------------------------------------------------------------------------- /17.响应式页面模板/image/luowenji.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/17.响应式页面模板/image/luowenji.jpg -------------------------------------------------------------------------------- /17.响应式页面模板/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 响应式页面模板 10 | 11 | 12 | 13 |
14 | 15 | 16 | 51 | 52 | 53 |
54 | Hello Friends 55 | “响应式Web设计”这个名字是Ethan Marcotte在2010年发明的。当时, 他在A List Apart上写了一篇文章, 这篇文章综合运用了三种已有技术 (弹性网格布局、弹性图片/媒体、媒体查询) 实现了一个解决方案, 就叫“响应式Web设计”。所谓响应式Web设计, 就是网页内容会随着访问它的视口及设备的不同而呈现不同的样式。 56 |
57 | 58 | 59 |
60 |
61 | 62 | well-known saying of a famous person 63 |
64 |
65 |
66 | Cicero 67 | The best advice for young people is to make them modest and prudent, honor their parents, and love their relatives and friends. 68 |
69 |
70 | Montaigne 71 | One must have three heads, a natural mind, a mind that comes from a book, and a mind that comes from life. 72 |
73 |
74 | Marx 75 | Friendship is like the fog of the morning, the flattery is not friendship, the friendship can only be used to consolidate it. 76 |
77 |
78 |
79 | 80 | 81 |
82 |
83 |
84 | 85 |
86 |
87 | Che Tai Xian 88 | Actor 89 |
90 |
91 |
92 |
93 | 94 |
95 |
96 | Luo Wen Ji 97 | Actor 98 |
99 |
100 |
101 |
102 | 103 |
104 |
105 | Ding Yi Yu 106 | Actor 107 |
108 |
109 |
110 |
111 | 112 |
113 |
114 | Jisoo 115 | Idol 116 |
117 |
118 |
119 | 120 | 121 |
122 | 123 | 124 | 125 | 126 | -------------------------------------------------------------------------------- /17.响应式页面模板/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | 4 | const bread = doc.querySelector('#bread'); // 面包按钮 5 | const drop = doc.querySelector('#drop'); // 下拉菜单 6 | 7 | doc.addEventListener('click', e => { 8 | drop.classList.remove('drop-show'); 9 | }); 10 | 11 | // 点击事件, 显示/隐藏下拉菜单 12 | bread.addEventListener('click', e => { 13 | e.stopPropagation(); 14 | drop.classList.toggle('drop-show'); 15 | }); 16 | 17 | 18 | // // 监听页面尺寸变化,动态修改 html 下 font-size 大小 19 | // window.onresize = () => { 20 | // setHtmlFontSize(); 21 | // }; 22 | 23 | // function setHtmlFontSize() { 24 | // const clientWidth = doc.body.clientWidth; // 获取 body 宽度 25 | // doc.querySelector('html').style.fontSize = clientWidth / 100 + 'px'; 26 | // } 27 | 28 | // // 页面初始化时执行一次 29 | // setHtmlFontSize(); -------------------------------------------------------------------------------- /17.响应式页面模板/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'Merienda-Regular'; 3 | src: url(./font/Merienda-Regular.ttf); 4 | } 5 | 6 | :root { 7 | --nav-bg-color: #222; 8 | --nav-text-color: #fff; 9 | --nav-menu-letter-spacing: 1px; 10 | --nav-text-hover-color: rgb(8, 198, 251); 11 | } 12 | 13 | * { 14 | margin: 0; 15 | padding: 0; 16 | box-sizing: border-box; 17 | } 18 | 19 | html { 20 | /* 这是设置了字体大小,既 1rem = 16px */ 21 | font-size: 16px; 22 | } 23 | 24 | body { 25 | height: 100vh; 26 | } 27 | 28 | /* 页面滚动条不显示 */ 29 | ::-webkit-scrollbar { 30 | width: 0; 31 | } 32 | 33 | /* 导航栏(正经导航栏部分 + 下拉菜单部分) */ 34 | .container .nav { 35 | width: 100%; 36 | height: 3.75rem; 37 | background-color: var(--nav-bg-color); 38 | position: fixed; 39 | top: 0; 40 | } 41 | 42 | /* 导航栏内容 */ 43 | .container .nav .container { 44 | height: 100%; 45 | padding: 0 2.25rem; 46 | display: flex; 47 | justify-content: space-between; 48 | align-items: center; 49 | } 50 | 51 | /* 导航栏左侧 */ 52 | .nav .nav-left .title { 53 | font-size: 1.25rem; 54 | font-weight: 900; 55 | color: var(--nav-text-color); 56 | user-select: none; 57 | letter-spacing: var(--nav-menu-letter-spacing); 58 | } 59 | 60 | /* 导航栏右侧菜单 */ 61 | .nav .nav-right { 62 | display: none; 63 | } 64 | 65 | .nav-right .first li { 66 | transition: all .2s ease-in-out; 67 | } 68 | 69 | .nav-right .first li:hover { 70 | color: var(--nav-text-hover-color); 71 | } 72 | 73 | /* 74 | 导航栏右侧 75 | 默认不显示、当浏览器最小宽度达到768px时显示 76 | */ 77 | @media(min-width: 768px) { 78 | .nav .nav-right { 79 | display: block; 80 | } 81 | 82 | .nav .nav-right .first { 83 | display: flex; 84 | justify-content: center; 85 | align-items: center; 86 | list-style: none; 87 | } 88 | 89 | .nav-right .first li { 90 | color: var(--nav-text-color); 91 | font-size: 1rem; 92 | margin: 0 1rem; 93 | user-select: none; 94 | cursor: pointer; 95 | letter-spacing: var(--nav-menu-letter-spacing); 96 | } 97 | } 98 | 99 | /* 100 | 面包按钮 101 | 默认显示,当浏览器最小宽度达到768px时隐藏 102 | */ 103 | .nav .bread-btn { 104 | width: 1.25rem; 105 | height: 1.25rem; 106 | cursor: pointer; 107 | } 108 | 109 | .nav .bread-btn .icon-menu2 { 110 | color: #fff; 111 | font-size: 1.375rem; 112 | transition: all .2s ease-in-out; 113 | } 114 | 115 | .nav .bread-btn:hover .icon-menu2 { 116 | color: var(--nav-text-hover-color); 117 | } 118 | 119 | @media(min-width: 768px) { 120 | .nav .bread-btn { 121 | display: none; 122 | } 123 | } 124 | 125 | /* 下拉菜单 */ 126 | .drop { 127 | visibility: hidden; 128 | opacity: 0; 129 | transition: all .3s ease-in-out; 130 | } 131 | 132 | .drop .drop-menu { 133 | list-style: none; 134 | border-top: 1px solid rgba(255, 255, 255, .02); 135 | } 136 | 137 | .drop .drop-menu li { 138 | color: var(--nav-text-color); 139 | background-color: var(--nav-bg-color); 140 | padding: 0.75rem 2.25rem; 141 | user-select: none; 142 | cursor: pointer; 143 | letter-spacing: var(--nav-menu-letter-spacing); 144 | transition: all .2s ease-in-out; 145 | } 146 | 147 | .drop .drop-menu li:hover { 148 | background-color: var(--nav-text-hover-color); 149 | color: #fff; 150 | } 151 | 152 | /* 用于控制下拉菜单是否显示 */ 153 | .drop-show { 154 | visibility: visible; 155 | opacity: 1; 156 | } 157 | 158 | /* 页面设置统一高度 */ 159 | .page { 160 | height: 100vh; 161 | } 162 | 163 | /* 首页 */ 164 | .home-page { 165 | background: url('./image/bg-1.jpg'); 166 | background-size: cover; 167 | display: flex; 168 | justify-content: center; 169 | align-items: center; 170 | flex-direction: column; 171 | padding: 0 4.375rem; 172 | } 173 | 174 | .home-page span { 175 | color: #fff; 176 | } 177 | 178 | .home-page .info { 179 | font-size: 1.5rem; 180 | font-weight: 700; 181 | font-family: 'Merienda-Regular'; 182 | letter-spacing: 0.25rem; 183 | user-select: none; 184 | } 185 | 186 | .home-page .sub-info { 187 | font-size: 1rem; 188 | font-family: 'Merienda-Regular'; 189 | letter-spacing: 0.125rem; 190 | line-height: 2; 191 | margin-top: 1.5rem; 192 | user-select: none; 193 | } 194 | 195 | /* 196 | 当浏览器视口宽度大于520px小于768px,字体变大一丢丢 197 | */ 198 | @media(min-width: 520px) { 199 | .home-page .info { 200 | font-size: 2rem; 201 | } 202 | 203 | .home-page .sub-info { 204 | font-size: 1.125rem; 205 | } 206 | } 207 | 208 | /* 209 | 当浏览器视口宽度大于768px,字体变大 210 | */ 211 | @media(min-width: 768px) { 212 | .home-page .info { 213 | font-size: 2.625rem; 214 | } 215 | 216 | .home-page .sub-info { 217 | font-size: 1.25rem; 218 | } 219 | } 220 | 221 | /* 名言警句页面 */ 222 | .first-page { 223 | background-color: #fff; 224 | display: flex; 225 | justify-content: center; 226 | align-items: center; 227 | flex-direction: column; 228 | } 229 | 230 | .first-page .title { 231 | font-size: 1.25rem; 232 | font-weight: 900; 233 | height: 3rem; 234 | line-height: 1.5; 235 | user-select: none; 236 | text-align: center; 237 | } 238 | 239 | .first-page .title .icon-geren1 { 240 | font-size: 1rem; 241 | margin-right: 0.25rem; 242 | } 243 | 244 | /* 245 | 视口宽度小于768px时,标题字体调小 246 | 大于768px时,标题字体调大一丢丢 247 | */ 248 | @media(min-width: 768px) { 249 | .first-page .title { 250 | font-size: 1.5rem; 251 | } 252 | 253 | .first-page .title .icon-geren1 { 254 | font-size: 1.125rem; 255 | } 256 | } 257 | 258 | .first-page .sentence-list { 259 | width: 100%; 260 | padding: 0 1.875rem; 261 | display: flex; 262 | justify-content: center; 263 | align-items: center; 264 | flex-direction: column; 265 | } 266 | 267 | /* 268 | 视口宽度小于768px时,竖着排, 269 | 大于768px时,横着排 270 | */ 271 | @media(min-width: 768px) { 272 | .first-page .sentence-list { 273 | flex-direction: row; 274 | margin-top: 3.75rem; 275 | } 276 | } 277 | 278 | .first-page .sentence-list .item { 279 | display: flex; 280 | flex-direction: column; 281 | margin: 2.5rem 1.875rem; 282 | } 283 | 284 | /* 285 | 视口宽度小于768px时,不设置item的宽度高度, 286 | 大于768px时,设置固定宽高 287 | */ 288 | @media(min-width: 768px) { 289 | .first-page .sentence-list .item { 290 | width: 20rem; 291 | height: 18.75rem; 292 | margin: 0 2.25rem; 293 | } 294 | } 295 | 296 | .sentence-list .item .author { 297 | text-align: center; 298 | font-size: 1rem; 299 | font-weight: 900; 300 | } 301 | 302 | .sentence-list .item .words { 303 | font-size: 0.875rem; 304 | margin-top: 1rem; 305 | line-height: 1.5; 306 | color: #8e8a8a; 307 | text-align: center; 308 | } 309 | 310 | /* yao叔追星页面 */ 311 | .second-page { 312 | background-color: #f7f7f7; 313 | display: flex; 314 | flex-direction: column; 315 | justify-content: space-around; 316 | align-items: center; 317 | padding: 0 1.25rem; 318 | overflow: auto; 319 | height: max-content; 320 | min-height: 100vh; 321 | } 322 | 323 | .second-page .box { 324 | width: 20rem; 325 | height: 28.75rem; 326 | border-radius: 0.375rem; 327 | overflow: hidden; 328 | background-color: #fff; 329 | display: flex; 330 | flex-direction: column; 331 | margin: 2.25rem 0; 332 | } 333 | 334 | .box .img { 335 | height: 23.75rem; 336 | } 337 | 338 | /* 339 | 视口宽度大于728px小于960时,一行排列两张图片, 340 | */ 341 | @media(min-width: 728px) { 342 | .second-page { 343 | align-items: center; 344 | flex-direction: row; 345 | flex-wrap: wrap; 346 | } 347 | 348 | .second-page .box { 349 | width: 20rem; 350 | height: 28.75rem; 351 | } 352 | 353 | .box .img { 354 | height: 23.75rem; 355 | } 356 | } 357 | 358 | /* 359 | 视口宽度大于960px时,四张图片呈一排排列, 360 | 小于768px时,设置固定宽高 361 | */ 362 | @media(min-width: 960px) { 363 | .second-page { 364 | align-items: center; 365 | } 366 | 367 | .second-page .box { 368 | width: 13.75rem; 369 | height: 22.5rem; 370 | } 371 | 372 | .box .img { 373 | height: 17.5rem; 374 | } 375 | } 376 | 377 | .box .img img { 378 | width: 100%; 379 | height: 100%; 380 | object-fit: cover; 381 | } 382 | 383 | .box .comment { 384 | flex: 1; 385 | display: flex; 386 | justify-content: center; 387 | align-items: center; 388 | flex-direction: column; 389 | } 390 | 391 | .box .comment .name { 392 | font-size: 1rem; 393 | font-family: 'Merienda-Regular'; 394 | color: #000; 395 | } 396 | 397 | .box .comment .job { 398 | font-size: 0.875rem; 399 | font-family: 'Merienda-Regular'; 400 | color: #968f8f; 401 | margin-top: 0.5rem; 402 | } 403 | 404 | -------------------------------------------------------------------------------- /2.樱花飞舞/image/bg1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/2.樱花飞舞/image/bg1.jpg -------------------------------------------------------------------------------- /2.樱花飞舞/image/sakura.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/2.樱花飞舞/image/sakura.png -------------------------------------------------------------------------------- /2.樱花飞舞/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 浪漫樱花飞舞 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /2.樱花飞舞/script.js: -------------------------------------------------------------------------------- 1 | // 获取canvas元素 2 | const canvas = document.querySelector('canvas'); 3 | 4 | // 设置canvas画布的宽高为浏览器视口宽高 5 | canvas.width = window.innerWidth; 6 | canvas.height = window.innerHeight; 7 | 8 | // 使用2d的绘图方式 9 | const ctx = canvas.getContext('2d'); 10 | 11 | // 定义花瓣的数量 12 | const SAKURA_SUM = 60; 13 | // 花瓣数组 14 | const sakuraArray = []; 15 | 16 | /** 17 | * 定义花瓣类 18 | */ 19 | class Sakura { 20 | // 构造方法 21 | constructor() { 22 | // 随机生成花瓣的x, y坐标 23 | this.x = Math.random() * canvas.width; 24 | this.y = (Math.random() * canvas.height * 2) - canvas.height; 25 | // 随机生成花瓣的宽高 26 | this.width = Math.random() * 15 + 25; 27 | this.height = Math.random() * 12 + 20; 28 | // 随机透明度 29 | this.opacity = this.w / 50; 30 | // 设置一个随机数,后面实现旋转角度效果时会用到 31 | this.rotate = Math.random(); 32 | // 速度初始化 33 | this.xSpeed = Math.random() * 2 + 1; 34 | this.ySpeed = Math.random() + 1.5; 35 | this.rotateSpeed = Math.random() * 0.02; 36 | } 37 | 38 | // 绘制 39 | draw() { 40 | // 当花瓣超过canvas画布边界后,重新设置花瓣的坐标、速度、和转速 41 | if (this.x > canvas.width || this.y > canvas.height) { 42 | this.x = -sakuraImg.width; // 刚好藏住 43 | this.y = (Math.random() * canvas.height * 2) - canvas.height; 44 | this.rotate = Math.random(); 45 | this.rotateSpeed = Math.random() * 0.02; 46 | this.xSpeed = Math.random() * 2 + 0.5; 47 | this.ySpeed = Math.random() + 1; 48 | } 49 | // 设置整个canvas透明度基数 50 | ctx.globalAlpha = this.opacity; 51 | ctx.drawImage( 52 | sakuraImg, 53 | this.x, 54 | this.y, 55 | this.width * (0.6 + (Math.abs(Math.cos(this.rotate)) / 3)), 56 | this.height * (0.8 + (Math.abs(Math.sin(this.rotate)) / 5)) 57 | ) 58 | } 59 | 60 | animate() { 61 | this.x += this.xSpeed + mouseX * 5; 62 | this.y += this.ySpeed + mouseX * 2; 63 | this.rotate += this.rotateSpeed; 64 | this.draw(); 65 | } 66 | } 67 | 68 | /** 69 | * 定义渲染方法 70 | */ 71 | function render() { 72 | // 清除矩形内的内容 - 清空屏幕 73 | ctx.clearRect(0, 0, canvas.width, canvas.height); 74 | sakuraArray.forEach(sakura => sakura.animate()); 75 | // 该方法会高速浏览器在重绘之前调用指定的函数 76 | // 这样可以保证在浏览器的刷新频率下去更新动画; 77 | window.requestAnimationFrame(render); 78 | } 79 | 80 | // 加载花瓣图片 81 | const sakuraImg = new Image(); 82 | sakuraImg.src = './image/sakura.png'; 83 | // 等花瓣图片加载完毕,将数目为SAKURA_SUM的花瓣实例保存到数组中 84 | sakuraImg.addEventListener('load', () => { 85 | for (let i = 0; i < SAKURA_SUM; i++) { 86 | sakuraArray.push(new Sakura()) 87 | } 88 | render(); 89 | }); 90 | 91 | 92 | // 监听浏览器窗口大小变化,重新设置canvas的宽高 93 | window.addEventListener('resize', () => { 94 | canvas.width = window.innerWidth; 95 | canvas.height = window.innerHeight; 96 | }); 97 | 98 | let mouseX = 0; 99 | function touchHandler(e) { 100 | // clinetX: 客户端区域的水平坐标 (与页面坐标不同) 101 | mouseX = (e.clientX || e.touches[0].clientX) / window.innerWidth; 102 | } 103 | // mousemove:鼠标移动的事件 104 | window.addEventListener('mousemove', touchHandler); 105 | // touchmove;触点在触屏上移动的事件 106 | window.addEventListener('touchmove', touchHandler); 107 | -------------------------------------------------------------------------------- /2.樱花飞舞/style.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | background-image: url(./image/bg1.jpg); 6 | background-size: cover; 7 | overflow: hidden; 8 | } -------------------------------------------------------------------------------- /3.3D卡片翻转效果-王心凌爱你/font/IndieFlower.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/3.3D卡片翻转效果-王心凌爱你/font/IndieFlower.ttf -------------------------------------------------------------------------------- /3.3D卡片翻转效果-王心凌爱你/image/wxl-1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/3.3D卡片翻转效果-王心凌爱你/image/wxl-1.jpg -------------------------------------------------------------------------------- /3.3D卡片翻转效果-王心凌爱你/image/wxl-3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/3.3D卡片翻转效果-王心凌爱你/image/wxl-3.jpg -------------------------------------------------------------------------------- /3.3D卡片翻转效果-王心凌爱你/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 3D卡片翻转效果-王心凌爱你 9 | 10 | 11 |
12 | 13 |
14 | 15 | 16 |
17 | 18 | 19 |
20 | 21 |
22 | 27 | 28 |
29 | 30 | 31 |
32 | 《爱你》 33 | 王心凌 34 |
35 |
36 |
37 | 38 | 39 | Cyndi Wang 40 | 41 | -------------------------------------------------------------------------------- /3.3D卡片翻转效果-王心凌爱你/style.css: -------------------------------------------------------------------------------- 1 | /* 引入谷歌字体 */ 2 | @font-face { 3 | /* 定义个名字,因为我最近比较喜欢mamamoo的wind flower,故以此命名 */ 4 | font-family: 'windflower'; 5 | src: url(./font/IndieFlower.ttf); 6 | } 7 | 8 | * { 9 | margin: 0; 10 | padding: 0; 11 | box-sizing: border-box; 12 | } 13 | 14 | body { 15 | height: 100vh; 16 | /* body内的内容水平垂直居中 */ 17 | display: flex; 18 | justify-content: center; 19 | align-items: center; 20 | /* 渐变背景色 */ 21 | background-image: linear-gradient(to top, #fdcbf1 0%, #fdcbf1 1%, #e6dee9 100%); 22 | position: relative; 23 | overflow: hidden; 24 | } 25 | 26 | .container { 27 | position: relative; 28 | width: 300px; 29 | height: 450px; 30 | background: #fff; 31 | box-shadow: 10px 20px 40px rgba(0, 0, 0, 0.25); 32 | /* 加上过渡效果 */ 33 | transition: all 1s ease-in-out; 34 | } 35 | 36 | .img-box { 37 | width: 100%; 38 | height: 100%; 39 | background: #000; 40 | /* 设置变形的原点为图片盒子的左侧 */ 41 | transform-origin: left; 42 | /* 指示元素的子元素应位于 3d 空间中 */ 43 | transform-style: preserve-3d; 44 | /* 加上过渡效果 */ 45 | transition: all 1s ease-in-out; 46 | } 47 | 48 | .img-box img { 49 | position: absolute; 50 | top: 0; 51 | left: 0; 52 | width: 100%; 53 | height: 100%; 54 | /* 在保持其宽高比的同时填充于元素的整个内容框 */ 55 | object-fit: cover; 56 | transform-style: preserve-3d; 57 | /* 背面朝用户时不可见 */ 58 | backface-visibility: hidden; 59 | } 60 | 61 | /* 第二张图片旋转180度,这样使其看不见 */ 62 | .img-box img:nth-child(2) { 63 | transform: rotateY(180deg); 64 | } 65 | 66 | /* 鼠标移动到容器上后,container向右移动自己宽度的50% */ 67 | .container:hover { 68 | transform: translateX(50%); 69 | } 70 | 71 | /* 72 | 鼠标移动到container上后, img-box绕Y轴方向旋转180度, 73 | 此时背后的图片显示,正面的图片隐藏 74 | */ 75 | .container:hover .img-box { 76 | transform: rotateY(180deg); 77 | } 78 | 79 | .right { 80 | position: absolute; 81 | top: 0; 82 | left: 0; 83 | width: 100%; 84 | height: 100%; 85 | padding: 3px; 86 | padding-top: 0px; 87 | /* 降低层级,使其出现在图片div的下方 */ 88 | z-index: -1; 89 | } 90 | 91 | .right .video-container { 92 | width: 100%; 93 | height: 240px; 94 | background: green; 95 | border-radius: 5px; 96 | overflow: hidden; 97 | } 98 | 99 | .right .video-container video { 100 | width: 100%; 101 | height: 100%; 102 | /* 在保持其宽高比的同时填充于元素的整个内容框 */ 103 | object-fit: cover; 104 | } 105 | 106 | .right .text { 107 | width: 100%; 108 | margin-top: 50px; 109 | display: flex; 110 | flex-direction: column; 111 | align-items: center; 112 | color: #ffb0b0; 113 | /* 用户无法选中字体 */ 114 | user-select: none; 115 | } 116 | 117 | /* 第一个span的样式 */ 118 | .right .text span:first-child { 119 | font-size: 20px; 120 | font-family: 700; 121 | letter-spacing: 6px; 122 | } 123 | 124 | /* 第二个span的样式 */ 125 | .right .text span:last-child { 126 | font-size: 16px; 127 | letter-spacing: 2px; 128 | margin-top: 10px; 129 | } 130 | 131 | .water-mark { 132 | position: absolute; 133 | z-index: -1; 134 | top: 50%; 135 | left: 47%; 136 | transform: translate(-50%, -50%) rotate(-20deg); 137 | font-size: 120px; 138 | font-weight: 700; 139 | font-family: 'windflower'; 140 | color: #fff; 141 | letter-spacing: 80px; 142 | /* 不换行 */ 143 | white-space: nowrap; 144 | } 145 | -------------------------------------------------------------------------------- /4.高考加油/image/bg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/4.高考加油/image/bg.jpg -------------------------------------------------------------------------------- /4.高考加油/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 【高考加油】看着还算比较逼真的折角效果 9 | 10 | 11 |
12 |
13 | 14 |
15 | 16 |
17 | 三年寒窗苦读日, 18 | 只盼金榜题名时。 19 | 高考加油! 20 | —小yao老师 21 |
22 | 23 | 24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | 32 | -------------------------------------------------------------------------------- /4.高考加油/style.css: -------------------------------------------------------------------------------- 1 | :root { 2 | /* 定义好变量,后面会用到 */ 3 | --content-top: 50px; 4 | } 5 | 6 | /* 样式初始化 */ 7 | * { 8 | margin: 0; 9 | padding: 0; 10 | box-sizing: border-box; 11 | } 12 | 13 | body { 14 | height: 100vh; 15 | background-image: url(./image/bg.jpg); 16 | background-size: cover; 17 | } 18 | 19 | .container { 20 | width: 100%; 21 | height: 100%; 22 | padding: 30px 20px; 23 | } 24 | 25 | .container .page { 26 | width: 390px; 27 | height: 520px; 28 | overflow: hidden; 29 | background: #fff; 30 | /* 水平居中 */ 31 | margin: 0 auto; 32 | margin-top: 50px; 33 | position: relative; 34 | /* 通过渐变色的效果来设置折纸两侧的颜色 */ 35 | background: linear-gradient(-150deg, transparent 45px, #fff 0); 36 | transition: all .2s ease-in-out; 37 | } 38 | 39 | .container .page:hover { 40 | transform: scale(1.1); 41 | } 42 | 43 | /* 折角 */ 44 | .container .page::after { 45 | content: ''; 46 | position: absolute; 47 | top: 0; 48 | right: 0; 49 | background: linear-gradient( 50 | to left bottom, 51 | transparent 50%, 52 | rgb(198, 193, 193) 0) no-repeat; 53 | /* 这里根据yao老师亲手话的 《图解1.png》进行计算得出 */ 54 | width: 52px; 55 | height: 90px; 56 | /* 以右下角为原点 */ 57 | transform-origin: bottom right; 58 | /* 59 | 先把角度30度调好,然后图省事的话就直接在页面上调偏移量 60 | 这里注意 rotate 和 translateY 的先后顺序,顺序不一样结果是不一样的 61 | */ 62 | transform: translateY(-39px) rotate(-30deg); 63 | } 64 | 65 | .page .lines { 66 | margin-top: var(--content-top); 67 | padding-left: 60px; 68 | height: calc(520px - var(--content-top)); 69 | /* 70 | 画线 71 | */ 72 | background-image: repeating-linear-gradient( 73 | white 0, 74 | white 23.5px, 75 | steelblue 25px 76 | ); 77 | } 78 | 79 | .page .text { 80 | position: absolute; 81 | top: 20%; 82 | left: 50%; 83 | transform: translateX(-50%); 84 | z-index: 10; 85 | display: flex; 86 | justify-content: center; 87 | } 88 | 89 | .page .text span { 90 | font-size: 32px; 91 | font-weight: 500; 92 | font-family: KaiTi; 93 | letter-spacing: 12px; 94 | margin: 0 16px; 95 | color: rgb(8, 8, 215); 96 | /* 文字垂直排列 */ 97 | writing-mode: vertical-lr; 98 | } 99 | 100 | .page .text span:last-child { 101 | font-size: 22px; 102 | /* 下端对齐 */ 103 | align-self: flex-end; 104 | letter-spacing: 2px; 105 | position: relative; 106 | bottom: 30px; 107 | left: 16px; 108 | } 109 | 110 | /* 设置红色竖线 */ 111 | .page::before { 112 | content: ''; 113 | position: absolute; 114 | height: 100%; 115 | background: rgb(240, 152, 152); 116 | margin-left: 48px; 117 | width: 2px; 118 | } 119 | 120 | .page .holes { 121 | position: absolute; 122 | height: 100%; 123 | width: 48px; 124 | margin-top: 1px; 125 | margin-bottom: 1px; 126 | top: 0; 127 | left: 0; 128 | } 129 | 130 | .page .holes .hole { 131 | position: absolute; 132 | left: 12.5px; 133 | width: 20px; 134 | height: 20px; 135 | border-radius: 50%; 136 | background: gainsboro; 137 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2); 138 | } 139 | 140 | /* 第一个洞 */ 141 | .page .holes .hole:nth-child(1) { 142 | top: 50px; 143 | } 144 | 145 | /* 第二个洞 */ 146 | .page .holes .hole:nth-child(2) { 147 | top: 260px; 148 | } 149 | 150 | /* 第三个洞 */ 151 | .page .holes .hole:nth-child(3) { 152 | top: 470px; 153 | } -------------------------------------------------------------------------------- /4.高考加油/图解1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/4.高考加油/图解1.png -------------------------------------------------------------------------------- /5.新拟态登录界面/icon/iconfont.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "iconfont"; /* Project id */ 3 | src: url('iconfont.ttf?t=1653988132919') format('truetype'); 4 | } 5 | 6 | .iconfont { 7 | font-family: "iconfont" !important; 8 | font-size: 16px; 9 | font-style: normal; 10 | -webkit-font-smoothing: antialiased; 11 | -moz-osx-font-smoothing: grayscale; 12 | } 13 | 14 | .icon-github3:before { 15 | content: "\e743"; 16 | } 17 | 18 | .icon-tuitetwitter44:before { 19 | content: "\e708"; 20 | } 21 | 22 | .icon-weibo:before { 23 | content: "\e64b"; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /5.新拟态登录界面/icon/iconfont.js: -------------------------------------------------------------------------------- 1 | !function(t){var e,n,o,i,c,s='',d=(d=document.getElementsByTagName("script"))[d.length-1].getAttribute("data-injectcss"),a=function(t,e){e.parentNode.insertBefore(t,e)};if(d&&!t.__iconfont__svg__cssinject__){t.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}function l(){c||(c=!0,o())}function r(){try{i.documentElement.doScroll("left")}catch(t){return void setTimeout(r,50)}l()}e=function(){var t,e=document.createElement("div");e.innerHTML=s,s=null,(e=e.getElementsByTagName("svg")[0])&&(e.setAttribute("aria-hidden","true"),e.style.position="absolute",e.style.width=0,e.style.height=0,e.style.overflow="hidden",e=e,(t=document.body).firstChild?a(e,t.firstChild):t.appendChild(e))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(e,0):(n=function(){document.removeEventListener("DOMContentLoaded",n,!1),e()},document.addEventListener("DOMContentLoaded",n,!1)):document.attachEvent&&(o=e,i=t.document,c=!1,r(),i.onreadystatechange=function(){"complete"==i.readyState&&(i.onreadystatechange=null,l())})}(window); -------------------------------------------------------------------------------- /5.新拟态登录界面/icon/iconfont.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "", 3 | "name": "", 4 | "font_family": "iconfont", 5 | "css_prefix_text": "icon-", 6 | "description": "", 7 | "glyphs": [ 8 | { 9 | "icon_id": "400807", 10 | "name": "github3", 11 | "font_class": "github3", 12 | "unicode": "e743", 13 | "unicode_decimal": 59203 14 | }, 15 | { 16 | "icon_id": "634581", 17 | "name": "推特_twitter44", 18 | "font_class": "tuitetwitter44", 19 | "unicode": "e708", 20 | "unicode_decimal": 59144 21 | }, 22 | { 23 | "icon_id": "834839", 24 | "name": "微博", 25 | "font_class": "weibo", 26 | "unicode": "e64b", 27 | "unicode_decimal": 58955 28 | } 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /5.新拟态登录界面/icon/iconfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/5.新拟态登录界面/icon/iconfont.ttf -------------------------------------------------------------------------------- /5.新拟态登录界面/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 新拟态登录界面 10 | 11 | 12 |
13 | 14 |
15 | 16 |
17 |
Welcome Back !
18 |

To keep connected with us please login with your personal info

19 | 20 |
21 | 22 | 23 |
24 |
Hello Friend !
25 |

Enter your person details and start journey with us

26 | 27 |
28 |
29 | 30 | 66 |
67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /5.新拟态登录界面/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | // 获取 .switch-panel 的标签 4 | const switchPanel = doc.querySelector('.switch-panel'); 5 | // 获取 .register-login-panel 的标签 6 | const register_login_Panel = doc.querySelector('.register-login-panel'); 7 | 8 | const switchPanel_login = doc.querySelector('#login'); 9 | const switchPanel_register = doc.querySelector('#register'); 10 | const registerPanel = doc.querySelector('.register'); 11 | const loginPanel = doc.querySelector('.login'); 12 | 13 | // 监听切换按钮点击事件 14 | const switchBtn1 = doc.querySelector('#switch1'); 15 | switchBtn1.addEventListener('click', switchStyle); 16 | 17 | const switchBtn2 = doc.querySelector('#switch2'); 18 | switchBtn2.addEventListener('click', switchStyle); 19 | 20 | /** 21 | * 切换样式 22 | * 23 | * 通过 toggle 方法来 增加 / 移除 定义好的用来 移动 / 隐藏 元素的样式 24 | * 25 | */ 26 | function switchStyle() { 27 | switchPanel.classList.toggle('switch-panel-slide'); 28 | register_login_Panel.classList.toggle('register-login-panel-slide'); 29 | switchPanel_login.classList.toggle('switch-hidden'); 30 | switchPanel_register.classList.toggle('switch-hidden'); 31 | loginPanel.classList.toggle('switch-hidden-2'); 32 | registerPanel.classList.toggle('switch-hidden-2'); 33 | } 34 | -------------------------------------------------------------------------------- /5.新拟态登录界面/style.css: -------------------------------------------------------------------------------- 1 | /* 样式初始化 */ 2 | * { 3 | margin: 0; 4 | padding: 0; 5 | box-sizing: border-box; 6 | } 7 | 8 | body { 9 | height: 100vh; 10 | background: #ecf0f3; 11 | /* 12 | flex布局 13 | 内容水平、垂直居中 14 | */ 15 | display: flex; 16 | justify-content: center; 17 | align-items: center; 18 | } 19 | 20 | .container { 21 | width: 800px; 22 | height: 500px; 23 | /* 阴影效果 */ 24 | box-shadow: 10px 10px 10px #d1d9e6, 25 | -10px -10px 10px #f9f9f9; 26 | border-radius: 12px; 27 | overflow: hidden; 28 | /* 因为它的子元素三个面板都要设置为绝对定位,所以这里要设置为相对定位 */ 29 | position: relative; 30 | } 31 | 32 | /* 切换按钮所在的面板 */ 33 | .switch-panel { 34 | width: 300px; 35 | height: 500px; 36 | background: #ecf0f3; 37 | /* 阴影效果 */ 38 | box-shadow: 10px 10px 10px #d1d9e6, 39 | -10px -10px 10px #f9f9f9; 40 | position: absolute; 41 | top: 0; 42 | left: 0; 43 | z-index: 20; 44 | display: flex; 45 | justify-content: center; 46 | align-items: center; 47 | transition: all .6s ease-in-out; 48 | } 49 | 50 | /* 切换面板滑动后的位置 */ 51 | .switch-panel-slide { 52 | left: 500px; 53 | } 54 | 55 | /* 注册面板 */ 56 | .register-login-panel { 57 | width: 500px; 58 | height: 500px; 59 | position: absolute; 60 | top: 0; 61 | right: 0; 62 | transition: all .6s ease-in-out; 63 | } 64 | 65 | .register-login-panel-slide { 66 | right: 300px; 67 | } 68 | 69 | .register, 70 | .login { 71 | width: 100%; 72 | height: 100%; 73 | display: flex; 74 | justify-content: center; 75 | align-items: center; 76 | transition: all .6s ease-in-out; 77 | } 78 | 79 | .switch-box { 80 | display: flex; 81 | flex-direction: column; 82 | justify-content: center; 83 | align-items: center; 84 | padding: 30px; 85 | transition: all .6s ease-in-out; 86 | } 87 | 88 | .switch-box .title { 89 | font-size: 26px; 90 | font-weight: 700; 91 | line-height: 3; 92 | color: #000; 93 | } 94 | 95 | .switch-box p { 96 | font-size: 12px; 97 | letter-spacing: 0.25px; 98 | line-height: 1.6; 99 | text-align: center; 100 | color: #a0a5a8 101 | } 102 | 103 | /* 按钮统一样式 */ 104 | .switch-box button, 105 | .login .content button, 106 | .register .content button { 107 | /* 阴影效果 */ 108 | box-shadow: 10px 10px 10px #d1d9e6, 109 | -10px -10px 10px #f9f9f9; 110 | width: 180px; 111 | height: 40px; 112 | border-radius: 25px; 113 | margin-top: 50px; 114 | font-weight: 700; 115 | font-size: 14px; 116 | color: #fff; 117 | border: none; 118 | outline: none; 119 | background: #4b70e2; 120 | user-select: none; 121 | /* 按钮点击后的过渡效果 */ 122 | transition: all .3s ease-in-out; 123 | cursor: pointer; 124 | } 125 | 126 | /* 按钮点击时的效果 */ 127 | .switch-box button:active { 128 | transform: scale(0.8); 129 | background: #abbdf4 130 | } 131 | 132 | .switch-hidden { 133 | position: absolute; 134 | opacity: 0; 135 | } 136 | 137 | .switch-hidden-2 { 138 | position: absolute; 139 | opacity: 0; 140 | top: 0; 141 | z-index: -10; 142 | } 143 | 144 | /******** 内容填充 ********/ 145 | .login .content, 146 | .register .content { 147 | display: flex; 148 | flex-direction: column; 149 | justify-content: center; 150 | align-items: center; 151 | } 152 | 153 | .login .content h2, 154 | .register .content h2 { 155 | font-size: 26px; 156 | font-weight: 700; 157 | line-height: 2.6; 158 | color: #000; 159 | } 160 | 161 | .login .content .icons i, 162 | .register .content .icons i { 163 | font-size: 16px; 164 | color: #a0a5a8; 165 | margin: 0 4px; 166 | } 167 | 168 | .login .content span, 169 | .register .content span { 170 | font-size: 12px; 171 | color: #a0a5a8; 172 | margin-top: 12px; 173 | margin-bottom: 8px; 174 | } 175 | 176 | .login .content input, 177 | .register .content input { 178 | width: 300px; 179 | height: 40px; 180 | margin: 8px 0; 181 | padding-left: 25px; 182 | font-size: 13px; 183 | letter-spacing: 0.15px; 184 | border: none; 185 | outline: none; 186 | background-color: #ecf0f3; 187 | transition: all .25s ease-in-out; 188 | border-radius: 8px; 189 | box-shadow: inset 2px 2px 4px #d1d9e6, 190 | inset -2px -2px 4px #f9f9f9; 191 | } 192 | 193 | .login .content button, 194 | .register .content button { 195 | margin-top: 24px; 196 | } -------------------------------------------------------------------------------- /6.主题切换/css/reset.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | min-height: 100vh; 9 | display: flex; 10 | justify-content: center; 11 | align-items: center; 12 | transition: background-color .5s ease-in-out; 13 | } 14 | 15 | .container .title { 16 | text-align: center; 17 | font-size: 32px; 18 | font-weight: 700; 19 | letter-spacing: 2px; 20 | user-select: none; 21 | transition: color .5s ease-in-out; 22 | } 23 | 24 | .container .switch-btns { 25 | display: flex; 26 | margin-top: 32px; 27 | } 28 | 29 | .container .switch-btns .btn { 30 | width: 50px; 31 | height: 50px; 32 | border-radius: 50%; 33 | margin: 0 20px; 34 | user-select: none; 35 | cursor: pointer; 36 | } 37 | 38 | .container .switch-btns .white { 39 | background-color: #fff; 40 | } 41 | 42 | .container .switch-btns .dark { 43 | background-color: #1d0624; 44 | } 45 | 46 | .container .switch-btns .red { 47 | background-color: red; 48 | } 49 | 50 | .container .switch-btns .blue { 51 | background-color: #3f00ff; 52 | } -------------------------------------------------------------------------------- /6.主题切换/css/theme-blue.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #1605ae; 3 | } 4 | 5 | .container .title { 6 | color: #6d72e8; 7 | } -------------------------------------------------------------------------------- /6.主题切换/css/theme-dark.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #020420; 3 | } 4 | 5 | .container .title { 6 | color: #907d7d; 7 | } -------------------------------------------------------------------------------- /6.主题切换/css/theme-red.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #ff5839; 3 | } 4 | 5 | .container .title { 6 | color: #da9696; 7 | } -------------------------------------------------------------------------------- /6.主题切换/css/theme-white.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: #eee; 3 | } 4 | 5 | .container .title { 6 | color: #d3d6df; 7 | } -------------------------------------------------------------------------------- /6.主题切换/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | 13 | 17 | 18 | 19 | 20 | 主题切换 21 | 22 | 23 |
24 |
Theme Switch
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /6.主题切换/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | const themes = [ 4 | doc.querySelector('link[data-theme="white"]'), 5 | doc.querySelector('link[data-theme="dark"]'), 6 | doc.querySelector('link[data-theme="red"]'), 7 | doc.querySelector('link[data-theme="blue"]') 8 | ]; 9 | 10 | const btns = doc.querySelectorAll('.btn'); 11 | 12 | btns.forEach(btn => { 13 | btn.addEventListener('click', (e) => { 14 | const theme = btn.getAttribute('data-theme'); 15 | this.switchTheme(theme); 16 | }); 17 | }); 18 | 19 | function switchTheme(theme) { 20 | themes.forEach(t => { 21 | if (t.dataset.theme === theme) { 22 | t.disabled = false; 23 | } else { 24 | t.disabled = true; 25 | } 26 | }); 27 | } -------------------------------------------------------------------------------- /7.可拖动半透明弹框dialog/image/longmao.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/7.可拖动半透明弹框dialog/image/longmao.jpg -------------------------------------------------------------------------------- /7.可拖动半透明弹框dialog/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 可拖动弹框Dialog 9 | 10 | 11 | 12 |
13 |
14 |
15 |

关闭弹框: 按 ESC / 点击其他区域

16 |
17 |
18 |
19 | 20 |
21 | 打开弹框 22 |
23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /7.可拖动半透明弹框dialog/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | 3 | const btn = doc.querySelector('.open-btn'); 4 | const dialog = doc.querySelector('dialog'); 5 | const header = doc.querySelector('.header-bar'); 6 | 7 | // 点击按钮,打开弹框 8 | btn.addEventListener('click', (e) => { 9 | dialog.showModal(); 10 | }) 11 | 12 | // 点击旁白区域,关闭弹框 13 | dialog.addEventListener('click', (e) => { 14 | if (e.target.nodeName === 'DIALOG') { 15 | dialogInit(); 16 | } 17 | }); 18 | 19 | // 监听 esc 键,按下 esc 键关闭 dialog, 位置初始化 20 | doc.addEventListener('keydown', (e) => { 21 | if (e.code === 'Escape') { 22 | dialogInit(); 23 | } 24 | }) 25 | 26 | // 移动弹框 27 | header.addEventListener('mousedown', (e) => { 28 | 29 | // 鼠标位于弹框内的坐标 30 | const offsetX = e.offsetX; 31 | const offsetY = e.offsetY; 32 | 33 | const dialogWidth = dialog.getBoundingClientRect().width; 34 | const dialogHeight = dialog.getBoundingClientRect().height; 35 | 36 | function mousemove(event) { 37 | const pageX = event.pageX; 38 | const pageY = event.pageY; 39 | 40 | // 移动后的坐标 41 | // 因为在css文件中设置dialog位于页面中心位置时,使用了 transform(-50%, -50%) 42 | // 使得 dialog 在 top: 50%; left: 50%; 的定位基础上又沿着 x, y 轴偏移了 dialog 自身宽高的50% 43 | // 所以这里在设置新的位置 top left 时, 应该加上 宽高的一半 44 | dialog.style.top = (pageY - offsetY + dialogHeight / 2) + 'px'; 45 | dialog.style.left = (pageX - offsetX + dialogWidth / 2) + 'px'; 46 | 47 | dialog.style.opacity = 0.2; 48 | } 49 | 50 | doc.addEventListener('mousemove', mousemove); 51 | 52 | // 拖动结束 53 | dialog.addEventListener('mouseup', (e) => { 54 | doc.removeEventListener('mousemove', mousemove); 55 | dialog.style.opacity = 1; 56 | }) 57 | 58 | }); 59 | 60 | // 弹框初始化 61 | function dialogInit() { 62 | dialog.close(); 63 | dialog.style.left = '50%'; 64 | dialog.style.top = '50%'; 65 | } -------------------------------------------------------------------------------- /7.可拖动半透明弹框dialog/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | min-height: 100vh; 9 | background-image: url(./image/longmao.jpg); 10 | background-repeat: no-repeat; 11 | background-size: cover; 12 | display: flex; 13 | justify-content: center; 14 | align-items: center; 15 | } 16 | 17 | .open-btn { 18 | padding: 20px 30px; 19 | background-color: #fff; 20 | border-radius: 30px; 21 | cursor: pointer; 22 | user-select: none; 23 | color: #787fb3; 24 | font-size: 20px; 25 | font-weight: 700; 26 | letter-spacing: 1px; 27 | box-shadow: 0 0 10px 10px rgba(255, 255, 255, 0.5); 28 | } 29 | 30 | dialog { 31 | position: fixed; 32 | top: 50%; 33 | left: 50%; 34 | transform: translate(-50%, -50%); 35 | } 36 | 37 | dialog .box { 38 | width: 350px; 39 | height: 240px; 40 | display: flex; 41 | flex-direction: column; 42 | } 43 | 44 | dialog .box .header-bar { 45 | height: 20px; 46 | background-color: #787fb3; 47 | cursor: move; 48 | user-select: none; 49 | } 50 | 51 | dialog .box .content { 52 | display: flex; 53 | justify-content: center; 54 | align-items: center; 55 | flex: 1; 56 | } 57 | 58 | .box .content p { 59 | font-size: 24px; 60 | font-weight: 700; 61 | color: #787fb3; 62 | user-select: none; 63 | } -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/image/avatar-Jennie.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/8.仿css-tricks的卡片抽出效果/image/avatar-Jennie.png -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/image/avatar-Jisoo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/8.仿css-tricks的卡片抽出效果/image/avatar-Jisoo.png -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/image/avatar-Jisoo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/8.仿css-tricks的卡片抽出效果/image/avatar-Jisoo2.png -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/image/avatar-Lisa2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/8.仿css-tricks的卡片抽出效果/image/avatar-Lisa2.png -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/image/avatar-Rose.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/8.仿css-tricks的卡片抽出效果/image/avatar-Rose.png -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 卡片抽出效果 9 | 10 | 11 |
12 |
13 | Jisoo 14 |
15 |
16 | Jennie 17 |
18 |
19 | Lisa 20 |
21 |
22 | Rose 23 |
24 |
25 | Jisoo 26 |
27 |
28 | 29 | -------------------------------------------------------------------------------- /8.仿css-tricks的卡片抽出效果/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | min-height: 100vh; 9 | background-color: #434343; 10 | display: flex; 11 | justify-content: center; 12 | align-items: center; 13 | } 14 | 15 | .container { 16 | padding: 30px 0 30px 20px; 17 | display: flex; 18 | position: relative; 19 | } 20 | 21 | .container .card { 22 | width: 300px; 23 | height: 350px; 24 | box-shadow: -20px 0 30px #000; 25 | border-radius: 16px; 26 | overflow: hidden; 27 | background: linear-gradient(85deg, #434343, #262626); 28 | transition: all .3s ease-in-out; 29 | } 30 | 31 | .container .card img { 32 | width: 100%; 33 | height: 100%; 34 | object-fit: cover; 35 | } 36 | 37 | /* 除第一张card,其他card向左移动130px,呈现一个折叠效果 */ 38 | .container .card:not(:first-child) { 39 | margin-left: -130px; 40 | } 41 | 42 | .container .card:hover { 43 | transform: translateY(-1rem) rotate(3deg); 44 | } 45 | 46 | .container .card:first-child:hover { 47 | transform: translate(-0.5rem, -1rem) rotate(3deg); 48 | } 49 | 50 | /* ~: 同级向下查找,即当前.card后面的兄弟card */ 51 | .container .card:hover~.card { 52 | transform: translateX(130px); 53 | } 54 | -------------------------------------------------------------------------------- /9.炎炎夏日送你一场雪/image/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/9.炎炎夏日送你一场雪/image/1.jpg -------------------------------------------------------------------------------- /9.炎炎夏日送你一场雪/image/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/9.炎炎夏日送你一场雪/image/3.jpg -------------------------------------------------------------------------------- /9.炎炎夏日送你一场雪/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 炎炎夏日,送你一场雪 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /9.炎炎夏日送你一场雪/script.js: -------------------------------------------------------------------------------- 1 | const doc = document; 2 | const canvas = doc.querySelector('canvas'); 3 | // 获取 2d 上下文 4 | const snowCtx = canvas.getContext('2d'); 5 | 6 | // 获取window的宽高,赋值给画布 7 | canvas.width = width = window.innerWidth; 8 | canvas.height = height = window.innerHeight; 9 | 10 | // 常量、参数 11 | const TOTAL = 600, // 雪花数量 12 | tsc = 1, // 用来设置雪花飘落效果的参数 13 | speed = 1; // 雪花飘落速度 14 | const sc = 1.3, // 用来生成雪花半径的参数 15 | t = 0, // 用来设置雪花飘落效果的参数 16 | mv = 20, 17 | minSpeed = 1, // 雪花飘落的最小速度 18 | snowArr = []; // 雪花数组,用来存放雪花的实例 19 | 20 | /** 21 | * 下雪 22 | */ 23 | function Snowy() { 24 | // 生成 TOTAL 数量的雪花类实例,存放到 snowArr 数组中 25 | for (let i = 0; i < TOTAL; i++) { 26 | const snowFlake = new SnowFlake(); 27 | snowArr.push(snowFlake); 28 | } 29 | // 渲染雪花 30 | render(); 31 | } 32 | 33 | /** 34 | * 渲染函数 35 | */ 36 | function render() { 37 | // 清除画布内容,准备绘制 38 | snowCtx.clearRect(0, 0, width, height); 39 | // 遍历雪花数组,让雪花数组中的实例改变位置、速度 等参数 40 | snowArr.forEach(snowFlake => snowFlake.animate()); 41 | // 该方法会让浏览器在重绘之前调用指定的函数 render 42 | // 这样可以保证在浏览器的刷新频率下更新动画; 43 | window.requestAnimationFrame(render); 44 | } 45 | 46 | /** 47 | * 雪花 类 48 | */ 49 | class SnowFlake { 50 | 51 | /** 52 | * 构造方法,数据初始化 53 | */ 54 | constructor() { 55 | this.y = Math.random() * (height + 50); // y轴坐标 56 | this.x = Math.random() * width; // x轴坐标 57 | this.t = Math.random() * (Math.PI * 2); 58 | this.size = (100 / (10 + (Math.random() * 100))) * sc; // 雪花半径 59 | this.speed = (Math.pow(this.size * 0.7, 2) * 0.15) * speed; // 雪花尺寸越大,速度越快,为了营造一种远近的层次感 60 | this.speed = this.speed < minSpeed ? minSpeed : this.speed; 61 | } 62 | 63 | /** 64 | * 雪花绘制的方法 65 | */ 66 | draw() { 67 | 68 | /* 69 | createRadialGradient:创建(圆形)梯度渐变 70 | 圆形起始区域:this.x(x轴坐标) this.y(y轴坐标) 0(半径) 71 | 圆形结束区域:this.x(x轴坐标) this.y(y轴坐标) this.size(半径) 72 | */ 73 | this.g = snowCtx.createRadialGradient(this.x, this.y, 0, this.x, this.y, this.size); 74 | /* 75 | 设置区域渐变色 76 | 简单理解:从圆心到园外由白色渐渐变成白色透明效果 77 | */ 78 | this.g.addColorStop(0, 'rgba(255, 255, 255, 1)'); // 白色,透明度1 79 | this.g.addColorStop(1, 'rgba(255, 255, 255, 0)'); // 白色,透明度0 80 | snowCtx.moveTo(this.x, this.y); // “画笔”移动到 (this.x, this.y) 位置,准备开始画 81 | snowCtx.fillStyle = this.g; 82 | snowCtx.beginPath(); // 开始 83 | // arc() 画圆(雪花) 84 | snowCtx.arc(this.x, this.y, this.size, 0, Math.PI * 2, true); 85 | snowCtx.fill(); // 着色 86 | 87 | // y轴方向超出画布高度,重新设置雪花在y轴的坐标 88 | if (this.y > height + 50) { 89 | this.y = -10 - Math.random() * mv; 90 | } 91 | // x轴方向超出画布的宽度,重新设置雪花在x的坐标 92 | if (this.x > width + mv) { 93 | this.x = -mv; 94 | } 95 | if (this.x < -mv) { 96 | this.x = width + mv; 97 | } 98 | } 99 | 100 | /** 101 | * 重新设置雪花运动时的参数,包括位置、速度等 102 | */ 103 | animate() { 104 | this.t += 0.05; 105 | this.t = this.t >= Math.PI * 2 ? 0 : this.t; 106 | this.y += this.speed; // y轴方向匀速下落 107 | this.x += Math.sin(this.t * tsc) * (this.size * 0.3); // 利用 Math.sin() 函数让雪花下落过程中水平方向产生正弦图形似的移动效果 108 | 109 | // 利用上述参数重新绘制雪花 110 | this.draw(); 111 | } 112 | 113 | } 114 | 115 | // 监听浏览器窗口变化 116 | window.addEventListener('resize', () => { 117 | canvas.width = width = window.innerWidth; 118 | canvas.height = height = window.innerHeight; 119 | }); 120 | 121 | // 调用 Snowy(), 开始下雪! 122 | Snowy(); -------------------------------------------------------------------------------- /9.炎炎夏日送你一场雪/style.css: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | } 6 | 7 | body { 8 | min-height: 100vh; 9 | background-color: rgba(0, 0, 0, 1); 10 | background-image: url(./image/1.jpg); 11 | overflow: hidden; 12 | background-size: cover; 13 | background-repeat: no-repeat; 14 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CSS-HTML- 2 | css+html案例分享 3 | -------------------------------------------------------------------------------- /【粉丝问题解答-第1期】飘落樱花背景的页面/image/petal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/【粉丝问题解答-第1期】飘落樱花背景的页面/image/petal.png -------------------------------------------------------------------------------- /【粉丝问题解答-第1期】飘落樱花背景的页面/image/sakura2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DoggyYao/css-html-demo/aa81216b176be746303988511a1a141b32e5e477/【粉丝问题解答-第1期】飘落樱花背景的页面/image/sakura2.jpg -------------------------------------------------------------------------------- /【粉丝问题解答-第1期】飘落樱花背景的页面/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 飘落樱花背景的页面 9 | 10 | 11 | 12 | 13 | 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 | -------------------------------------------------------------------------------- /【粉丝问题解答-第1期】飘落樱花背景的页面/script.js: -------------------------------------------------------------------------------- 1 | const canvas = document.querySelector('canvas'); 2 | 3 | // innerWidth: 视口宽度 4 | canvas.width = window.innerWidth; 5 | // innerWidth: 视口高度 6 | canvas.height = window.innerHeight; 7 | // 使用2d绘图的上下文 8 | const ctx = canvas.getContext('2d'); 9 | 10 | // 定义花瓣数量 11 | const TOTAL = 70; 12 | // 花瓣数组 13 | const petalArray = []; 14 | 15 | 16 | // 加载花瓣图片 17 | const petalImg = new Image(); 18 | petalImg.src = './image/petal.png'; 19 | // 待图片加载完毕,将100个花瓣类的实例放到花瓣数组petalArray中 20 | petalImg.addEventListener('load', () =>{ 21 | for (let i = 0; i < TOTAL; i++) { 22 | petalArray.push(new Petal()); 23 | }; 24 | render(); 25 | }) 26 | 27 | /** 28 | * 定义渲染的方法 29 | */ 30 | function render() { 31 | // 清除页面内容 32 | ctx.clearRect(0, 0, canvas.width, canvas.height); 33 | petalArray.forEach(petal => petal.animate()); 34 | // 该方法会高速浏览器在重绘之前调用指定的函数 35 | // 这样可以保证在浏览器的刷新频率下去更新动画; 36 | window.requestAnimationFrame(render); 37 | } 38 | 39 | // 监听浏览器窗口大小变化,重新设置canvas的宽高 40 | window.addEventListener('resize', () => { 41 | canvas.width = window.innerWidth; 42 | canvas.height = window.innerHeight; 43 | }); 44 | 45 | let mouseX = 0; 46 | function touchHandler(e) { 47 | mouseX = (e.clientX || e.touches[0].clientX) / window.innerWidth; 48 | } 49 | window.addEventListener('mousemove', touchHandler); 50 | window.addEventListener('touchmove', touchHandler); 51 | 52 | /** 53 | * 定义花瓣类 54 | */ 55 | class Petal { 56 | // 构造方法 57 | constructor() { 58 | // 位置随机生成 59 | this.x = Math.random() * canvas.width; 60 | this.y = (Math.random() * canvas.height * 2) - canvas.height; 61 | // 花瓣宽高随机生成 62 | this.w = 25 + Math.random() * 15; 63 | this.h = 20 + Math.random() * 10; 64 | // 透明度 65 | this.opacity = this.w / 40; 66 | // 旋转角度 67 | this.flip = Math.random(); 68 | // 速度初始化 69 | this.xSpeed = 1.5 + Math.random() * 2; 70 | this.ySpeed = 1 + Math.random() * 1; 71 | this.flipSpeed = Math.random() * 0.03; 72 | } 73 | 74 | // 绘图 75 | draw() { 76 | // 当花瓣超过边界,重新设置其位置、速度和旋转角度 77 | if (this.y > canvas.height || this.x > canvas.width) { 78 | this.x = -petalImg.width; 79 | this.y = (Math.random() * canvas.height * 2) - canvas.height; 80 | this.xSpeed = 1.5 + Math.random() * 2; 81 | this.ySpeed = 1 + Math.random() * 1; 82 | this.flip = Math.random(); 83 | } 84 | // 设置整个canvas透明度基数 85 | ctx.globalAlpha = this.opacity; 86 | ctx.drawImage( 87 | petalImg, 88 | this.x, 89 | this.y, 90 | this.w * (0.6 + (Math.abs(Math.cos(this.flip)) / 3)), 91 | this.h * (0.8 + (Math.abs(Math.sin(this.flip)) / 5)) 92 | ) 93 | } 94 | 95 | animate() { 96 | this.x += this.xSpeed + mouseX * 5; 97 | this.y += this.ySpeed + mouseX * 2; 98 | this.flip += this.flipSpeed; 99 | this.draw(); 100 | } 101 | } -------------------------------------------------------------------------------- /【粉丝问题解答-第1期】飘落樱花背景的页面/style.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | margin: 0; 3 | padding: 0; 4 | width: 100%; 5 | height: 100%; 6 | background-color: #1a1a1a; 7 | overflow: hidden; 8 | } 9 | 10 | body { 11 | background-image: url(./image/sakura2.jpg); 12 | background-size: cover; 13 | position: relative; 14 | } 15 | 16 | /* 位于樱花飘落背景上方的覆盖层 */ 17 | .overlay { 18 | position: absolute; 19 | top: 0; 20 | left: 0; 21 | bottom: 0; 22 | right: 0; 23 | z-index: 1; 24 | overflow-y: auto; 25 | padding: 25px 0; 26 | /* 设置背景为透明,当然只要不设置颜色也可以 */ 27 | background: transparent; 28 | } 29 | 30 | /* 去除滚动条 */ 31 | .overlay::-webkit-scrollbar { 32 | width: 0; 33 | } 34 | 35 | .article { 36 | max-width: 800px; 37 | margin: 0 auto; 38 | padding: 55px 50px; 39 | /* 拟物玻璃化效果 */ 40 | background-color: rgba(255, 255, 255, 0.4); 41 | backdrop-filter: blur(15px) saturate(180%); 42 | border-radius: 10px; 43 | border: 1px solid rgba(209, 213, 219, 0.4); 44 | color: #000; 45 | } 46 | 47 | h2, h4 { 48 | text-align: center; 49 | margin: 12px 0; 50 | } 51 | 52 | h4 { 53 | font-weight: 500; 54 | } 55 | 56 | .article p { 57 | text-indent: 2em; 58 | line-height: 2; 59 | margin-bottom: 1em; 60 | } --------------------------------------------------------------------------------