【青训营】- CSS 入门 - 怎么总摆不对位置 😭

422 阅读5分钟

CSS (Cascading Style Sheet) 是通过一组一组的样式规则,来指定 HTML 元素的样式。入门 CSS 的时候,经常会遇到这样的问题。

为什么这个元素不在这里出现?为什么这个元素会在这里出现?

一、钦点(CSS 选择器)

CSS 要决定修改哪个元素的样式,就需要对 HTML 节点进行钦点(选择)。

CSS 中主要用到的有以下选择器:

  • 元素选择器
  • ID 选择器
  • 类选择器
  • 属性选择器
  • 伪类选择器

其中,属性选择器可以选择具备某些属性值的 HTML 标签。

img[src] {
  width: 100px;
  height: 100px;
}

以上示例中,我们选择了所有具有 src 属性的 img 标签。即所有的 <img src="">

二、子承父业(层叠与继承)

先来看一个简单的例子。在 HTML 中有一个简单的 div。

<div class="demo"></div>
.demo {
  width: 100px;
  height: 100px;
  /*   先设置红色背景 */
  background-color: red;
}

.demo {
  /* 再设置蓝色背景 */
  background-color: blue;
}
See the Pen Cascading & Inheriting by Yiyang Sun (@syycn) on CodePen.

可以通过 codepen 看到,最终这个 div 显示的颜色为 蓝色

给这个蓝色的 div 加一个红色的边框,设置字体颜色为白色,再给其中放入一个 span 会是什么效果?

<div class="demo2">
  <span>我是 span</span>
</div>
.demo2 {
  width: 100px;
  height: 100px;
  background-color: blue;
  border: 10px solid red;
  color: white;
}

span {
}

可以看到,字体颜色背景颜色 继承了父元素的样式,而 边框 并未默认继承样式。

除此之外,还有一些其他的特性,可以在 codepen 上进行探索。

简单总结一下:

  • 选择器越具体,优先级越高
  • 后出现的样式会覆盖前面出现的样式
  • colorbackground-color 等属性会默认继承父元素样式,border 属性不会默认继承父元素的样式。

三、盒模型

说起 CSS,不得不提起一个重要的概念,那就是 盒模型

我们可以把网页上的元素想象成一个个盒子,这个盒子由以下四个部分组成:

  • 外边距 - margin
  • 边框 - border
  • 内边距 - padding
  • 内容 - content

image-20210818202658435.png

在开发过程中,常接触到两种盒子:

  • content-box
  • border-box

两者的区别主要体现在盒子长宽的计算上。

这里盒子的长宽指的是 border 之间的距离(含 border)。

3.1 content-box

.box {
  box-sizing: content-box;
  margin: 10px;
  border: 5px solid black;
  padding: 20px;
  width: 40px;
  height: 30px;
}

对于上面这个盒子而言,它的宽度为 (5px + 20px) * 2 + 40px = 90px,它的高度为 (5px + 20px) * 2 + 30px = 80px。也就是说,我们在 CSS 中设置的 widthheight 属性,并不是盒子真实的宽高,而是 content 区域的宽高

3.2 border-box

.box {
  box-sizing: border-box;
  margin: 10px;
  border: 5px solid black;
  padding: 20px;
  width: 40px;
  height: 30px;
}

在日常开发中,我们希望所设置的 widthheight 的值就是盒子真实的宽高,就可以使用 border-box

如果我们让 border-boxpaddingborder 的总宽度和总高度恰好与 widthheight 相等,会发生什么呢?

See the Pen Border-box Test by Yiyang Sun (@syyCN) on CodePen.

感觉很是神奇,当边框或内边距单独变得很大时,会侵占 content 区域的空间;当它们的总宽高大于 widthheight 时,这个宽高值的设置就不起作用了,多出来的部分会向外扩展。

The content box can't be negative and is floored to 0, making it impossible to use border-box to make the element disappear. [1]

这是 MDN 上的一段话,意思是 border-box 中,content 区域不能为负值,最小值是 0,这使得不能使用 border-box 来让元素消失。

这也就解释了为什么 padding 或者 border 过宽时,会向外扩展。

四、布局

常用的布局方式有两种:

  • 弹性布局 (Flex)
  • 定位 (Position)

关于 Flex 布局和 Position 布局,其最大的区别是 Position 布局有可能使元素脱离文档流。脱离文档流的元素,其任何样式上的变化不会引起 重绘和回流

关于这两种布局方式,回头可以单独整理一下其中常用的属性值,先在这里挖一个大坑 🕳。

五、装饰

对 HTML 的装饰主要包括以下几种:

  • 字体相关
  • 背景
  • 阴影
  • 交互相关 (hover 等)
  • 动画

其中,阴影和 CSS 3 的动画是两门很深的学问。当下比较火的 新拟态 就是巧妙利用的光影,模拟真实世界;而有一些比较炫酷的动画效果是可以通过 CSS 来实现的。

这里推荐一位 B 站的 Up 主,CodingStartup 起码课。他经常会更新一些有趣的前端小 demo。

六、CSS 发展

6.1 调试 CSS

平时在编写 CSS 样式的时候,如果改一次参数,跳转到浏览器看一下效果,不合适再改,这样效率会比较低下。

推荐的方法是使用浏览器的开发者工具,选中某个节点直接进行对其样式进行修改,可以实现实时修改,实时预览。

6.2 CSS 扩展

现在有比较流行的 CSS 预处理器,例如 SCSSLESS。这些 CSS 预处理器很好地实现了样式的嵌套,便于代码的维护。

不过 CSS 原生似乎也在向这个方向前进,最近 CSS 原生嵌套语法在前端社区中比较火,未来如果 CSS 支持了嵌套语法,这些预处理将何去何从,我们拭目以待。

6.3 CSS 革新

革新主要分为两类:

  • css-in-js
  • utility-class

第一种是把 CSS 集成到 JS 中进行编写和管理。

第二种是 语义化类名,以 tailwind 为代表。一个 CSS 类名对应一种特定样式,这样只需要在 HTML 中写类名,而不需要重复编写样式代码。

语义化类名通过限制 CSS 样式的可选择性,来提升对 CSS 代码的管理。

七、小结

参加 字节青训营,听行业内的大牛们讲课,深感知识积累以及基础的重要性。

通过简单整理 CSS 相关的知识,我学习到了第一次粗略学习时没有关注到的点。

温故而知新~

参考

[1]box-sizing - css: cascading style sheets | mdn