网页开发入门|06 层叠样式

网页中的样式效果之间的继承关系,导致有一些样式被覆盖和遮挡,而其它的依然露了出来,层峦叠嶂,这就是层叠样式表CSS(Cascading Style Sheets)。

网页开发入门|06 层叠样式

不知道经过上一节的综合练习后,你是否感受了使用代码进行创作的快乐,希望如此😊

欢迎来到快乐星球
欢迎来到快乐星球

不过,快乐之余,我们还是留下了一些没有解决的问题,导致最终的成稿和设计之间出现了一些差异。为了解决这些问题,还需要的一些新的知识,咱们将在接下来的几节课中依次展开。

在本节课,让我们先把目光聚焦在一个可能会被忽视的细节上。为了发现它,让我们再次观察一下上节课中的这段代码:

<div style="font-size: 0.9em; color: gray">
  【作者】
  <a href="https://baike.baidu.com/item/王之涣"
    style="text-decoration: none">王之涣</a>
	【朝代】唐
</div>
王之涣三个字的字体变小了,但颜色却不是灰色
王之涣三个字的字体变小了,但颜色却不是灰色

明明是在div标签的style属性中设定的font-size,怎么对a标签里的内容也生效了呢?

而与此同时,同样也进行设定了的color却没有类似的效果,又是为什么呢?

对这个问题的探索,将为我们打开一片新的天地。

样式的继承

让我们先关注font-size所产生的效果,这里的div元素是a元素的父元素。当我们对父元素设定样式时,对子元素也生效了。

这个能力被称作继承inherit

Inherit被翻译成了继承,但它在英文中还有另外一个含义「通过遗传获取特征」。其实在这里,更接近「遗传」的含义,即子元素遗传了父元素的样式。但是为了和主流的说法保持一致,我们后文中仍然会使用「继承」的说法。
龙生九子,各不相同,但都遗传龙的一些特点
龙生九子,各不相同,但都遗传龙的一些特点

子元素不仅会继承父元素的样式,还能继承父元素的父元素,以及一路向上的所有祖辈元素。

继承可以让我们很方便的,一次性为一大片的元素设定统一的样式。比如,我们现在需要将上节课中图文页面中文字的字体全部改为楷体。

为了不破坏上节课的成果,建议大家在workspace中复制一份poem.html,命名为poem2.html,接下来的尝试都在这个副本中进行。

需要说明的是,在不同的设备和操作系统中,自带的字体并不完全一样。如果我们给网页中的文字设定的字体,并未被安装到用户的系统中,那就不会有任何效果。

简单起见,我们只考虑MacOS和Windows上的情况。在这两个系统上,自带的楷体分别叫STKaiti, KaiTi

幸运的是用于修改字体的font-family支持同时指定多个字体,并将找到的第一个可用字体作为最终的效果,就像这样。

font-family: STKaiti, KaiTi

通过在每一段文字的style属性进行设定font-family,便可以将页面中的文字全部改为楷体。

<h1 style="font-family: STKaiti, KaiTi">登鹳雀楼</h1>
<div style="font-size: 0.9em; color: gray; font-family: STKaiti, KaiTi">
    【作者】
    <a href="https://baike.baidu.com/item/王之涣"
    style="text-decoration: none">王之涣</a>
    【朝代】唐
</div>
<!-- 此处省略部分代码 -->

想想看,如果页面中有几百段文字,如果要对每个段落都要进行设置,岂不是很麻烦?但是如果我们有一个所有元素的公共父元素,便可以通过样式的继承能力,快速达到相同的效果。

我们可以使用body标签作为这个公共父元素。body是W3C建议的,用于包含网页中所有元素的标签,天然就是所有元素的父元素。

<body style="font-family: STKaiti, KaiTi">
  <h1>登鹳雀楼</h1>
  <div style="font-size: 0.9em; color: gray">
      【作者】
      <a href="https://baike.baidu.com/item/王之涣"
      style="text-decoration: none">王之涣</a>
      【朝代】唐
  </div>
  <!-- 此处省略部分代码 -->
</body>
body是页面中所有元素的父元素,所以body标签在一个网页中有且只能有一个。虽然我们在之前写的代码中,从来没有明确的写上body标签,其实浏览器都会在渲染网页之前,自动的帮我们补上它。

尽管继承如此方便,但并不是所有的样式属性都会(默认)被继承,你可以通过尝试或查阅文档了解不同样式属性的继承性。

样式的覆盖

如果一个子元素不想全盘继承来自父元素的样式,子元素也可以明确的设定自己的样式,以覆盖override继承的效果。

比如说,我们想在其它内容依然保持楷体的情况下,只把文章标签这部分文字修改为宋体(MacOS:STSong,Windows:SimSun),便可以直接在元素的style中直接设定新的字体。

<body style="font-family: STKaiti, KaiTi">
  <!-- 此处省略部分代码 -->
  <div style="font-size: 0.9em; font-family: STSong, SimSun">
    标签:
    <a href="#" style="text-decoration: none; background-color: lightgray">写景</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">登楼</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">唐诗三百首</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">哲理</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">黄河</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">场景</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">励志</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">景色</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">山水</a>
    <a href="#" style="text-decoration: none; background-color: lightgray">数字</a>
  </div>
  <!-- 此处省略部分代码 -->
</body>
对子元素设定的样式覆盖了来自父元素的继承
对子元素设定的样式覆盖了来自父元素的继承

