2907 字
15 分钟

courses网站案例课程模块

欢迎来到我的博客!#

使用 Markdown 格式编写。

今天学到了什么#

  • gird布局默认设置
  • grid属性特征
  • 按钮不继承父元素的属性
  • outline属性介绍
  • transition不会被子元素继承
  • justify-content justify-items align-items align-content 的区别

User: 为什么设置了这个后,input会自动换行,如果不写的话,为什么页面缩小到一定程度,li里面的图标会缩小,而.search盒子不会缩小#

GitHub Copilot:

这是一个关于 Flexbox、Grid 布局以及盒模型固定宽度与弹性宽度的机制问题。下面为你解答这两个现象产生的原因:

1. 为什么设置了这就话后,input 会自动换行?#

你提到的代码块(在 @media (max-width: 700px) 中):

.course-r {
display: grid; /* 1. 改变布局模式 */
gap: 20px;
justify-content: center;
justify-items: center;
}
  • 布局模式改变:原本 .course-rdisplay: flex(Flex布局默认是水平排列,一行显示)。这段代码将其改为了 display: grid(Grid布局)。
  • 默认行为:在 Grid 布局中,如果你没有特别指定 grid-template-columns 来定义列数,默认情况下,每一个子元素(网格项)都会独占一行
  • 结果.icon 盒子作为第一个子元素占据第一行,.search 盒子作为第二个子元素就被挤到了第二行,这就是你看到的“自动换行”现象。

2. 如果不写(保持 Flex 布局),为什么缩小屏幕时 li 里的图标会缩小,而 .search 盒子不会?#

这是因为两者的内容宽度特性不同,在 Flex 容器空间不足进行收缩(shrink)时表现不一:

  1. Search 盒子是“硬”的(固定宽度)

    • 查看 index.css 可以发现,.search input 设置了具体的宽度:width: 204px;
    • 在 Flex 布局中,浏览器会优先保证这些有固定宽度的元素的内容能完整显示。.search 盒子的最小宽度被这个 204px 的 input 撑住了,它很难再被压缩。
  2. 图标区域是“软”的(弹性宽度)

    • .icon ul 使用了 repeat(7, 1fr)。这里的 1fr 是一个弹性单位,意思是可以根据剩余空间自由伸缩。
    • 同时,通常在响应式基础样式(如 base.css)中,图片都会设置 img { max-width: 100%; }
    • 过程:当屏幕变窄,Flex 容器空间不足 -> .search 盒子死守 204px 不退让 -> 压力全给到了左边的 .course-l(如果有)和 .icon 部分 -> 由于 1fr 允许被压缩,且图片支持 max-width: 100% 缩小,所以浏览器选择压缩图标区域来适应屏幕

总结:一边是写死了 px 的固定宽度,一边是 fr 的弹性宽度,Flexbox 在空间不足时,会优先牺牲那个弹性的部分。

User: 但是图片也设置宽度了啊#

GitHub Copilot: 你是对的,图片确实设置了固定宽度 width: 44px

但是,造成它们表现差异的根本原因并不在最底层的 img 标签上,而是在包裹它们的容器定义的“规则”上。

这里有一个“层级压制”的关系:

关键区别:fr (可以怂) vs px (我很刚)#

1. 左边 Icon 区域:外层容器“出卖”了它#

图标的父容器 .icon ul 是这样写的:

.icon ul {
display: grid;
grid-template-columns: repeat(7, 1fr); /* <--- 罪魁祸首在这里 */
gap: 20px;
}
  • 1fr 的含义fr 是 Fraction(片段/比例)单位。它的本质就是**“分配剩余空间”。既然是“分配”,就意味着它天生就是弹性的**。
  • 当屏幕空间不够时,父级 Flex 容器(.course-r)会向子元素施压。
  • .icon 盒子虽然里面的图片写了 44px,但因为它的布局规则是 1fr,它向父级传递的信号是:“我是弹性的,如果有必要,我可以被压缩”。
  • 于是浏览器就会压缩 1fr 计算出来的宽度(此时可能会小于 44px),而里面的图片通常配合了全局样式的 max-width: 100%(在基础 CSS 中常见),所以图片被迫跟着变小了。

