区块链技术博客
www.b2bchain.cn

今天听什么歌?求职学习资料

本文介绍了今天听什么歌?求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

在上一节我们一起学习了 JavaScript,涉及的东西比较多,可能你会感觉到有点难也有点枯燥。这是很正常的,不需要为此担心。这一节我们一起来做一个好玩的东西,一个随机选择今天要听的歌的小页面,最终代码在这里。

今天听什么歌?

今天听什么?

JavaScript 有变量常量、函数、对象、数组等等概念,那么这些概念又是怎么和界面联系到一起的呢?它和 HTML、CSS 又是如何一起工作的呢?在这一节我们就能知道答案。

提示:这篇文章涉及到很多东西,但你不需要一次性消化所有内容,只需要跟着教程边看边做,有一个整体的了解之后再查看那些扩展链接知识点。

画出界面

首先,让我们先写 HTML、CSS 来画出界面。同样地,今天我们还是继续在 Codepen.io 里面写代码。

第一张专辑卡片

界面中有六张专辑卡片和一个按钮,我们先画出一个专辑卡片。它的结构很简单,就是由一张封面、一个专辑名和一个乐队名组成,所以我们可以写成下面这种结构。

<div class="card">   <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/s27289592.jpg"/>   <h3>相见恨晚</h3>   <p>腰乐队</p> </div>

现在它还没有样式,看起来比较朴素:

今天听什么歌?

单张专辑卡片

现在我们来给它添加样式,不过今天我们不用 CSS 了,我来给大家介绍一个好东西,它叫 Sass——一种 CSS 预处理器。

CSS 本身不支持层级嵌套,所以当你需要给某一个层级比较深的元素添加样式的时候,需要像下图左边这样不断用空格来表达下一层级(在《从最熟悉的地方开始》这一节讲到过)。比如 .card h3 a 表示的是 class 为 card 的元素里面的 <h3> 元素里面的 <a> 元素,这样在我们写一些元素层级很深的界面结构时非常麻烦,所以就有人发明了 CSS 预处理器,它可以让你像下图右边那样写出和 HTML 元素一样嵌套的具有层级的 CSS 样式。同时它还具有一些增强的功能,比如说代码复用、CSS 变量等等,后面我们会慢慢接触到。

今天听什么歌?

CSS-Scss

CSS 预处理器不止 Sass 一种,还有很多其他实现比如 Less、Stylus 等,但是它们的语法大同小异,就不一一介绍了。需要注意的是,你可能注意到了,我开始说的是 Sass,但是上图中 CSS 右边的小括号中显示的是 Scss。其实 .sass.scss 是 Sass 支持的两种文件格式,前者更加极端,直接以缩进来表示层级,连括号都省略了,我们先温和一点,使用 scss

这种写法本身不被浏览器支持(虽然有消息说 CSS 原生嵌套已经提案了),我们需要做一些额外的工作来把它转化为普通的 CSS,不过在这里 Codepen.io 已经帮我们做了。

回到正题,我们写一下专辑卡片的样式。

