从昨天写下第一行HTML代码到今天,中间隔了一个晚上,但脑子里始终没停下来。DAY1我搞清楚了网页的基本结构,理解了标签、属性、层级,还做出了一个只有标题、段落和链接的简陋页面。看着那个白底黑字的页面,说实话挺有成就感的——它能运行了,但它离“好看”差得实在太远。所以我给DAY2定了一个目标:学会给网页上样式,让页面从“能看”变成“想看”。
这篇文章记录的就是我这一整天的学习过程。我会从CSS最基础的选择器、盒模型讲起,再到我用Flexbox做的第一个导航栏,最后记录一个让我卡了二十分钟的问题排查过程。如果你也是零基础、正在学前端,或者想通过别人的学习路径来梳理自己的体系,这篇日记应该能给你一些参考价值。
1. 第一天遗留的“地基”问题:HTML只负责骨架,视觉要交给CSS
1.1 我DAY1做的页面处于什么水平
DAY1结束时,我的页面长这样:一行大标题,两段正文,中间放了一个链接,然后没了。HTML结构大概是这样:
html复制<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>我的第一个网页</title>
</head>
<body>
<h1>欢迎来到我的学习日记</h1>
<p>这是我的第一段文字,是用HTML写的。</p>
<p>点击这里查看<a href="https://example.com">一个链接</a>。</p>
</body>
</html>
当时我觉得挺牛的,因为浏览器真的把这段文字渲染出来了。但把页面缩小、放大、换个屏幕再看,问题全暴露了:标题贴着页面顶部,没有任何呼吸感;文字默认是黑色,链接默认是蓝色下划线;两个段落之间的距离也不对,看起来像挤在一起。说白了,这就是一个典型的“毛坯房”,HTML把所有砖块垒好了,但没有贴瓷砖、没有刷漆、没有做任何软装。
我原本以为做一个好看的网页要学很复杂的东西,但昨天搜了一圈资料后发现,网页的“装修”工作基本上都交给了CSS。CSS全称是Cascading Style Sheets,中文叫层叠样式表,它专门负责控制元素的颜色、大小、间距、位置、排版方式等等。HTML负责内容,CSS负责表现——这两个东西分开设计,是前端开发里最重要的基础思想。
1.2 我列出的DAY2学习计划
DAY2一开始,我没有直接翻教程,而是先给自己提了三个问题:
- 怎么给文字换颜色、换字体、调大小?
- 怎么把一组链接排成一行,做成导航栏?
- 为什么有些人写的CSS会不生效,到底哪些因素会影响样式?
这三个问题刚好对应了CSS里三个最核心的知识模块:选择器与属性、盒模型与布局、优先级的判断。我原本打算一天就学会所有CSS内容,但翻了翻目录发现,CSS光属性就有上百个,想一口吃成胖子完全不现实。所以我把范围缩小,今天只搞定三个点:选择器、盒模型、Flexbox。至于动画、响应式、Grid等高级内容,全部留到后面。
这里也顺便给同样在自学的人一个建议:学习前端一定要学会“切分目标”,不要试图一天学完一个大章节。CSS是一门需要大量练习才能内化的语言,一天能扎实掌握三四个概念就已经很了不起了。贪多求快的唯一结果,就是第二天发现什么都记不住。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 从页面到“悦目”:CSS选择器与盒模型的核心练习
2.1 选择器优先级:写CSS时最常遇到的顺序问题
上午我从最简单的入手:给HTML文件配上CSS。CSS有三种写法,我刚学的时候完全分不清适用场景,现在用一天下来,总算理清楚了:
第一种:内联样式(Inline Style)
直接在HTML元素的style属性里写样式:
html复制<p style="color: red; font-size: 18px;">这段文字是红色</p>
这种写法最直接,但非常不推荐日常使用。因为样式被硬编码在HTML里,一旦想统一修改,就得一个一个元素去改,维护成本极高。
第二种:内部样式表
把CSS写在HTML文件的<style>标签中,通常放在<head>里。适合单页面做一些简单样式,或者临时调试时用:
html复制<style>
p {
color: blue;
}
</style>
第三种:外部样式表(最推荐)
单独建一个.css文件,然后用<link>引入:
html复制<link rel="stylesheet" href="style.css">
然后把所有样式写进style.css。这种方式的优势非常明显:一个CSS文件可以被多个页面共用,想换主题时只需要改一个地方,浏览器还能缓存它,加载速度更快。
我DAY2选择的是第三种方式,因为我觉得既然要长期学,就应该从一开始就养成规范的习惯。
接下来自然遇到了一个绕不开的概念:选择器。选择器说白了就是“告诉CSS,你要给哪些元素上样式”。我梳理了一遍,发现常用选择器其实就四种:
| 选择器类型 | 写法 | 作用范围 | 示例 |
|---|---|---|---|
| 标签选择器 | p |
所有该标签 | p { color: gray; } |
| 类选择器 | .className |
所有class属性为该值的元素 | .intro { font-size: 20px; } |
| ID选择器 | #idName |
唯一一个指定ID的元素 | #header { height: 60px; } |
| 后代选择器 | div p |
div内部的所有p元素 | div p { margin: 10px; } |
我一开始以为选择器只用记语法就行了,结果很快就踩了坑。我给一个段落同时用了.类选择器、p标签选择器和内联样式,结果发现它们同时生效时,到底听谁的?我做了个简单测试:
html复制<style>
p {
color: blue;
}
.highlight {
color: red;
}
</style>
<p class="highlight" style="color: green;">这行字到底是什么颜色?</p>
最后浏览器显示的是绿色。然后我查了一下优先级规则:内联样式 > ID选择器 > 类选择器 > 标签选择器。如果优先级相同,则后面的覆盖前面的。后来我还知道有个!important可以打破这个规则,但大部分情况下不应该用——它是一个“核弹级”手段,用了之后会让层级关系变得很难维护。
这个知识点看起来简单,但它解释了“为什么我写了CSS却不生效”的很多情况。很多新手包括我,最开始的反应就是“是不是我写错了”,其实更可能是优先级不够,被别的样式覆盖了。所以遇到样式不对时,第一件事应该想自己碰上的是不是优先级问题。
2.2 盒模型:一个边距让我多花二十分钟的案例
学习选择器之后,我开始做今天的第一个小项目:做一张卡片,卡片里放一段简介文字。页面很简单,但我想让它看起来干净一点,于是给它加了边框、内边距和外边距,结果第一次接触了“盒模型”这个概念。
盒模型是CSS布局里的最底层逻辑:每个HTML元素都可以看作一个矩形盒子,从里到外依次是内容区(content)、内边距(padding)、边框(border)和外边距(margin)。当你设置宽度时,默认情况下宽度只作用于内容区,这跟我最初的理解完全不一样。
我实际遇到的问题是:我打算做一个宽300px的卡片,内容区正好放一段文字,然后我加了padding: 20px,结果整个卡片变成了340px宽,跟设计稿对不上。我还以为是浏览器出错了,后来才发现,内容区、padding、border这三部分是要叠加的,最终元素总宽度=内容宽度+左右padding+左右border。
如果在实际项目中频繁遇到这种宽度计算的问题,有个很实用的属性可以解决问题,就是box-sizing。设置border-box后,宽度就包含padding和border了,整体计算会方便很多。不过我当时为了彻底理解“默认模式下为什么会撑大”,还是先保留了默认值,亲手感受了一遍盒子被撑大的全过程。我觉得初学阶段做这种“反向验证”是值得的。一个知识点,光看教程是记不牢的,必须自己验一遍,整理进自己的经验体系。
边距属性里还有一个特别隐蔽的坑:外边距折叠。当两个垂直方向的元素都有margin时,它们之间的间距不会是两个margin之和,而是取其中的最大值。比如上面元素的margin-bottom: 30px,下面元素的margin-top: 20px,最终两个元素间只有30px,不是50px。
我第一次遇到这个现象的时候,以为是代码哪里写错了,调了半天才发现是两个margin互相“合并”了。这个现象只发生在垂直方向,水平方向不会折叠。了解这个机制之后,我在给纵向元素设置间距时,会刻意只使用一个方向(比如只用margin-bottom)来避免认知混乱。这个小习惯,越往后学越觉得省心。
3. 用Flexbox实现页面居中的完整过程
3.1 为什么我用传统方法居中都有点别扭
上午解决了样式基本问题,下午就开始折腾布局。我想做一个效果:页面中间有一行文字,垂直水平都居中。听起来简单,实际上我在传统方案里绕了不少弯路。
一开始我用text-align: center给文字水平居中,非常顺利,一行代码就搞定了:
css复制text-align: center;
但垂直居中就没这么好搞了。我尝试给父元素设置一个固定高度,然后给子元素设置margin-top: 自动计算的一半,这明显不可行,因为一旦字号变化或屏高变化,就全乱套。我也试过把元素转换成display: table-cell再搭配vertical-align: middle,这种方式能实现,但总是觉得非常绕,不够直观。
正当我准备放弃垂直居中,先做横向导航栏的时候,我看到一篇文章里反复提到display: flex,也就是Flexbox弹性盒布局。学完这个概念,我才明白为什么以前那些方案都“差点意思”——它们是在用面向文档流的思路去解决一个需要面向空间排列的问题。而Flexbox的设计初衷,就是解决在一维方向上分配空间、对齐元素的问题,正好命中这类需求。
3.2 导航栏从零到能用:一个完整的练习过程
我决定用Flexbox做一个横向导航栏。HTML结构很简单,就是一个带链接的列表:
html复制<nav>
<ul>
<li><a href="#">首页</a></li>
<li><a href="#">学习笔记</a></li>
<li><a href="#">项目作品</a></li>
<li><a href="#">关于我</a></li>
</ul>
</nav>
默认情况下,ul里的li是纵向排列的,而且ul自带缩进和圆点,需要先清掉:
css复制nav ul {
list-style: none;
margin: 0;
padding: 0;
display: flex;
}
关键就是最后一行display: flex。这行代码让ul变成了一个弹性容器,里面的子元素li立刻从纵向排列变成了横向排列,这个改变给我的冲击还挺大的,因为一行代码就完成了传统CSS要用float加各种清除操作才能做到的效果。
但我很快就发现,列表虽然横向了,但都挤在左边缘,我的目标是让它们均匀分布在整个导航栏里。于是添加了:
css复制nav ul {
display: flex;
justify-content: space-between;
}
justify-content: space-between的意思是:子元素两端对齐,剩余空间自动分配到子元素之间。于是我看到了很典型的导航栏效果:最左边一个链接,最右边一个链接,中间的链接均匀分布。
接下来我想让导航栏在垂直方向上也居中,因为虽然链接文字自然分布在水平方向,但如果导航栏高度变高,文字就会紧贴顶部。这里要用到align-items: center:
css复制nav ul {
display: flex;
justify-content: space-between;
align-items: center;
height: 60px;
background-color: #2c3e50;
}
align-items控制的是交叉轴方向的对齐,在默认的横向布局下,就是垂直方向上的对齐。设置成center后,菜单文字总在60px高度的垂直居中位置。
到这一步,我已经能做出一个像模像样的导航栏了。后来又给链接加了一点内边距,让点击区域更大,同时改变了颜色和hover效果:
css复制nav a {
color: white;
text-decoration: none;
padding: 8px 16px;
border-radius: 4px;
transition: background-color 0.2s;
}
nav a:hover {
background-color: #34495e;
}
到这个时候我才突然意识到,“布局”这个听起来很高级的词,其实就是通过几个属性组合控制元素的排布方式。justify-content处理主轴上的分布,align-items处理交叉轴上的对齐,flex-wrap控制是否换行。三个属性搭配起来,就已经能解决绝大多数常见布局问题了。
顺便讲一个我练习时反复用到的属性:flex: 1。当几个子元素设置了这个属性后,它们会等分容器的剩余空间。我做了个快速实验:
html复制<div class="container">
<div class="box">A</div>
<div class="box">B</div>
<div class="box">C</div>
</div>
css复制.container {
display: flex;
}
.box {
flex: 1;
border: 1px solid #ccc;
text-align: center;
}
三个盒子自动等宽,铺满了整个容器。这个能力在制作卡片列表、侧边栏、底部栏等场景下非常常用,建议初学者无论如何都要亲手练一遍。
4. 排查记录:样式不生效的三种常见原因
4.1 从审查元素开始的排错法
DAY2最大的收获可能不是学会了几个属性,而是我第一次完整地走完了一个“样式不生效”的排查过程。下午做Flexbox练习的时候,我给一个卡片加了一行类名,然后去style.css里写了样式,刷新浏览器,发现样式完全没反应。
我记得清清楚楚,CSS是这样的:
css复制.card {
background-color: #f0f0f0;
padding: 20px;
border-radius: 8px;
}
HTML是这样的:
html复制<div class="card">
卡片内容
</div>
怎么看都没问题。一开始我怀疑是浏览器缓存了旧CSS文件,于是按了Ctrl + F5强制刷新,没用。然后又怀疑是文件路径不对,检查了link标签的href,也没问题。最后我打开了浏览器的开发者工具(Windows按F12,Mac按Option+Command+I),在Elements面板中点中那个div.card,右边找到了Styles面板,发现一个可怕的事实:.card规则根本没有出现在样式列表里,就好像它不存在一样。
经过一段时间的排查,我把这个“样式不生效”的排查方法论总结了出来。对于这种问题,第一件事绝对不要盲目改代码,而是按顺序检查以下三层:
- 检查CSS文件是否被正确加载到页面上(看Network面板里有没有该文件)。
- 在Elements面板选中目标元素,看Styles区域是否有匹配的规则。
- 如果有匹配规则但显示被划掉,说明有更高优先级或后面的规则覆盖了它。
我当时卡在第1步之后,是因为我根本没有想到样式表文件压根没被正确加载。后来发现,我犯了一个特别低级的错误:把style.css放在了css子目录里,但link标签里我只写了href="style.css"。文件确实存在,但浏览器在根目录找不到它,于是返回404。我盯着HTML代码看了很久,却忘了核对文件目录结构。
4.2 类名、层级、缓存:最容易忽略的三个坑
这次经历让我把“CSS不生效”的常见原因认认真真整理了三个。对新手来说,这几乎就是踩坑重灾区。
坑一:类名拼写不一致,或者误用了ID选择器
HTML里class="card",CSS里写成.crd,这很难一眼发现。我建议初学者在写HTML类名和CSS选择器时,尽量使用有意义的单词,而且保持一致。实在不行就利用编辑器的全局搜索(Ctrl+Shift+F)搜索类名,检查是否存在拼写不同。
另外一个容易搞混的是ID选择器和类选择器。ID在同一个页面只能出现一次,而且优先级比类高。如果你在HTML里用id="card",在CSS里却用.card去选中它,那肯定不生效。需要区分:
css复制#card { } /* 对应 id="card" */
.card { } /* 对应 class="card" */
坑二:选择器层级不匹配
我学HTML的时候就知道了,元素可以嵌套,但到我写CSS时才发现,嵌套关系直接影响选择器的生效范围:
div p:选中的是div内的所有p(包括孙子元素)div > p:选中的只是div的直接子元素p,孙子辈的p不会被选中div + p:选中的是div后面紧邻的兄弟p
我一开始总混淆“后代”和“子元素”这两个概念,导致样式要么多生效,要么不生效。比如我想给直接子元素加边框,用了div p,结果内层还有段落,边框全加到内层段落上了,跟预期完全不一样。改成div > p,才正确选择了直接子元素。
坑三:浏览器缓存旧CSS
很多时候你明明改了代码,刷新后浏览器却还在用旧的样式。这是因为浏览器会把CSS文件缓存起来,为了强制刷新可以使用Ctrl + F5,或者打开开发者工具后右键刷新按钮选“清空缓存并硬性重新加载”。这也是很多新手觉得“我改了但没反应”的原因。这种时候,也许你的代码根本没有问题,只是浏览器没重新加载而已。
排查完这三个坑之后,我最大的体会是:排查样式问题的核心从来不是“猜”,而是用开发者工具去看浏览器到底拿到的是什么文件、匹配到了哪些规则、有哪些规则被覆盖。只要按这个顺序走一遍,绝大多数样式问题都能快速定位。这个习惯越早养成,后面学任何前端框架都会受益。
5. 今日复盘:第二天的学习节奏与明日安排
5.1 如果用“能做出什么”来衡量今天的完成度
DAY2结束时,我把自己写的页面打开,跟DAY1的毛坯页面对比。差距已经很明显了:导航栏整齐地分布在顶栏,卡片有了背景、圆角和内边距,文字也不再挤在一起,而是有了充足的呼吸感。能完成这些视觉效果,说明我至少已经跨过了“会拼HTML”到“会做基本页面样式”的这个门槛。
如果按“能做”来打分,我知道自己今天能做到以下这些事情:
- 给元素设置颜色、字号、背景、边框、内边距、外边距
- 使用类选择器和后代选择器去匹配指定元素
- 用Flexbox实现横向导航栏、水平垂直居中、等分布局
- 通过开发者工具定位样式不生效的原因
我还做不到的事情也非常明确:响应式布局还不会,页面在小屏上一缩小就会乱;Flexbox里的flex-grow和flex-shrink的细节逻辑还不熟;更别说Grid、动画这些进阶内容。
这种“知道自己会什么,也知道自己还不会什么”的感觉,比单纯看教程要踏实得多。因为学习最怕的是“我好像都看懂了”的错觉。看懂了和能做出东西之间,隔着一道巨大的练习鸿沟。今天一天下来,我至少反复验证了这一点:每敲一遍代码,理解就深一层。
5.2 我根据这一天的实操,给明天的路线做了调整
原本我打算第三天就开始学JavaScript,但今天临睡前复盘了一下,发现自己今天学Flexbox时,很多地方还是在“照葫芦画瓢”。比如justify-content的取值有flex-start、flex-end、center、space-between、space-around、space-evenly,我知道它们各自的效果,但还没到不用查资料就能熟练应用的程度。如果这种基础布局能力都不牢固,后面学JavaScript做动态交互时会更吃力。
所以我把明天的学习计划调整为:继续巩固半天Flexbox,再做两个小项目来检验,同时补一补响应式设计的入门知识。目标很具体,第一个项目是做一个上面导航栏、下面三栏卡片的内容区,第二项目是做一个简单的个人名片,在手机和平板上都要能正常显示。等这两个项目做完了,才正式进入JavaScript。
这里有一段话想分享给同样在学前端的人:学习路径上最大的坑,不是“学得慢”,而是“以为学会了,结果根本做不出来”。所以与其按章节顺序追进度,不如每学一个知识点,都给自己出一个小题目,做出来了再往下走。进度慢一点没关系,基础扎实了,后面遇到框架、工程化工具时,才知道它们到底在解决什么问题。如果一上来就图快,后面只会加倍返还。
今天这篇学习日记先记到这里。DAY2最大的心得,就是CSS没那么神秘,它不过是一套帮助你控制“视觉表现”的规则;但CSS也没那么简单,它需要大量的实践来形成手感和排查能力。如果你也正在学习前端,不妨也试着写下自己的每天复盘,不用很长,关键是记录“今天做成了什么”和“卡在哪里”,第二天重新看的时候,很多问题会比当时清醒得多。