这个覆盖的效果也可以解释开篇的问题,为什么a元素中的文字依然保持了蓝色:

abi等标签有自带的样式效果,相当于在style属性中设定了样式。在作为子元素时,它们的自带样式的覆盖了来自父元素的继承。

样式的层叠

如果父元素设定了多个样式属性,子元素只对其中的一些进行了覆盖,剩余的那些依然可以保持继承性,并不会全面的否定。

再来到页面中作者和朝代这里看一下,父元素div同时设定了字体大小font-size和颜色color

<div style="font-size: 0.9em; color: gray">
  【作者】
  <a href="https://baike.baidu.com/item/王之涣"
  style="text-decoration: none">王之涣</a>
  【朝代】唐
</div>
王之涣三个字的字体变小了,但颜色却不是灰色
王之涣三个字的字体变小了,但颜色却不是灰色

子元素a自带颜色为蓝色的样式属性,于是颜色效果就被覆盖了。然而,a并不自带字体大小样式属性,所以父元素中的font-size对子元素a依然生效。

网页中的样式效果就像这样,有一些继承,有一些被覆盖遮挡,有一些露了出来,层峦叠嶂,于是给网页中的设定样式的这些代码,被起了一个非常形象的名字——层叠样式表CSS(Cascading Style Sheets)

就像山的层叠一样,离得越近就越完整,远处的就会被遮住一部分,漏出一部分
就像山的层叠一样,离得越近就越完整,远处的就会被遮住一部分,漏出一部分

CSS也是W3C所推荐的网页样式标准,至今已经发展到到了第三代,即CSS3。

style标签

CSS在网页中扮演了非常重要的角色,但是像我们之前一样,把样式代码和内容代码混在一起写,非常不利于阅读和维护。

于是便有了一个专门用来给页面元素设定样式的style标签,可以把样式代码,也就是CSS,单独抽出来存放和编写,就像这样:

<style>
  a {
    text-decoration: none;
    color: lightskyblue;
  }
</style>

在这段代码中,大括号前的a是一个选择器,它选中了页面里全部的a元素。

选择器可以选中页面中的一些元素,并告诉浏览器,要对它所选中的元素进行样式设定,而要设定的样式属性,正是大括号里的代码所决定的。

选择器的类型有很多,用于准确选中具备某些特点的元素,我们将在下一节课更加详细的展开关于选择器的内容。

大括号里的CSS代码的写法,比较简单,与我们之前在元素的style属性里所写的方法完全一样。为了增强可读性,建议将每个样式属性单独写成一行。

所以上面的代码的整体含义是:将页面中所有a元素的下划线去除,并将它们的颜色设定为浅天蓝色。

但还有一个问题,style标签该写在哪里?

style标签里的代码只是一些样式,并不会也无法直接在页面上显示出什么内容,它是对页面的一些整体性描述或设置。这类的内容,被称作的元信息Meta-information

照片Exif信息就是一种元信息,它存储了拍摄时的一些重要参数
照片Exif信息就是一种元信息,它存储了拍摄时的一些重要参数

元信息与别的元素非常的不同,它不存在于页面的主要结构中,好像写在哪里都有点怪怪的。

为了解决这个问题,W3C定义了一个与上面小节介绍过的body标签相对应的标签headhead是网页中所有元信息的父元素,所以style可以放到head标签内。

<head>
  <style>
    a {
      text-decoration: none;
      color: lightskyblue;
      }
  </style>
</head>
<body style="font-family: STKaiti, KaiTi">
  <!-- 此处省略部分代码 -->
</body>

有了在style标签里定义的样式之后,我们原本在每个a元素中写的text-decoration: none就不再需要了。最终的代码类似于这样:

<head>
  <style>
    a {
      text-decoration: none;
      color: lightskyblue;
      }
  </style>
</head>
<body style="font-family: STKaiti, KaiTi">
  <h1>登鹳雀楼</h1>
  <div style="font-size: 0.9em; color: gray">
      【作者】
      <a href="https://baike.baidu.com/item/王之涣">王之涣</a>
      【朝代】唐
  </div>
  <hr>
  <p>白日依山尽,黄河入海流。</p>
  <p>欲穷千里目,更上一层楼。</p>
  <div style="font-size: 0.9em; font-family: STSong, SimSun">
    标签:
    <a href="#" style="background-color: lightgray">写景</a>
    <a href="#" style="background-color: lightgray">登楼</a>
    <a href="#" style="background-color: lightgray">唐诗三百首</a>
    <a href="#" style="background-color: lightgray">哲理</a>
    <a href="#" style="background-color: lightgray">黄河</a>
    <a href="#" style="background-color: lightgray">场景</a>
    <a href="#" style="background-color: lightgray">励志</a>
    <a href="#" style="background-color: lightgray">景色</a>
    <a href="#" style="background-color: lightgray">山水</a>
    <a href="#" style="background-color: lightgray">数字</a>
  </div>
  <p>
    <img src="assets/王之涣.jpg" alt="王之涣">
  </p>
</body>
页面中所有超链接的颜色都变成了浅天蓝色,也都不再有下划线了
页面中所有超链接的颜色都变成了浅天蓝色,也都不再有下划线了
我将本课程所有的代码托管在gitee上了,你可以点击这个链接,或到gitee.com上搜索弦五 网页开发入门,查看和获取本课程的全部代码。