2. 右边 Search 区域:直接定死#

搜索框是这样写的:

.search input {
width: 204px; /* <--- 这是一个没有任何商量余地的绝对值 */
/* padding 还会撑大它 */
}
  • .search 盒子内部没有任何弹性的布局规则(比如百分比或 fr)。
  • 它向父级 Flex 容器传递的信号是:“我内部有一个实实在在的 204px 的铁块,压缩我就会导致内容溢出或坏掉”。
  • 浏览器为了保护内容的可读性,在 Flex 布局计算剩余空间时,会优先保留这个“硬度”更高的宽度。

总结#

  • 图标变小是因为它的布局管理员(Grid 容器)用了 1fr 这个软性单位,虽然住户(图片)想占 44px,但房东(Grid)把只有 30px 的房间分给了它,它只能缩小。
  • 搜索框不变是因为它由内而外都是硬性像素(px) 撑起来的,浏览器不敢随便压扁它。
  • align-items: end 的意思是:每个子项按“自身内容高度”排版,然后在各自网格区域内靠底对齐

按钮不继承父元素的属性#

这是因为 <button>(表单元素)默认不会继承父级的文字颜色。

在 CSS 中,像 divpspan 这样的普通标签会自动继承父元素的 color。但是 buttoninput 等表单控件有浏览器自带的默认样式(User Agent Stylesheet),它的默认文字颜色通常是黑色。

虽然你给外层的 a 标签设置了白色,但里层的 button “不想听”,还是坚持自己的默认黑色。

解决方法#

你需要直接在 button 的样式里设置颜色:

/* ...existing code... */
.footer-con-left .item button {
display: flex;
align-items: center;
width: 144px;
height: 44px;
border-radius: 10px;
background: none;
gap: 10px;
/* 添加下面这一行 */
color: #fff;
/* 建议同时加上这两行去除默认边框和增加手型 */
border: 0;
cursor: pointer;
}
/* ...existing code... */

outline属性介绍#

outline 属性在 CSS 中用于在元素周围绘制一条线,位于边框边缘的外围。

在你选中的代码块中:

.footer-con-left .item button {
/* ...其他样式... */
border: 0;
outline: 0; /* <--- 这一行 */
/* ...其他样式... */
}

1. 作用#

outline: 0 (或者 outline: none) 的作用是移除元素默认的轮廓线

2. 为什么要写这个?#

  • 默认行为:如果你不写这一行,当用户点击这个按钮(或者用键盘 Tab 键选中它)使其处于 聚焦状态 (focus) 时,浏览器会自动在按钮周围加上一圈默认的蓝线(Chrome)或虚线(Firefox)。这通常被称为 “focus ring”。
  • 美观考虑:很多设计师觉得这个默认的蓝框很丑,和网站的整体设计风格不搭,所以开发人员通常会用 outline: 0 把它去掉。

3. outline 和 border 的区别#

  • Border (边框):占用空间,会改变盒子的尺寸。
  • Outline (轮廓)不占用空间,它是在盒子外面画的,不会把周围的元素挤开。

⚠️ 无障碍访问 (Accessibility) 警告#

虽然去掉它能让点击效果更好看,但也带来了一个副作用:键盘用户(使用 Tab 键浏览网页的人)看不出当前选中的是哪个按钮了

  • 最佳实践:如果去掉了默认的 outline,最好 manually(手动)为 :focus 状态定义一些样式(比如改变背景色或加个 shadow),以便让用户知道当前焦点在哪里。

你下方的 :hover 样式已经做了一些背景和阴影变化,这在鼠标操作时很好,但键盘操作时可能需要补充 :focus 样式。

不会。

transition不会被子元素继承#

transition(过渡)属性是不继承的。

这意味着给父盒子(.item)加了过渡,只有父盒子自己的属性变化(比如父盒子变大、背景变色)会有动画效果。子元素(比如里面的图片 img)并不会自动获得这个“平滑过渡”的能力。

