補課:從HTML/CSS/JavaScript實例掌握核心機(jī)制)
簡介《HTML.CSS.JavaScript標(biāo)準(zhǔn)教程》實例版第二版是一套面向Web前端初學(xué)者與進(jìn)階開發(fā)者的實例型學(xué)習(xí)資料圍繞HTML結(jié)構(gòu)標(biāo)記、CSS樣式布局與JavaScript交互邏輯三大核心展開幫助讀者從零建立完整的前端知識體系并動手實踐。資源包共收錄528個文件以286個html示例頁面、115張jpg與67張gif配圖為主輔以23個ppt課件、5個css樣式表、4個htm頁面及若干txt說明與psd源文件壓縮包約35.9MB目錄按章節(jié)組織便于對照知識點逐項查閱。內(nèi)容覆蓋HTML5音頻視頻與離線存儲、CSS盒模型與Flexbox/Grid布局、響應(yīng)式設(shè)計以及JavaScript基礎(chǔ)語法、DOM操作、AJAX異步通信和ES6箭頭函數(shù)、模板字符串、類與模塊等新特性每個知識點均配有可運行的代碼示例。目前已有274人學(xué)習(xí)下載適合希望邊學(xué)邊練、將理論轉(zhuǎn)化為實際開發(fā)能力的讀者參考使用。1. 從一本舊書翻出的前端基本功為什么我還在推薦《HTML.CSS.JavaScript標(biāo)準(zhǔn)教程(實例版)(第2版)》前陣子幫一個剛轉(zhuǎn)行的朋友排查頁面問題他寫了個div套div的布局CSS 里用float清浮動結(jié)果在移動端全亂套。我問他盒模型怎么算的他愣了半天。這不是個例——現(xiàn)在很多人上手就是 Vue、React腳手架一跑組件一拼頁面能出來但一旦樣式錯位、事件綁定失效、DOM 操作報錯就徹底抓瞎。這本《HTML.CSS.JavaScript標(biāo)準(zhǔn)教程(實例版)(第2版)》恰好補的就是這塊地基。它不是那種翻兩頁就困的理論書而是每個知識點都配一個能跑起來的實例從!DOCTYPE html聲明到 JavaScript 判斷數(shù)據(jù)類型再到 CSS 樣式引入方式全是用小案例串起來的。適合誰剛?cè)腴T前端但不想只當(dāng)“調(diào)包俠”的人以及工作幾年但基礎(chǔ)概念一直模模糊糊、想回頭補課的人。我翻完的感受是它把“為什么這樣寫”講清楚了而不是只告訴你“這樣寫能跑”。2. 把實例跑起來環(huán)境、文件結(jié)構(gòu)與第一個可交互頁面2.1 選編輯器還是選 IDE別在工具上糾結(jié)太久拿到這本書的配套實例第一件事是決定在哪寫代碼。常見做法是 VS Code 加 Live Server 插件輕量、啟動快、保存即刷新。如果你習(xí)慣 JetBrains 系WebStorm 也行但對純靜態(tài)頁面來說有點重。Ubuntu 用戶如果不想裝圖形化編輯器用 gedit 或 nano 直接改也行但調(diào)試體驗差一截。我的建議是初學(xué)階段用 VS Code裝三個插件——Live Server、Prettier、Auto Rename Tag。Live Server 解決刷新問題Prettier 統(tǒng)一格式Auto Rename Tag 避免你改開標(biāo)簽忘了閉標(biāo)簽。書里的實例通常按章分文件夾每個實例一個獨立目錄里面至少有一個.html文件CSS 和 JS 可能內(nèi)嵌也可能外鏈。你不需要把整本書的代碼一次性全下載下來跑按章按節(jié)來跑通一個再下一個。下面是一個典型實例的目錄結(jié)構(gòu)我按書里的組織方式還原一下chapter03/ ├── index.html ├── css/ │ └── style.css └── js/ └── main.js2.2 從 DOCTYPE 到字符編碼那些你復(fù)制粘貼時忽略的頭部很多新手直接復(fù)制書里的body部分把頭部丟了結(jié)果中文亂碼、樣式不生效。頭部這幾行看著不起眼但每一行都有用。下面是一個標(biāo)準(zhǔn)實例頁面的骨架!DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 title實例CSS 樣式引入方式對比/title !-- 外鏈樣式書里推薦的方式便于復(fù)用 -- link relstylesheet hrefcss/style.css /head body h1三種樣式引入方式/h1 p stylecolor: red;這是行內(nèi)樣式/p div classbox這是外鏈樣式控制的盒子/div script srcjs/main.js/script /body /html邏輯說明!DOCTYPE html告訴瀏覽器用標(biāo)準(zhǔn)模式渲染不加這行會觸發(fā)怪異模式盒模型計算方式都變了。langzh-CN對屏幕閱讀器和翻譯工具有意義。meta charsetUTF-8必須放在head最前面否則中文可能變問號。viewport那行是移動端適配的前提書里實例版第 2 版已經(jīng)覆蓋了響應(yīng)式基礎(chǔ)。link引入外部 CSSscript放在/body前是為了不阻塞 DOM 解析。參數(shù)說明href路徑用相對路徑css/style.css表示當(dāng)前 HTML 同級目錄下的 css 文件夾。如果你把 CSS 和 HTML 放同一層直接寫style.css。src同理。書里有些實例把 JS 寫在head里那就要加defer屬性否則 DOM 還沒生成document.getElementById會返回 null。2.3 用一個小實例驗證環(huán)境點擊按鈕改變文本跑通下面這個例子說明你的環(huán)境沒問題也說明你理解了 HTML 結(jié)構(gòu)、CSS 選擇器和 JS 事件綁定的最小閉環(huán)。!DOCTYPE html html langzh-CN head meta charsetUTF-8 title環(huán)境驗證實例/title style #display { font-size: 20px; color: #333; margin: 20px 0; } button { padding: 8px 16px; cursor: pointer; } /style /head body div iddisplay原始文本/div button idchangeBtn點擊改變/button script // 獲取元素 var displayEl document.getElementById(display); var btnEl document.getElementById(changeBtn); var count 0; // 綁定點擊事件 btnEl.addEventListener(click, function() { count; displayEl.textContent 你點擊了 count 次; // 根據(jù)點擊次數(shù)切換顏色演示 JS 操作 CSS if (count % 2 0) { displayEl.style.color blue; } else { displayEl.style.color red; } }); /script /body /html邏輯說明getElementById拿到 DOM 元素addEventListener綁定 click 事件回調(diào)里修改textContent和style.color。這是最基礎(chǔ)的“結(jié)構(gòu) 樣式 行為”分離寫法書里從第 1 章就開始灌輸這個模式。參數(shù)說明count變量用來記錄點擊次數(shù)%取模判斷奇偶。如果你把addEventListener寫成onclick屬性也能跑但不利于維護(hù)書里推薦前者。提示如果你打開頁面發(fā)現(xiàn)按鈕沒反應(yīng)先按 F12 看 Console 有沒有報錯。最常見的是script寫在了head里且沒加defer導(dǎo)致getElementById返回 null。3. CSS 布局與樣式引入從盒模型到五種布局方式的實例拆解3.1 盒模型和 box-sizing為什么你的寬度總是對不上書里講盒模型那章我建議反復(fù)看。CSS 盒模型分標(biāo)準(zhǔn)盒模型和 IE 盒模型區(qū)別在width是否包含padding和border。默認(rèn)是content-box你設(shè)width: 200px再加padding: 20px實際占寬是 240px。很多人布局對不齊就是這里沒算清楚。實例版里有一個對比案例我把它簡化成下面這樣/* 標(biāo)準(zhǔn)盒模型實際寬度 width padding border */ .box-content { box-sizing: content-box; width: 200px; padding: 20px; border: 5px solid #333; background: #f0f0f0; } /* IE 盒模型實際寬度 widthpadding 和 border 擠占內(nèi)容區(qū) */ .box-border { box-sizing: border-box; width: 200px; padding: 20px; border: 5px solid #333; background: #d0d0d0; }邏輯說明content-box下內(nèi)容區(qū)寬 200px加上左右 padding 各 20px、左右 border 各 5px總占寬 250px。border-box下總占寬就是 200px內(nèi)容區(qū)被壓縮到 150px。書里推薦全局設(shè)置* { box-sizing: border-box; }這樣計算寬度時不用做加法減少翻車概率。參數(shù)說明*通配符會影響所有元素包括偽元素一般夠用。如果你用第三方組件庫注意它可能自己重置了box-sizing別盲目覆蓋。3.2 五種布局方式的實例對比float、position、flex、grid、table書里有一章專門對比布局方式我按自己的理解整理成表格方便你選型布局方式適用場景書里實例主要坑點float文字環(huán)繞圖片、舊式多列圖文混排需要清浮動父元素高度塌陷position彈層、固定導(dǎo)航、角標(biāo)返回頂部按鈕脫離文檔流層級要管 z-indexflex一維排列、居中、等分導(dǎo)航欄、卡片列表舊版瀏覽器前綴flex-basis 和 width 混用grid二維網(wǎng)格、復(fù)雜頁面后臺管理布局兼容性比 flex 稍差但現(xiàn)代瀏覽器都支持table表格數(shù)據(jù)、老式垂直居中數(shù)據(jù)報表語義不對響應(yīng)式困難書里對 float 清浮動的實例用了clearfix偽元素方案比overflow: hidden更可控。flex 那節(jié)講了justify-content和align-items的組合建議你每個屬性值都改一遍看效果。grid 部分實例版第 2 版有更新但如果你面向的是老項目先掌握 flex 就夠用。3.3 樣式引入三種方式行內(nèi)、內(nèi)嵌、外鏈的取舍書里明確推薦外鏈但也沒否定另外兩種。行內(nèi)樣式優(yōu)先級最高但沒法復(fù)用調(diào)試時臨時改可以正式代碼別用。內(nèi)嵌樣式寫在style里適合單頁面且樣式不多的情況。外鏈樣式用link引入瀏覽器可緩存多個頁面共用是標(biāo)準(zhǔn)做法。有一個細(xì)節(jié)link和import都能引入外部 CSS但import會等 HTML 解析到那行才開始加載可能造成閃屏?xí)锝ㄗh用link。!-- 推薦link 引入并行加載 -- link relstylesheet hrefcss/reset.css link relstylesheet hrefcss/main.css !-- 不推薦import 串行加載且必須寫在 style 最前面 -- style import url(css/main.css); /style邏輯說明多個link可以并行下載import是串行的。參數(shù)說明relstylesheet不能省否則瀏覽器不知道這是樣式表。如果你用構(gòu)建工具最終也會打包成一個 CSS 文件但開發(fā)階段保持外鏈結(jié)構(gòu)清晰。4. JavaScript 核心機(jī)制數(shù)據(jù)類型、函數(shù)、事件與 DOM 操作實例4.1 判斷數(shù)據(jù)類型的四種方法typeof、instanceof、constructor、Object.prototype.toString書里講數(shù)據(jù)類型那節(jié)我補充一個實際工作中最常用的判斷函數(shù)。typeof對基本類型夠用但typeof null返回objecttypeof []也返回object。instanceof判斷原型鏈跨 iframe 會失效。constructor可以被改寫。最穩(wěn)的是Object.prototype.toString.call()。function getType(value) { // 先處理 null 和 undefined if (value null) return null; if (value undefined) return undefined; // 用 Object.prototype.toString 獲取精確類型 var type Object.prototype.toString.call(value); // 截取 [object Xxx] 中的 Xxx轉(zhuǎn)小寫 return type.slice(8, -1).toLowerCase(); } // 測試 console.log(getType(123)); // number console.log(getType(abc)); // string console.log(getType([])); // array console.log(getType({})); // object console.log(getType(null)); // null console.log(getType(function(){})); // function邏輯說明Object.prototype.toString.call(value)返回[object Array]這樣的字符串slice(8, -1)去掉[object和]再轉(zhuǎn)小寫。參數(shù)說明這個函數(shù)對基本類型和引用類型都有效除了自定義類實例會返回object需要配合instanceof進(jìn)一步判斷。書里實例版有類似的工具函數(shù)但沒這么完整我一般會把這個函數(shù)放在項目 utils 里。4.2 函數(shù)聲明與函數(shù)表達(dá)式的區(qū)別提升、this 和調(diào)用時機(jī)書里用實例對比了function foo() {}和var foo function() {}。前者會提升后者不會。在事件綁定和回調(diào)里這個區(qū)別很關(guān)鍵。// 函數(shù)聲明可以在聲明前調(diào)用 sayHello(); // 輸出 hello function sayHello() { console.log(hello); } // 函數(shù)表達(dá)式聲明前調(diào)用會報錯 // sayHi(); // TypeError: sayHi is not a function var sayHi function() { console.log(hi); }; sayHi(); // 輸出 hi邏輯說明函數(shù)聲明整體提升函數(shù)表達(dá)式只有變量聲明提升賦值不提升。參數(shù)說明在 ES6 之后箭頭函數(shù)沒有自己的this書里實例版第 2 版可能沒覆蓋箭頭函數(shù)但你可以自己補上。如果回調(diào)里需要this指向當(dāng)前元素用function而不是箭頭函數(shù)。4.3 事件綁定與事件對象從 onclick 到 addEventListener書里從onclick屬性講到addEventListener再到事件委托。事件委托是重點尤其在做列表點擊時不要給每個li綁事件綁在父級ul上通過event.target判斷點的是誰。ul idlist li>// 動態(tài)創(chuàng)建列表 var data [蘋果, 香蕉, 橙子]; var ul document.createElement(ul); data.forEach(function(item) { var li document.createElement(li); li.textContent item; ul.appendChild(li); }); document.body.appendChild(ul); // 返回頂部按鈕 var backBtn document.createElement(button); backBtn.textContent 返回頂部; backBtn.style.position fixed; backBtn.style.bottom 30px; backBtn.style.right 30px; backBtn.addEventListener(click, function() { // 平滑滾動到頂部 window.scrollTo({ top: 0, behavior: smooth }); }); document.body.appendChild(backBtn);邏輯說明createElement創(chuàng)建元素appendChild插入 DOM。window.scrollTo的behavior: smooth實現(xiàn)平滑滾動書里老版本可能用setInterval逐步減scrollTop現(xiàn)代瀏覽器直接支持平滑滾動。參數(shù)說明position: fixed讓按鈕固定在視口bottom和right控制位置。如果你要兼容很老的瀏覽器用document.documentElement.scrollTop 0代替。5. 避坑與排查實例跑不通時先看這五條5.1 中文亂碼現(xiàn)象是頁面顯示問號或方塊現(xiàn)象HTML 里寫的中文在瀏覽器里變成???或亂碼。原因meta charset沒寫、寫錯位置、或者文件保存編碼和聲明不一致。解決確保meta charsetUTF-8是head的第一個子元素編輯器保存時選 UTF-8 無 BOM。如果還不行用 VS Code 右下角編碼切換成 UTF-8 再保存。5.2 樣式不生效現(xiàn)象是改了 CSS 但頁面沒變化現(xiàn)象修改style.css后刷新頁面樣式?jīng)]變。原因瀏覽器緩存、選擇器權(quán)重不夠、路徑寫錯、或者被其他樣式覆蓋。解決先按 CtrlF5 強(qiáng)制刷新再按 F12 看 Elements 面板里樣式有沒有被劃掉。如果路徑寫錯Network 面板會顯示 404。權(quán)重問題用!important臨時驗證但正式代碼別濫用。5.3 JS 報錯 “Cannot read property of null”現(xiàn)象是腳本中斷現(xiàn)象Console 里報Uncaught TypeError: Cannot read property xxx of null。原因getElementById沒找到元素通常是script在元素之前執(zhí)行了。解決把script放到/body前或者給script加defer屬性或者把代碼包在window.onload里。書里實例有些把 JS 放頭部你跑的時候注意調(diào)整。5.4 事件綁定多次觸發(fā)現(xiàn)象是點一次按鈕執(zhí)行了多次現(xiàn)象點擊按鈕回調(diào)執(zhí)行了兩次或更多。原因addEventListener被重復(fù)調(diào)用或者事件委托里沒判斷target。解決確保綁定代碼只執(zhí)行一次或者在綁定前先removeEventListener。事件委托里加if (target.tagName LI)過濾。書里事件那章有提到但新手容易忽略。5.5 浮動導(dǎo)致父元素高度塌陷現(xiàn)象是背景色不見了現(xiàn)象父元素設(shè)了背景色但子元素浮動后父元素高度變成 0背景色看不到。原因浮動元素脫離文檔流父元素計算高度時忽略它們。解決給父元素加overflow: hidden觸發(fā) BFC或者用::after偽元素清浮動。書里推薦后者代碼是.clearfix::after { content: ; display: block; clear: both; }邏輯說明clear: both清除左右浮動display: block讓偽元素占一行。參數(shù)說明content: 不能省否則偽元素不生成。把這個類加到浮動元素的父級上即可。6. 進(jìn)階技巧用實例版里的思路做一個小型倒計時組件書里最后幾章有綜合實例我挑一個倒計時的場景把 HTML、CSS、JavaScript 串起來。這個組件在很多活動頁、秒殺頁里都能用而且能幫你理解Date對象、setInterval和 DOM 更新的配合。先看結(jié)構(gòu)div idcountdown span classnum iddays00/span 天 span classnum idhours00/span 時 span classnum idminutes00/span 分 span classnum idseconds00/span 秒 /divCSS 部分用 flex 居中數(shù)字用等寬字體避免跳動#countdown { display: flex; justify-content: center; align-items: center; font-size: 24px; font-family: Courier New, monospace; gap: 10px; } .num { background: #333; color: #fff; padding: 8px 12px; border-radius: 4px; min-width: 50px; text-align: center; }JS 邏輯設(shè)定一個目標(biāo)時間每秒計算差值更新 DOM。注意setInterval的時間不準(zhǔn)用Date.now()計算實際差值更穩(wěn)。// 目標(biāo)時間2026-12-31 23:59:59 var targetDate new Date(2026-12-31T23:59:59).getTime(); function updateCountdown() { var now Date.now(); var diff targetDate - now; // 如果時間到了停止計時并顯示 00 if (diff 0) { document.getElementById(days).textContent 00; document.getElementById(hours).textContent 00; document.getElementById(minutes).textContent 00; document.getElementById(seconds).textContent 00; clearInterval(timer); return; } // 計算天、時、分、秒 var days Math.floor(diff / (1000 * 60 * 60 * 24)); var hours Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); var minutes Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60)); var seconds Math.floor((diff % (1000 * 60)) / 1000); // 補零 document.getElementById(days).textContent days 10 ? 0 days : days; document.getElementById(hours).textContent hours 10 ? 0 hours : hours; document.getElementById(minutes).textContent minutes 10 ? 0 minutes : minutes; document.getElementById(seconds).textContent seconds 10 ? 0 seconds : seconds; } // 先執(zhí)行一次避免頁面加載后等 1 秒才顯示 updateCountdown(); var timer setInterval(updateCountdown, 1000);邏輯說明targetDate用 ISO 格式字符串創(chuàng)建Date對象getTime()轉(zhuǎn)成毫秒時間戳。diff是剩余毫秒數(shù)。天、時、分、秒的換算用取模和除法。補零用三元表達(dá)式。setInterval每 1000 毫秒執(zhí)行一次但實際間隔可能偏差所以每次都用Date.now()重新計算而不是累加。參數(shù)說明clearInterval(timer)在倒計時結(jié)束時清除定時器避免無意義執(zhí)行。如果你要支持多個倒計時把邏輯封裝成函數(shù)傳入目標(biāo)時間和 DOM 容器。這個組件我后來在好幾個活動頁里復(fù)用改一下目標(biāo)時間就能上線。書里實例版沒有直接給這個案例但把Date、setInterval、DOM 操作都講到了組合起來就是這么一個東西。從那以后我每次寫倒計時都強(qiáng)制走一遍“先算差值再更新 DOM”的流程而不是用seconds--那種寫法因為后者在頁面切到后臺時會變慢甚至卡住。希望這個思路幫到你。本文還有配套的精品資源點擊獲取