.card{   width: 160px;   height: 240px;   padding: 12px;   border-radius: 20px;   overflow: hidden;   background: #F7FAFC;   box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);   text-align: center;   img{     width: 100%;     margin-bottom: 16px;     border-radius: 12px;     overflow: hidden;     box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);   }   h3{     margin: 0;   }   p{     margin: 0;     color: #718096;   } }

这些样式,我们从单词的字面意思就可以理解每一行的样式是做什么的。比较陌生的是 overflow: hidden;,它表示裁切形状,也就是超出元素范围的内容不显示。box-shadow 是投影,由四个距离加一个颜色表示,四个距离值分别表示 X 轴方向偏移,Y 轴方向偏移,模糊值以及伸缩值(Spread)。我们可以给一个元素添加多个投影,只需要用逗号隔开就可以了。如下图,右侧 Figma 中的阴影属性设置对应的就是左边亮起来的那一行代码。

今天听什么歌?

阴影

此时我们看到的效果应该如下图所示:

今天听什么歌?

一张卡片

这里插一个题外话,你可以打开浏览器的控制台,通过审查元素选中这个卡片,可以看到它的实际宽高和代码中的不一致。代码中宽度是 160px 而实际是 184px,高度是 240px 而实际是 264px

今天听什么歌?

专辑卡片盒模型

这是因为浏览器会根据指定的 CSS 框盒模型来渲染元素,所谓框盒模型也就是元素的尺寸包含下图的哪些区域的规则(在浏览器审查元素时可以看到和下图一样的颜色区分)。默认的框盒模型是 content-box,也就是我们通过 CSS 设定的元素宽高是指它实际的内容区域,不包含内边距(Padding)、边框(Border)和外边距(Margin)。
在这个专辑卡片中因为设定了内边距(绿色部分)为 12px 所以实际的元素尺寸会在上下左右各增加 12px

今天听什么歌?

Box Model

这可能与我们的第一印象不太一样,一般我们会认为内边距和边框属于元素本身,只有外边距应该排除在外(想一想你在设计工具中是怎样画图的),所以一般我们会指定所有元素的框盒模型为 border-box,代码如下:

// 星号代表所有元素 * {   box-sizing: border-box; }

它的意思是,指定所有元素的框盒模型为 border-box,也就是元素尺寸包含实际内容、内边距、边框,但不包含外边距。

画出它的反面

在一开始的效果图中可以看到,卡片是有正反两面的。用 CSS 我们没法直接给一个元素写出正反两面,所以在这里我们需要单独写正反两面,再使用前面讲过的 3D 变换来实现。也就是如下图这样,分别画出两个面对应的元素,再把反面旋转 180° 放在正面的后面。

今天听什么歌?

卡片的两面

现在,我们改一下卡片的结构,增加一个 .card 容器,把卡片的正反两面放在里面。

<div class="card">   <!--   卡片反面 -->   <div class="card-back">     <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/guitar.png">   </div>   <!--   卡片正面 -->   <div class="card-front">     <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/s27289592.jpg"/>     <h3>相见恨晚</h3>     <p>腰乐队</p>   </div> </div>

正面的样式不变,反面除了和正面一样的宽高、圆角等属性,我们还给它添加了一个渐变的背景 background: linear-gradient(145deg, #ED8936 0%, #CA6511 100%);linear-gradient 表示线性渐变,括号内 145deg 表示渐变角度,后面的两组表示所处位置(百分比)和对应颜色,渐变还有很多种,具体可以参考这里的说明。

除此之外,我们还给反面卡片添加了三个弹性布局属性,它们的作用是让里面的图片水平垂直居中,每个属性解释如下:

  • display: flex;:表示设定其为弹性布局的容器
  • align-items: center;:设定内部元素在水平方线上居中
  • justify-content: center;设定内部元素在垂直线上居中

Flex 弹性布局是一个比较强大但又有一些复杂的布局方式,它有点类似于 Figma 的 Auto Layout,可以让元素在水平或垂直方向上更好地排布,但是更强大。可以阅读这篇文章了解更多,此外,这里还有一个小游戏可以帮助你更好地理解它。

* {   box-sizing: border-box; }  body{   padding: 36px;     color: #1A202C;     background: #CBD5E0; }  .card{   .card-front{     width: 160px;     height: 240px;     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: #F7FAFC;     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);     text-align: center;     img{       width: 100%;       margin-bottom: 16px;       border-radius: 12px;       overflow: hidden;       box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);     }     h3{       margin: 0;     }     p{       margin: 0;       color: #718096;     }   }   .card-back{     display: flex;     align-items: center;     justify-content: center;     width: 160px;     height: 240px;     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: linear-gradient(145.01deg, #ED8936 0%, #CA6511 100%);     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);     transform: rotateY(180deg);     img{       width: 96px;     }   } }

现在,我们分别写出了卡片的两面,也通过 transform: rotateY(180deg); 把反面翻转了 180°,但是卡片的反面并没有隐藏在正面的后面。还记得在前面《从最熟悉的地方开始》我们讲过网页元素的布局是流式的吗?HTML 代码中的元素都会从上往下不断堆积,想让两个元素在位置上重叠我们需要额外的布局方式。

今天听什么歌?

卡片的两面

使用绝对定位

让它俩重叠在一起的秘密就是「绝对定位」,所谓绝对定位就是让元素脱离文档流,通过你指定的位置来给它定位。我们可以给元素添加 positiontopleft 属性来设置元素的绝对定位。现在给卡片反面 .card-back 添加下面三行代码:

// ……   .card-back{     position: absolute;     top: 150px;     left: 150px;     // 其它代码     // ……   } // ……

第一行 position: absolute; 意思是设置这个元素为绝对定位,后两行是设定它的偏移坐标,在这里这个偏移是相对整个网页的 body 元素定位的。我们使用的是相对于左上角偏移,你还可以使用 bottomright 来相对于右下角定位。此时,卡片的效果如下:

今天听什么歌?

绝对定位

可以看到,反面元素脱离了文档流,正面元素向上占据了它的位置。反面元素脱离了文档流之后,根据我们的代码会相对于 body 左上角定位,距离顶部和左边都是 150px。因为右边的实时预览窗口是一个嵌入的网页,所以它的 body 元素其实是蓝色框的部分,并不是整个浏览器窗口。绝对定位元素并不总是相对于 body 元素偏移,而是相对于最近的 position: static; 祖先元素的。position: static; 是指文档流中正常的元素,只要你不给它设定其它定位方式,就都是 static 定位,可以参考这里查看其它定位方式。

现在,我们给正反面元素都添加绝对定位,让它们重叠在一起。正反面元素的宽高一致,位置一致,圆角也一致,所以我们可以把它们的公共样式提取出来。我们通过下面的代码给正反面元素设置一样的样式:

.card-front, .card-back{   position: absolute;   top: 0;   left: 0;   width: 160px;   height: 240px;   padding: 12px;   border-radius: 20px;   overflow: hidden;   background: #F7FAFC;   box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1); }

然后再设置父级元素 .card 的定位方式为 position: relative; 也就是相对定位。相对定位的意思是,元素会相对自己原来的位置进行偏移,但不会脱离文档流。由于我们并没有设置它的 topleft 等属性,所以它其实不会偏移。那么我们为什么要给它设置相对定位呢?还记得上面说的绝对定位元素会相对于最近的非 Static 祖先定位吗?没错,现在 .card 是正反面元素最近的非 static 祖先了,.card-front.card-back 就会相对于它进行绝对定位了。因为我们设定的正反面元素的 topleft 属性都是 0,所以它俩重叠并且和容器 .card 也重叠。使用 position: relative; 的父容器来让 position: absolute; 的子元素定位是一种很常用的手段,在写代码布局时经常会用到。

我们再优化一下代码(下面注释部分),现在的代码看起来像这样:

.card{   position: relative;   width: 160px; // 给父元素设定宽度   height: 240px; // 给父元素设定高度   text-align: center;   transform-style: preserve-3d; // 设定变换在 3D 空间   transition: transform 0.6s; // 增加过渡效果   &:hover{     transform: rotateY(-180deg); // 鼠标悬浮在上方时旋转 180°,也就是翻转   }   .card-front,   .card-back{     position: absolute;     top: 0;     left: 0;     width: 100%; // 设定子元素和父元素一样的宽度     height: 100%; // 设定子元素和父元素一样的宽度     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: #F7FAFC;     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);   }   .card-front{     img{       width: 100%;       margin-bottom: 16px;       border-radius: 12px;       overflow: hidden;       box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);     }     h3{       margin: 0;     }     p{       margin: 0;       color: #718096;     }   }   .card-back{     display: flex;     align-items: center;     justify-content: center;     transform: rotateY(180deg);     background: linear-gradient(145.01deg, #ED8936 0%, #CA6511 100%);     img{       width: 96px;     }   } }

可以看到我们给它添加了过渡动效的代码,现在鼠标移动到卡片上方就可以看到整个卡片翻转的效果了。

今天听什么歌?

错误的翻转效果

等等,这闪烁的效果并不是我们想要的啊,为什么有时候可以同时看到卡片的两面呢?这是因为,CSS 里的 3D 变换默认可以看到元素的背面,也就是说当元素翻转之后背对着我们还是可以看到它的正面图像,只不过会镜像变换一下。想要翻转后看不到它的反面,只需要加一行代码就可以了。

.card-front, .card-back{   // 其它代码……   backface-visibility: hidden; }

现在看起来舒服多了。

今天听什么歌?

正确的翻转效果

画出剩下 5 张卡片

不容易啊,到现在为止我们终于画完了第一张可以翻转的卡片,现在让我们一起来画剩下的 5 张卡片吧。首先我们在最外层添加一个 div 容器,给它一个 cards 类。像下面这样:

<!-- 新添加的最外层容器 --> <div class="cards">   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div> </div>

这里有一个小技巧,当你需要让一大段代码向后缩进时,可以选中它并按下 Tab 键,就像下面这样:

今天听什么歌?

代码缩进

当然也可以反向操作,按下 Shift 和 Tab 键代码段就会向前一个缩进。

现在所有卡片都到齐了,我们分别替换一下图片的 src 和专辑名乐队名,但是现在它们是从上至下排列的。因为每一个卡片都是 block 元素(块级元素),所以它们每个都会占领一行(即使宽度并没有占满一行),一直往下面堆叠,这符合我们前面所说的流式布局。

今天听什么歌?

向下堆叠的卡片

现在我们一起来使用另一种布局方式,让这 6 张卡片按照两行三列排布。

使用 Grid 布局

前面说的 Flex 布局可以帮助你在水平方向或垂直方向上排布元素,Grid (栅格)布局则可以帮助你在这两个方向上排布元素,也就是说 Flex 是线上的而 Grid 是面上的。

首先我们给最外层的容器加上 display: grid;,这样它里面的子元素就可以按照 Grid 布局了。但是这时候里面的卡片还是和之前一样,这是因为我们还没有告诉它布局的规则。

最简单的两个 Grid 规则是行和列,比如这里,我们想要的效果是两行三列,如果没有间隙的话就是每行 240px,每列 160px,那么只需要像这样写就可以了:

.cards{   display: grid;   grid-template-rows: 240px 240px; // 两行,每行高度 240px   grid-template-columns: 160px 160px 160px; // 三列,每列宽度 160px   // …… }

grid-template-rows 描述的是行的排布规则,grid-template-columns 描述的是列的排布规则,这里我们用的是最直接的方式——直接设定它们的宽高,其实还可以用其它写法。现在的效果如下:

今天听什么歌?

Grid 布局

这样太挤啦!我们需要一些呼吸的空间。我们把每行的高度改为 260px,每一列的宽度不再使用 px 单位了,我们用弹性系数 fr(flex factor)。fr 的意思是,根据对应的数字分配比例,比如 grid-template-columns: 1fr 1fr 1fr 的意思是,子元素分为三列,每列宽度占总宽度的三分之一。

在上一节我们一起学习了 JavaScript,涉及的东西比较多,可能你会感觉到有点难也有点枯燥。这是很正常的,不需要为此担心。这一节我们一起来做一个好玩的东西,一个随机选择今天要听的歌的小页面,最终代码在这里。

今天听什么歌?

今天听什么?

JavaScript 有变量常量、函数、对象、数组等等概念,那么这些概念又是怎么和界面联系到一起的呢?它和 HTML、CSS 又是如何一起工作的呢?在这一节我们就能知道答案。

提示:这篇文章涉及到很多东西,但你不需要一次性消化所有内容,只需要跟着教程边看边做,有一个整体的了解之后再查看那些扩展链接知识点。

画出界面

首先,让我们先写 HTML、CSS 来画出界面。同样地,今天我们还是继续在 Codepen.io 里面写代码。

第一张专辑卡片

界面中有六张专辑卡片和一个按钮,我们先画出一个专辑卡片。它的结构很简单,就是由一张封面、一个专辑名和一个乐队名组成,所以我们可以写成下面这种结构。

<div class="card">   <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/s27289592.jpg"/>   <h3>相见恨晚</h3>   <p>腰乐队</p> </div>

现在它还没有样式,看起来比较朴素:

今天听什么歌?

单张专辑卡片

现在我们来给它添加样式,不过今天我们不用 CSS 了,我来给大家介绍一个好东西,它叫 Sass——一种 CSS 预处理器。

CSS 本身不支持层级嵌套,所以当你需要给某一个层级比较深的元素添加样式的时候,需要像下图左边这样不断用空格来表达下一层级(在《从最熟悉的地方开始》这一节讲到过)。比如 .card h3 a 表示的是 class 为 card 的元素里面的 <h3> 元素里面的 <a> 元素,这样在我们写一些元素层级很深的界面结构时非常麻烦,所以就有人发明了 CSS 预处理器,它可以让你像下图右边那样写出和 HTML 元素一样嵌套的具有层级的 CSS 样式。同时它还具有一些增强的功能,比如说代码复用、CSS 变量等等,后面我们会慢慢接触到。

今天听什么歌?

CSS-Scss

CSS 预处理器不止 Sass 一种,还有很多其他实现比如 Less、Stylus 等,但是它们的语法大同小异,就不一一介绍了。需要注意的是,你可能注意到了,我开始说的是 Sass,但是上图中 CSS 右边的小括号中显示的是 Scss。其实 .sass.scss 是 Sass 支持的两种文件格式,前者更加极端,直接以缩进来表示层级,连括号都省略了,我们先温和一点,使用 scss

这种写法本身不被浏览器支持(虽然有消息说 CSS 原生嵌套已经提案了),我们需要做一些额外的工作来把它转化为普通的 CSS,不过在这里 Codepen.io 已经帮我们做了。

回到正题,我们写一下专辑卡片的样式。

.card{   width: 160px;   height: 240px;   padding: 12px;   border-radius: 20px;   overflow: hidden;   background: #F7FAFC;   box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);   text-align: center;   img{     width: 100%;     margin-bottom: 16px;     border-radius: 12px;     overflow: hidden;     box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);   }   h3{     margin: 0;   }   p{     margin: 0;     color: #718096;   } }

这些样式,我们从单词的字面意思就可以理解每一行的样式是做什么的。比较陌生的是 overflow: hidden;,它表示裁切形状,也就是超出元素范围的内容不显示。box-shadow 是投影,由四个距离加一个颜色表示,四个距离值分别表示 X 轴方向偏移,Y 轴方向偏移,模糊值以及伸缩值(Spread)。我们可以给一个元素添加多个投影,只需要用逗号隔开就可以了。如下图,右侧 Figma 中的阴影属性设置对应的就是左边亮起来的那一行代码。

今天听什么歌?

阴影

此时我们看到的效果应该如下图所示:

今天听什么歌?

一张卡片

这里插一个题外话,你可以打开浏览器的控制台,通过审查元素选中这个卡片,可以看到它的实际宽高和代码中的不一致。代码中宽度是 160px 而实际是 184px,高度是 240px 而实际是 264px

今天听什么歌?

专辑卡片盒模型

这是因为浏览器会根据指定的 CSS 框盒模型来渲染元素,所谓框盒模型也就是元素的尺寸包含下图的哪些区域的规则(在浏览器审查元素时可以看到和下图一样的颜色区分)。默认的框盒模型是 content-box,也就是我们通过 CSS 设定的元素宽高是指它实际的内容区域,不包含内边距(Padding)、边框(Border)和外边距(Margin)。
在这个专辑卡片中因为设定了内边距(绿色部分)为 12px 所以实际的元素尺寸会在上下左右各增加 12px

今天听什么歌?

Box Model

这可能与我们的第一印象不太一样,一般我们会认为内边距和边框属于元素本身,只有外边距应该排除在外(想一想你在设计工具中是怎样画图的),所以一般我们会指定所有元素的框盒模型为 border-box,代码如下:

// 星号代表所有元素 * {   box-sizing: border-box; }

它的意思是,指定所有元素的框盒模型为 border-box,也就是元素尺寸包含实际内容、内边距、边框,但不包含外边距。

画出它的反面

在一开始的效果图中可以看到,卡片是有正反两面的。用 CSS 我们没法直接给一个元素写出正反两面,所以在这里我们需要单独写正反两面,再使用前面讲过的 3D 变换来实现。也就是如下图这样,分别画出两个面对应的元素,再把反面旋转 180° 放在正面的后面。

今天听什么歌?

卡片的两面

现在,我们改一下卡片的结构,增加一个 .card 容器,把卡片的正反两面放在里面。

<div class="card">   <!--   卡片反面 -->   <div class="card-back">     <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/guitar.png">   </div>   <!--   卡片正面 -->   <div class="card-front">     <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/s27289592.jpg"/>     <h3>相见恨晚</h3>     <p>腰乐队</p>   </div> </div>

正面的样式不变,反面除了和正面一样的宽高、圆角等属性,我们还给它添加了一个渐变的背景 background: linear-gradient(145deg, #ED8936 0%, #CA6511 100%);linear-gradient 表示线性渐变,括号内 145deg 表示渐变角度,后面的两组表示所处位置(百分比)和对应颜色,渐变还有很多种,具体可以参考这里的说明。

除此之外,我们还给反面卡片添加了三个弹性布局属性,它们的作用是让里面的图片水平垂直居中,每个属性解释如下:

  • display: flex;:表示设定其为弹性布局的容器
  • align-items: center;:设定内部元素在水平方线上居中
  • justify-content: center;设定内部元素在垂直线上居中

Flex 弹性布局是一个比较强大但又有一些复杂的布局方式,它有点类似于 Figma 的 Auto Layout,可以让元素在水平或垂直方向上更好地排布,但是更强大。可以阅读这篇文章了解更多,此外,这里还有一个小游戏可以帮助你更好地理解它。

* {   box-sizing: border-box; }  body{   padding: 36px;     color: #1A202C;     background: #CBD5E0; }  .card{   .card-front{     width: 160px;     height: 240px;     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: #F7FAFC;     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);     text-align: center;     img{       width: 100%;       margin-bottom: 16px;       border-radius: 12px;       overflow: hidden;       box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);     }     h3{       margin: 0;     }     p{       margin: 0;       color: #718096;     }   }   .card-back{     display: flex;     align-items: center;     justify-content: center;     width: 160px;     height: 240px;     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: linear-gradient(145.01deg, #ED8936 0%, #CA6511 100%);     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);     transform: rotateY(180deg);     img{       width: 96px;     }   } }

现在,我们分别写出了卡片的两面,也通过 transform: rotateY(180deg); 把反面翻转了 180°,但是卡片的反面并没有隐藏在正面的后面。还记得在前面《从最熟悉的地方开始》我们讲过网页元素的布局是流式的吗?HTML 代码中的元素都会从上往下不断堆积,想让两个元素在位置上重叠我们需要额外的布局方式。

今天听什么歌?

卡片的两面

使用绝对定位

让它俩重叠在一起的秘密就是「绝对定位」,所谓绝对定位就是让元素脱离文档流,通过你指定的位置来给它定位。我们可以给元素添加 positiontopleft 属性来设置元素的绝对定位。现在给卡片反面 .card-back 添加下面三行代码:

// ……   .card-back{     position: absolute;     top: 150px;     left: 150px;     // 其它代码     // ……   } // ……

第一行 position: absolute; 意思是设置这个元素为绝对定位,后两行是设定它的偏移坐标,在这里这个偏移是相对整个网页的 body 元素定位的。我们使用的是相对于左上角偏移,你还可以使用 bottomright 来相对于右下角定位。此时,卡片的效果如下:

今天听什么歌?

绝对定位

可以看到,反面元素脱离了文档流,正面元素向上占据了它的位置。反面元素脱离了文档流之后,根据我们的代码会相对于 body 左上角定位,距离顶部和左边都是 150px。因为右边的实时预览窗口是一个嵌入的网页,所以它的 body 元素其实是蓝色框的部分,并不是整个浏览器窗口。绝对定位元素并不总是相对于 body 元素偏移,而是相对于最近的 position: static; 祖先元素的。position: static; 是指文档流中正常的元素,只要你不给它设定其它定位方式,就都是 static 定位,可以参考这里查看其它定位方式。

现在,我们给正反面元素都添加绝对定位,让它们重叠在一起。正反面元素的宽高一致,位置一致,圆角也一致,所以我们可以把它们的公共样式提取出来。我们通过下面的代码给正反面元素设置一样的样式:

.card-front, .card-back{   position: absolute;   top: 0;   left: 0;   width: 160px;   height: 240px;   padding: 12px;   border-radius: 20px;   overflow: hidden;   background: #F7FAFC;   box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1); }

然后再设置父级元素 .card 的定位方式为 position: relative; 也就是相对定位。相对定位的意思是,元素会相对自己原来的位置进行偏移,但不会脱离文档流。由于我们并没有设置它的 topleft 等属性,所以它其实不会偏移。那么我们为什么要给它设置相对定位呢?还记得上面说的绝对定位元素会相对于最近的非 Static 祖先定位吗?没错,现在 .card 是正反面元素最近的非 static 祖先了,.card-front.card-back 就会相对于它进行绝对定位了。因为我们设定的正反面元素的 topleft 属性都是 0,所以它俩重叠并且和容器 .card 也重叠。使用 position: relative; 的父容器来让 position: absolute; 的子元素定位是一种很常用的手段,在写代码布局时经常会用到。

我们再优化一下代码(下面注释部分),现在的代码看起来像这样:

.card{   position: relative;   width: 160px; // 给父元素设定宽度   height: 240px; // 给父元素设定高度   text-align: center;   transform-style: preserve-3d; // 设定变换在 3D 空间   transition: transform 0.6s; // 增加过渡效果   &:hover{     transform: rotateY(-180deg); // 鼠标悬浮在上方时旋转 180°,也就是翻转   }   .card-front,   .card-back{     position: absolute;     top: 0;     left: 0;     width: 100%; // 设定子元素和父元素一样的宽度     height: 100%; // 设定子元素和父元素一样的宽度     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: #F7FAFC;     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);   }   .card-front{     img{       width: 100%;       margin-bottom: 16px;       border-radius: 12px;       overflow: hidden;       box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);     }     h3{       margin: 0;     }     p{       margin: 0;       color: #718096;     }   }   .card-back{     display: flex;     align-items: center;     justify-content: center;     transform: rotateY(180deg);     background: linear-gradient(145.01deg, #ED8936 0%, #CA6511 100%);     img{       width: 96px;     }   } }

可以看到我们给它添加了过渡动效的代码,现在鼠标移动到卡片上方就可以看到整个卡片翻转的效果了。

今天听什么歌?

错误的翻转效果

等等,这闪烁的效果并不是我们想要的啊,为什么有时候可以同时看到卡片的两面呢?这是因为,CSS 里的 3D 变换默认可以看到元素的背面,也就是说当元素翻转之后背对着我们还是可以看到它的正面图像,只不过会镜像变换一下。想要翻转后看不到它的反面,只需要加一行代码就可以了。

.card-front, .card-back{   // 其它代码……   backface-visibility: hidden; }

现在看起来舒服多了。

今天听什么歌?

正确的翻转效果

画出剩下 5 张卡片

不容易啊,到现在为止我们终于画完了第一张可以翻转的卡片,现在让我们一起来画剩下的 5 张卡片吧。首先我们在最外层添加一个 div 容器,给它一个 cards 类。像下面这样:

<!-- 新添加的最外层容器 --> <div class="cards">   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div> </div>

这里有一个小技巧,当你需要让一大段代码向后缩进时,可以选中它并按下 Tab 键,就像下面这样:

今天听什么歌?

代码缩进

当然也可以反向操作,按下 Shift 和 Tab 键代码段就会向前一个缩进。

现在所有卡片都到齐了,我们分别替换一下图片的 src 和专辑名乐队名,但是现在它们是从上至下排列的。因为每一个卡片都是 block 元素(块级元素),所以它们每个都会占领一行(即使宽度并没有占满一行),一直往下面堆叠,这符合我们前面所说的流式布局。

今天听什么歌?

向下堆叠的卡片

现在我们一起来使用另一种布局方式,让这 6 张卡片按照两行三列排布。

使用 Grid 布局

前面说的 Flex 布局可以帮助你在水平方向或垂直方向上排布元素,Grid (栅格)布局则可以帮助你在这两个方向上排布元素,也就是说 Flex 是线上的而 Grid 是面上的。

首先我们给最外层的容器加上 display: grid;,这样它里面的子元素就可以按照 Grid 布局了。但是这时候里面的卡片还是和之前一样,这是因为我们还没有告诉它布局的规则。

最简单的两个 Grid 规则是行和列,比如这里,我们想要的效果是两行三列,如果没有间隙的话就是每行 240px,每列 160px,那么只需要像这样写就可以了:

.cards{   display: grid;   grid-template-rows: 240px 240px; // 两行,每行高度 240px   grid-template-columns: 160px 160px 160px; // 三列,每列宽度 160px   // …… }

grid-template-rows 描述的是行的排布规则,grid-template-columns 描述的是列的排布规则,这里我们用的是最直接的方式——直接设定它们的宽高,其实还可以用其它写法。现在的效果如下:

今天听什么歌?

Grid 布局

这样太挤啦!我们需要一些呼吸的空间。我们把每行的高度改为 260px,每一列的宽度不再使用 px 单位了,我们用弹性系数 fr(flex factor)。fr 的意思是,根据对应的数字分配比例,比如 grid-template-columns: 1fr 1fr 1fr 的意思是,子元素分为三列,每列宽度占总宽度的三分之一。

在上一节我们一起学习了 JavaScript,涉及的东西比较多,可能你会感觉到有点难也有点枯燥。这是很正常的,不需要为此担心。这一节我们一起来做一个好玩的东西,一个随机选择今天要听的歌的小页面,最终代码在这里。

今天听什么歌?

今天听什么?

JavaScript 有变量常量、函数、对象、数组等等概念,那么这些概念又是怎么和界面联系到一起的呢?它和 HTML、CSS 又是如何一起工作的呢?在这一节我们就能知道答案。

提示:这篇文章涉及到很多东西,但你不需要一次性消化所有内容,只需要跟着教程边看边做,有一个整体的了解之后再查看那些扩展链接知识点。

画出界面

首先,让我们先写 HTML、CSS 来画出界面。同样地,今天我们还是继续在 Codepen.io 里面写代码。

第一张专辑卡片

界面中有六张专辑卡片和一个按钮,我们先画出一个专辑卡片。它的结构很简单,就是由一张封面、一个专辑名和一个乐队名组成,所以我们可以写成下面这种结构。

<div class="card">   <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/s27289592.jpg"/>   <h3>相见恨晚</h3>   <p>腰乐队</p> </div>

现在它还没有样式,看起来比较朴素:

今天听什么歌?

单张专辑卡片

现在我们来给它添加样式,不过今天我们不用 CSS 了,我来给大家介绍一个好东西,它叫 Sass——一种 CSS 预处理器。

CSS 本身不支持层级嵌套,所以当你需要给某一个层级比较深的元素添加样式的时候,需要像下图左边这样不断用空格来表达下一层级(在《从最熟悉的地方开始》这一节讲到过)。比如 .card h3 a 表示的是 class 为 card 的元素里面的 <h3> 元素里面的 <a> 元素,这样在我们写一些元素层级很深的界面结构时非常麻烦,所以就有人发明了 CSS 预处理器,它可以让你像下图右边那样写出和 HTML 元素一样嵌套的具有层级的 CSS 样式。同时它还具有一些增强的功能,比如说代码复用、CSS 变量等等,后面我们会慢慢接触到。

今天听什么歌?

CSS-Scss

CSS 预处理器不止 Sass 一种,还有很多其他实现比如 Less、Stylus 等,但是它们的语法大同小异,就不一一介绍了。需要注意的是,你可能注意到了,我开始说的是 Sass,但是上图中 CSS 右边的小括号中显示的是 Scss。其实 .sass.scss 是 Sass 支持的两种文件格式,前者更加极端,直接以缩进来表示层级,连括号都省略了,我们先温和一点,使用 scss

这种写法本身不被浏览器支持(虽然有消息说 CSS 原生嵌套已经提案了),我们需要做一些额外的工作来把它转化为普通的 CSS,不过在这里 Codepen.io 已经帮我们做了。

回到正题,我们写一下专辑卡片的样式。

.card{   width: 160px;   height: 240px;   padding: 12px;   border-radius: 20px;   overflow: hidden;   background: #F7FAFC;   box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);   text-align: center;   img{     width: 100%;     margin-bottom: 16px;     border-radius: 12px;     overflow: hidden;     box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);   }   h3{     margin: 0;   }   p{     margin: 0;     color: #718096;   } }

这些样式,我们从单词的字面意思就可以理解每一行的样式是做什么的。比较陌生的是 overflow: hidden;,它表示裁切形状,也就是超出元素范围的内容不显示。box-shadow 是投影,由四个距离加一个颜色表示,四个距离值分别表示 X 轴方向偏移,Y 轴方向偏移,模糊值以及伸缩值(Spread)。我们可以给一个元素添加多个投影,只需要用逗号隔开就可以了。如下图,右侧 Figma 中的阴影属性设置对应的就是左边亮起来的那一行代码。

今天听什么歌?

阴影

此时我们看到的效果应该如下图所示:

今天听什么歌?

一张卡片

这里插一个题外话,你可以打开浏览器的控制台,通过审查元素选中这个卡片,可以看到它的实际宽高和代码中的不一致。代码中宽度是 160px 而实际是 184px,高度是 240px 而实际是 264px

今天听什么歌?

专辑卡片盒模型

这是因为浏览器会根据指定的 CSS 框盒模型来渲染元素,所谓框盒模型也就是元素的尺寸包含下图的哪些区域的规则(在浏览器审查元素时可以看到和下图一样的颜色区分)。默认的框盒模型是 content-box,也就是我们通过 CSS 设定的元素宽高是指它实际的内容区域,不包含内边距(Padding)、边框(Border)和外边距(Margin)。
在这个专辑卡片中因为设定了内边距(绿色部分)为 12px 所以实际的元素尺寸会在上下左右各增加 12px

今天听什么歌?

Box Model

这可能与我们的第一印象不太一样,一般我们会认为内边距和边框属于元素本身,只有外边距应该排除在外(想一想你在设计工具中是怎样画图的),所以一般我们会指定所有元素的框盒模型为 border-box,代码如下:

// 星号代表所有元素 * {   box-sizing: border-box; }

它的意思是,指定所有元素的框盒模型为 border-box,也就是元素尺寸包含实际内容、内边距、边框,但不包含外边距。

画出它的反面

在一开始的效果图中可以看到,卡片是有正反两面的。用 CSS 我们没法直接给一个元素写出正反两面,所以在这里我们需要单独写正反两面,再使用前面讲过的 3D 变换来实现。也就是如下图这样,分别画出两个面对应的元素,再把反面旋转 180° 放在正面的后面。

今天听什么歌?

卡片的两面

现在,我们改一下卡片的结构,增加一个 .card 容器,把卡片的正反两面放在里面。

<div class="card">   <!--   卡片反面 -->   <div class="card-back">     <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/guitar.png">   </div>   <!--   卡片正面 -->   <div class="card-front">     <img src="https://dock-1255718578.cos.ap-chengdu.myqcloud.com/codesigner/what-to-listen-today/s27289592.jpg"/>     <h3>相见恨晚</h3>     <p>腰乐队</p>   </div> </div>

正面的样式不变,反面除了和正面一样的宽高、圆角等属性,我们还给它添加了一个渐变的背景 background: linear-gradient(145deg, #ED8936 0%, #CA6511 100%);linear-gradient 表示线性渐变,括号内 145deg 表示渐变角度,后面的两组表示所处位置(百分比)和对应颜色,渐变还有很多种,具体可以参考这里的说明。

除此之外,我们还给反面卡片添加了三个弹性布局属性,它们的作用是让里面的图片水平垂直居中,每个属性解释如下:

  • display: flex;:表示设定其为弹性布局的容器
  • align-items: center;:设定内部元素在水平方线上居中
  • justify-content: center;设定内部元素在垂直线上居中

Flex 弹性布局是一个比较强大但又有一些复杂的布局方式,它有点类似于 Figma 的 Auto Layout,可以让元素在水平或垂直方向上更好地排布,但是更强大。可以阅读这篇文章了解更多,此外,这里还有一个小游戏可以帮助你更好地理解它。

* {   box-sizing: border-box; }  body{   padding: 36px;     color: #1A202C;     background: #CBD5E0; }  .card{   .card-front{     width: 160px;     height: 240px;     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: #F7FAFC;     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);     text-align: center;     img{       width: 100%;       margin-bottom: 16px;       border-radius: 12px;       overflow: hidden;       box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);     }     h3{       margin: 0;     }     p{       margin: 0;       color: #718096;     }   }   .card-back{     display: flex;     align-items: center;     justify-content: center;     width: 160px;     height: 240px;     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: linear-gradient(145.01deg, #ED8936 0%, #CA6511 100%);     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);     transform: rotateY(180deg);     img{       width: 96px;     }   } }

现在,我们分别写出了卡片的两面,也通过 transform: rotateY(180deg); 把反面翻转了 180°,但是卡片的反面并没有隐藏在正面的后面。还记得在前面《从最熟悉的地方开始》我们讲过网页元素的布局是流式的吗?HTML 代码中的元素都会从上往下不断堆积,想让两个元素在位置上重叠我们需要额外的布局方式。

今天听什么歌?

卡片的两面

使用绝对定位

让它俩重叠在一起的秘密就是「绝对定位」,所谓绝对定位就是让元素脱离文档流,通过你指定的位置来给它定位。我们可以给元素添加 positiontopleft 属性来设置元素的绝对定位。现在给卡片反面 .card-back 添加下面三行代码:

// ……   .card-back{     position: absolute;     top: 150px;     left: 150px;     // 其它代码     // ……   } // ……

第一行 position: absolute; 意思是设置这个元素为绝对定位,后两行是设定它的偏移坐标,在这里这个偏移是相对整个网页的 body 元素定位的。我们使用的是相对于左上角偏移,你还可以使用 bottomright 来相对于右下角定位。此时,卡片的效果如下:

今天听什么歌?

绝对定位

可以看到,反面元素脱离了文档流,正面元素向上占据了它的位置。反面元素脱离了文档流之后,根据我们的代码会相对于 body 左上角定位,距离顶部和左边都是 150px。因为右边的实时预览窗口是一个嵌入的网页,所以它的 body 元素其实是蓝色框的部分,并不是整个浏览器窗口。绝对定位元素并不总是相对于 body 元素偏移,而是相对于最近的 position: static; 祖先元素的。position: static; 是指文档流中正常的元素,只要你不给它设定其它定位方式,就都是 static 定位,可以参考这里查看其它定位方式。

现在,我们给正反面元素都添加绝对定位,让它们重叠在一起。正反面元素的宽高一致,位置一致,圆角也一致,所以我们可以把它们的公共样式提取出来。我们通过下面的代码给正反面元素设置一样的样式:

.card-front, .card-back{   position: absolute;   top: 0;   left: 0;   width: 160px;   height: 240px;   padding: 12px;   border-radius: 20px;   overflow: hidden;   background: #F7FAFC;   box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1); }

然后再设置父级元素 .card 的定位方式为 position: relative; 也就是相对定位。相对定位的意思是,元素会相对自己原来的位置进行偏移,但不会脱离文档流。由于我们并没有设置它的 topleft 等属性,所以它其实不会偏移。那么我们为什么要给它设置相对定位呢?还记得上面说的绝对定位元素会相对于最近的非 Static 祖先定位吗?没错,现在 .card 是正反面元素最近的非 static 祖先了,.card-front.card-back 就会相对于它进行绝对定位了。因为我们设定的正反面元素的 topleft 属性都是 0,所以它俩重叠并且和容器 .card 也重叠。使用 position: relative; 的父容器来让 position: absolute; 的子元素定位是一种很常用的手段,在写代码布局时经常会用到。

我们再优化一下代码(下面注释部分),现在的代码看起来像这样:

.card{   position: relative;   width: 160px; // 给父元素设定宽度   height: 240px; // 给父元素设定高度   text-align: center;   transform-style: preserve-3d; // 设定变换在 3D 空间   transition: transform 0.6s; // 增加过渡效果   &:hover{     transform: rotateY(-180deg); // 鼠标悬浮在上方时旋转 180°,也就是翻转   }   .card-front,   .card-back{     position: absolute;     top: 0;     left: 0;     width: 100%; // 设定子元素和父元素一样的宽度     height: 100%; // 设定子元素和父元素一样的宽度     padding: 12px;     border-radius: 20px;     overflow: hidden;     background: #F7FAFC;     box-shadow: 0 2px 16px -1px rgba(0, 0, 0, 0.1);   }   .card-front{     img{       width: 100%;       margin-bottom: 16px;       border-radius: 12px;       overflow: hidden;       box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);     }     h3{       margin: 0;     }     p{       margin: 0;       color: #718096;     }   }   .card-back{     display: flex;     align-items: center;     justify-content: center;     transform: rotateY(180deg);     background: linear-gradient(145.01deg, #ED8936 0%, #CA6511 100%);     img{       width: 96px;     }   } }

可以看到我们给它添加了过渡动效的代码,现在鼠标移动到卡片上方就可以看到整个卡片翻转的效果了。

今天听什么歌?

错误的翻转效果

等等,这闪烁的效果并不是我们想要的啊,为什么有时候可以同时看到卡片的两面呢?这是因为,CSS 里的 3D 变换默认可以看到元素的背面,也就是说当元素翻转之后背对着我们还是可以看到它的正面图像,只不过会镜像变换一下。想要翻转后看不到它的反面,只需要加一行代码就可以了。

.card-front, .card-back{   // 其它代码……   backface-visibility: hidden; }

现在看起来舒服多了。

今天听什么歌?

正确的翻转效果

画出剩下 5 张卡片

不容易啊,到现在为止我们终于画完了第一张可以翻转的卡片,现在让我们一起来画剩下的 5 张卡片吧。首先我们在最外层添加一个 div 容器,给它一个 cards 类。像下面这样:

<!-- 新添加的最外层容器 --> <div class="cards">   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div>   <div class="card">     <!-- 卡片内部代码,略 -->   </div> </div>

这里有一个小技巧,当你需要让一大段代码向后缩进时,可以选中它并按下 Tab 键,就像下面这样:

今天听什么歌?

代码缩进

当然也可以反向操作,按下 Shift 和 Tab 键代码段就会向前一个缩进。

现在所有卡片都到齐了,我们分别替换一下图片的 src 和专辑名乐队名,但是现在它们是从上至下排列的。因为每一个卡片都是 block 元素(块级元素),所以它们每个都会占领一行(即使宽度并没有占满一行),一直往下面堆叠,这符合我们前面所说的流式布局。

今天听什么歌?

向下堆叠的卡片

现在我们一起来使用另一种布局方式,让这 6 张卡片按照两行三列排布。

使用 Grid 布局

前面说的 Flex 布局可以帮助你在水平方向或垂直方向上排布元素,Grid (栅格)布局则可以帮助你在这两个方向上排布元素,也就是说 Flex 是线上的而 Grid 是面上的。

首先我们给最外层的容器加上 display: grid;,这样它里面的子元素就可以按照 Grid 布局了。但是这时候里面的卡片还是和之前一样,这是因为我们还没有告诉它布局的规则。

最简单的两个 Grid 规则是行和列,比如这里,我们想要的效果是两行三列,如果没有间隙的话就是每行 240px,每列 160px,那么只需要像这样写就可以了:

.cards{   display: grid;   grid-template-rows: 240px 240px; // 两行,每行高度 240px   grid-template-columns: 160px 160px 160px; // 三列,每列宽度 160px   // …… }

grid-template-rows 描述的是行的排布规则,grid-template-columns 描述的是列的排布规则,这里我们用的是最直接的方式——直接设定它们的宽高,其实还可以用其它写法。现在的效果如下:

今天听什么歌?

Grid 布局

这样太挤啦!我们需要一些呼吸的空间。我们把每行的高度改为 260px,每一列的宽度不再使用 px 单位了,我们用弹性系数 fr(flex factor)。fr 的意思是,根据对应的数字分配比例,比如 grid-template-columns: 1fr 1fr 1fr 的意思是,子元素分为三列,每列宽度占总宽度的三分之一。

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » 今天听什么歌?求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们