为什么看起来好像起作用了?#

这是常见的错觉,分两种情况:

  1. 父元素带着跑(被动)

    • 代码中 .item:hover 触发了 transform: scale(1.1)(整体放大)。
    • 父盒子平滑放大的过程中,里面的图片、文字作为父盒子的一部分,当然也跟着一起平滑放大了。但这不叫继承,这叫“跟着动”。
  2. 子元素自己变(主动)

    • 代码中还写了 .item:hover figure>img { transform: scale(0.9); }(图片缩小)。
    • 关键点:如果图片自己没有写 transition,那么鼠标放上去的瞬间,父盒子在平滑变大,而图片会瞬间生硬地缩小。
    • 所以,你在代码第 262行 专门给图片也写了一句 transition: all 0.3s ...,就是为了让图片自己的变化也能动起来。

结论#

谁发生属性变化,谁就得自己加 transition 父元素的 transition 只负责父元素自己的变化。

justify-content, justify-items, align-items, align-content的区别#

这几个属性是 Flexbox(弹性布局)和 Grid(网格布局)中最容易混淆但也是最核心的控制属性。

它们主要控制两个方向:主轴(水平方向)交叉轴(垂直方向)

确实有 align-content 这个属性。下面是详细对比和解释:


1. justify-content (管局势 - 水平整体)#

  • 作用对象整体内容(所有子元素作为一个整体)。
  • 控制方向主轴(通常是水平方向 Left \leftrightarrow Right)。
  • 场景
    • Grid:把所有列放在容器的左边、中间、还是右边?
    • Flex:把所有子元素排在左边、中间、还是两头分开?
  • 常见值
    • center:整体居中。
    • space-between:两端对齐,中间拉开。
    • start / end:靠左 / 靠右。

2. align-items (管个体 - 垂直单行)#

  • 作用对象每一行里的单体
  • 控制方向交叉轴(通常是垂直方向 Top \updownarrow Bottom)。
  • 场景
    • Grid:这一行的格子里,内容是在格子的上边、中间、还是下边?
    • Flex:这一行的元素,是靠上对齐、居中对齐、还是拉伸填满高度?
  • 常见值
    • center:垂直居中(最常用)。
    • stretch:默认值,拉伸填满高度。
    • start / end:顶对齐 / 底对齐。

3. justify-items (管个体 - 水平单行)#

  • 注意这是 Grid 布局特有的,Flex 布局没有这个属性(Flex 里控制子项水平只能靠 margin: autojustify-content)。
  • 作用对象每一个格子里的内容
  • 控制方向水平方向(单个格子内部)。
  • 场景
    • Grid:不管格子多宽,我要让内容死死地守在格子的正中心。
  • 常见值center, start, end, stretch

4. align-content (管局势 - 垂直整体)#

  • 回答你的问题是的,有 align-content
  • 作用对象多行整体。只有当内容**折行(多行)**且容器高度有剩余空间时才生效。
  • 控制方向交叉轴(垂直方向整体)。
  • 场景
    • Grid/Flex:我有 5 行内容,容器很高。我是要把这 5 行整体打包放在容器顶部?还是垂直居中?还是把这 5 行上下分散开?
  • 区别
    • align-items 是管每一行内部怎么对齐。
    • align-content 是管这几行之间怎么排布。

总结速查表#

属性控制方向作用对象一句话口诀
justify-content↔️ 水平整体你们一伙人,靠左站还是靠右站?
justify-items↔️ 水平个体 (仅Grid)你自己在你的小格子里,居中还是靠边?
align-items↕️ 垂直个体 (单行)这一行的每个兵,头顶对齐还是居中?
align-content↕️ 垂直整体 (多行)这一堆行,是聚在头顶还是分散开?

赞助支持

如果这篇文章对你有帮助,欢迎赞助支持!

赞助
最后更新于 2026-01-18,距今已过 61 天

部分内容可能已过时

目录