CSS3-专家级编程-全-
CSS3 专家级编程(全)
原文:
zh.annas-archive.org/md5/2789AE2FE8CABD493B142B2A68E84610译者:飞龙
前言
CSS 通常被认为是一种简单的语言。实际上,尽管它是声明性的并且表面上看起来简单,但它很难维护。对于不断增长的大规模网络应用程序,可维护性至关重要。本书介绍了利用已知的技巧和黑客、新的 CSS 3 模块技术、预处理器和其他工具来创建真正高质量的产品的方法。这将包括如处理浮动和基于组件的 CSS 等技术的示例。
本书涵盖的内容
第一章,“基础和工具”,介绍了可以帮助您构建更好的 CSS 代码的工具。它描述了预处理器的特性,然后提供了关于 SASS 的基础知识。在这一章中,您将获得有关使用 GULP.js 在前端开发中自动化可重复流程的基础知识。您还将找到一个文件结构的示例,您可以使用它将项目分成小文件,易于编辑和维护。
第二章,“基础的掌握”,帮助您掌握框模型、浮动 CSS、定位故障排除和显示类型。在本章之后,您将更加了解 HTML 和 CSS 的基础知识。
第三章,“伪类和伪元素的掌握”,描述了伪类和伪元素以及如何使用它们。它将涵盖绘制基本图形的问题以及如何将其作为优化 CSS 代码的一部分使用。
第四章,“响应式网站-为特定设备准备您的代码”,提供了关于 RWD 以及如何准备项目的知识。它将涵盖现代网站的问题和优化技术。
第五章,“在 CSS 中使用背景图片”,解决了几乎每个网页上都有图片的事实。本章将教您如何在现代设备的广泛范围上正确显示图片,包括手机和平板电脑。
第六章,“样式化表单”,教您如何样式化表单以及您可以使用哪些 CSS 元素和不能使用哪些 CSS 元素。
第七章,“解决经典问题”,是关于解决 CSS 中经典问题的故障排除:处理不透明度、变换和居中元素。
第八章,“Flexbox 变换的使用”,教您有关 CSS 的新特性以及在哪里使用它们。
第九章,“Calc、渐变和阴影”,将提供有关在 CSS 中进行数学运算的 calc 函数的信息。本章将揭示渐变函数以及您如何在 HTML 布局中使用它们。在本章中,您还将获得有关 CSS 阴影及其用法的基础知识。在本章之后,您将知道如何向框和文本添加阴影。
第十章,“不要重复自己-让我们创建一个简单的 CSS 框架”,是关于构建可重用代码以及如何稍后将其用作自己项目的基础的问题。本章将涵盖与创建基本 CSS 框架相关的问题。
第十一章, 邮件发送基础知识,是对邮件发送和在邮件发送过程中可能出现的问题的简短介绍。本章侧重于基础知识。
第十二章, 可扩展性和模块化,教你如何准备可扩展的 CSS 代码。
第十三章, 代码优化,涉及在构建 CSS 代码后发生的最终过程。主要是关于优化和缩小工具。它涵盖了在开始编码之前和在创建 CSS 代码期间准备代码时涉及的问题。
第十四章, 最终自动化和流程优化,涉及对 CSS 代码进行操作的自动化。
您需要什么
为了使用本书,建议您安装您喜欢的 IDE,该 IDE 应支持以下内容:
-
HTML
-
SASS
-
CSS
为了更好地理解代码及其调试,您将需要像这样的浏览器:
-
Google Chrome
-
Mozilla Firefox
-
Internet Explorer 9+
此外,您还需要以下内容:
-
Ruby(用于安装 SASS)
-
SASS
-
Node.js(用于安装 Gulp.js)
-
Gulp.js
这本书适合谁
本书适用于所有希望学习如何使用 CSS 和 SASS 功能的前端开发人员。本书涵盖了许多对每个级别的开发人员都可能感兴趣的主题。如果您是初学者,它将向您介绍 CSS 和 SASS。如果您是中级/高级程序员,本书可以是一本关于一些 CSS 和 SASS 功能的良好复习书。此外,最后一章适用于所有希望开始作为前端开发人员工作并希望自动化大量任务(例如缩小 CSS 代码)的开发人员。
约定
在本书中,您将找到许多工具。主要是 SASS 和 CSS 代码,但是如您所知,CSS 不能单独工作,我们将使用基本的 HTML 结构。此外,还将有大量 JS 代码,用于描述 Gulp.js 任务。
文本中的代码词、数据库表名、文件夹名、文件名、文件扩展名、路径名、虚拟 URL、用户输入和 Twitter 句柄显示如下:"使用预处理器,每个@import都会为您进行合并,在这个位置,您将拥有所提到文件的内容"
代码块设置如下:
@import "typography.css"
@import "blocks.css"
@import "main.css"
@import "single.css"
任何命令行输入或输出都将按如下方式编写:
npm init
npm install gulp-compass gulp --save-dev
新术语和重要单词以粗体显示。例如,屏幕上看到的单词,例如菜单或对话框中的单词,会在文本中显示为这样:"调用检查器的最简单方法是右键单击元素,然后选择检查。"
注意
警告或重要说明会出现在这样的框中。
提示
提示和技巧会出现在这样。
第一章:基础和工具
了解每个领域的基础知识非常重要。您需要有基本信息才能成为专业人士。良好的工具使用几乎和基础一样重要。没有好的工具,您的基础就无法得到很好的利用。
本章介绍了将帮助构建更好的 CSS 代码的工具。它描述了预处理器的特性,最后是关于 SASS 的基础知识。在本章中,您可以获得有关使用GULP.js在前端开发中自动化可重复过程的基本知识。最后,您可以找到一个文件结构的示例,它将您的项目部分化为小型、易于编辑和可维护的文件。
在本章中,我们将:
-
了解预处理器的用法。
-
创建一个具有适当结构的 CSS 项目。
选择正确的 IDE
构建 CSS 代码非常简单。如果您想开始,您只需要一个简单的文本编辑器并开始编写代码。如果您想加快这个过程,您将需要选择正确的文本编辑器或集成开发环境(IDE)。目前,前端开发人员最流行的编辑器/IDE 如下:
-
Sublime Text
-
Atom
-
WebStorm/PHPStorm
-
Eclipse/Aptana
-
Brackets
您的选择将基于价格和质量。您应该使用您感觉最舒适的编辑器。
使用代码片段/Emmet 加快编程过程
当您创建代码时,您会有一些在所有项目/文件中重复的代码部分。您需要创建一些代码片段,这将帮助您加快编写代码的过程。作为前端开发人员,我建议您对Emmet(以前是 Zen Coding)有基本了解。这是一组 HTML/CSS 代码片段,可以帮助您更快地构建代码。如何使用它?它基本上包含在现代前端编辑器(Sublime Text,Atom,Brackets,WebStorm 等)中。如果您想了解 Emmet 在 CSS 中的工作原理,您需要开始声明一些类,例如.className,打开括号({})并写入例如:
pl
padding-left
以下是最常用的属性和值的示例:
| Emmet 表单 | 结果 |
|---|---|
bg |
背景 |
bgc |
背景颜色 |
m |
外边距 |
ml,mr,mt,mb |
左边距,右边距,上边距,下边距 |
ml20px |
左边距:20px |
c |
颜色 |
fl |
浮动:左 |
p20px20p |
填充:20px 20% |
tac |
文本对齐:中心 |
tdn |
文本装饰:无 |
ttu |
文本转换:大写 |
dib |
显示:内联块 |
! |
!important |
为了更好地理解 Emmet 并获得完整的功能列表,建议查看项目的官方网站:emmet.io/。
键盘快捷键
您还记得您学习最令人印象深刻的键盘快捷键Ctrl + C,Ctrl + V吗?它帮助您每次想要复制和粘贴文本或任何其他元素时节省约 2 秒。但是在构建代码时自动化一些过程呢?是的,这将会很有帮助,您可以使用键盘快捷键来实现。
您的 IDE 中应该知道的快捷键如下:
-
复制行
-
删除行
-
移动行
-
格式化代码
跨浏览器兼容性 - 您应该安装哪些浏览器?
要测试您的代码,您将需要所有现代的 Web 浏览器。在您的列表中,您应该有以下浏览器:
-
Google Chrome(最新版本)
-
Mozilla Firefox(最新版本)
-
Mozilla Firefox 开发者版(最新版本)
-
Opera(最新版本)
-
Safari(最新版本)
-
Internet Explorer
Internet Explorer(IE)是前端开发人员生活中最大的问题,因为你需要在你的机器上安装一堆 IE,比如 9、10 和 11。这个列表越来越小,因为过去这个列表更长。IE6、7、8、9 等。现在 IE6、7 和 8 在像 YouTube 和 Facebook 这样的大型网络项目中大多数情况下不被支持。但在一些大公司中,更改操作系统是一个相当复杂的过程。
要在一堆浏览器上轻松测试你的代码,最好使用专门用于此测试的在线工具:
但一个简单而免费的方法是在你的计算机上创建一个虚拟机,并使用你需要的系统和浏览器。要收集所需版本的 IE,你可以参考modern.ie。使用modern.ie,你可以选择你需要的 IE 版本和你的虚拟机平台版本(VirtualBox,Parallels,Vagrant,VMware)。
如何使用检查器
在没有检查器的情况下处理 HTML 和 CSS 代码现在几乎是不可能的。在这个工具中,你可以看到标记和 CSS。此外,你还可以看到盒模型。这对于网页开发人员在浏览器中也是众所周知的。几年前,每个人都在使用专门为 Firefox 设计的 Firebug。现在每个现代浏览器都有自己内置的检查器,它可以帮助你调试代码。
调用检查器的最简单方法是右键单击元素,然后选择检查。在 Chrome 中,你可以使用快捷键。在 Windows 中,你需要按下F12。在 MAC OSX 中,你可以使用cmd + alt + I来调用检查器。

快捷键
为了更快地使用你的浏览器,最好知道一些可以加快进程的快捷键组合。
| 快捷键组合 | 功能 |
|---|---|
| Ctrl + R, cmd + R | 重新加载 |
| Ctrl + Shift + R, cmd + shift + R | 带缓存重新加载 |
| cmd + I, F12 | 检查器 |
| Ctrl + U, cmd + alt + U | 页面源 |
预处理器-为什么应该使用它们?
预处理器是一个程序,它将从其他类似或几乎相同于 CSS 的语法构建 CSS 代码。预处理器的主要优点如下:
-
代码嵌套
-
使用变量的能力
-
创建 mixin 的能力
-
使用数学/逻辑运算的能力
-
使用循环和条件的能力
-
合并多个文件
在预处理器中嵌套元素
预处理器使你能够建立具有声明嵌套的代码的优势。在简单的 CSS 中,你需要写以下内容:
.class {
property: value;
}
.class .insideClass {
property: value;
}
在预处理器中,你只需要写以下内容:
.class {
property: value;
.insideClass {
property: value;
}
}
或者在 SASS 中使用以下缩进:
.class
property: value
.insideClass
property: value
它将简单地编译成代码:
.class {
property: value;
}
.class .insideClass {
property: value;
}
正确的嵌套用法会给你最好的结果。你需要知道良好的 CSS 代码。
使用变量来参数化你的 CSS 代码
在良好的 CSS 代码中,所有浏览器都不可能使用变量。有时你在几个地方使用相同的值,但当你从客户/项目经理/客户经理那里收到更改请求时,你立即需要更改一些颜色/边距等。在 CSS 中,旧版本的 Internet Explorer 不支持使用变量。使用变量是可能的,使用 CSS 预处理器。
在预处理器中使用 mixin
在经典的编程语言中,你可以使用函数来执行一些数学运算或做其他事情,比如显示文本。在 CSS 中,你没有这个功能,但在预处理器中你可以创建 mixin。例如,你需要为 border-radius(旧 IE,Opera 版本)添加前缀:
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
你可以在 SASS 中创建一个 mixin:
@mixin borderRadius($radius) {
-webkit-border-radius: $radius;
-moz-border-radius: $radius;
border-radius: $radius;
}
然后调用它:
@include borderRadius(20px)
数学运算
在预处理器中,你可以使用以下数学运算:
-
加法
-
减法
-
乘法
-
除法
例如,我们可以创建简单的网格系统。例如,您需要 10 列,分辨率为 1,000 像素:
$wrapperWidth: 1000px;
$columnsNumber: 10;
$innerPadding: 10px;
$widthOfColumn = $wrapperWidth / $columnsNumber;
.wrapper {
width: $wrapperWidth;
}
.column {
width: $widthOfColumn;
padding: 0 10px;
}
逻辑操作和循环
没有逻辑运算符的比较操作和循环,您无法在经典编程语言中创建良好的程序。预处理器也是如此。您需要它们来自动创建类/ mixin 等。以下是可能的运算符和循环的列表。
比较运算符的列表如下:
-
<:小于 -
>:大于 -
==:等于 -
!=:不等于 -
<=:小于或等于 -
>=:大于或等于
逻辑运算符的列表如下:
-
and -
or -
not
循环的列表如下:
-
if -
for -
each -
while
多个文件的连接
在经典 CSS 中,您可以将文件导入一个 CSS 文档。但在浏览器中,它仍然会向服务器发出额外的请求。所以,比方说当您有一个文件,其中包含以下内容:
@import "typography.css"
@import "blocks.css"
@import "main.css"
@import "single.css"
它将生成四个额外的 CSS 文件请求。使用预处理器,每个@import都会为您合并,在这个地方您将得到所提到文件的内容。所以,最终,您将得到一个文件中的四个文件。
Less – 简短介绍
Less 是主要用于 Bootstrap 框架的预处理器。它具有预处理器的所有功能(mixin,数学,嵌套和变量)。

其中一个好功能是快速调用已声明的 mixin。例如,您已创建了一个类:
.text-settings {
font-size: 12px;
font-family: Arial;
text-align: center;
}
然后,您可以在您的 less 文件中声明的其他元素中添加已声明属性及其值(它的工作原理类似于 mixin):
p {
.text-settings;
color: red;
}
最终您将得到以下内容:
p {
font-size: 12px;
font-family: Arial;
text-align: center;
color: red;
}
使用 Stylus 的 CSS
Stylus 有两个版本的代码(类似 SASS):一个带有大括号/分号,另一个不带大括号/分号。此外(超过 SASS),您可以省略冒号。如果它继续开发并保留其现有功能,它将成为 SASS 的最大竞争对手。

SASS – 最成熟的预处理器
SASS 代表Syntactically Awesome Stylesheets。它首次出现于 2006 年,主要与Ruby on Rails(RoR)项目相关联。RoR 中使用的敏捷方法对前端开发产生了影响。这是目前在 Foundation 框架中使用的最知名的 CSS 预处理器,结合了 Compass。Twitter Bootstrap 的新版本(第四版)框架也将基于 SASS。

在 SASS 中,您可以以称为SCSS的 CSS 样式版本编写代码。这个代码版本看起来非常类似于 CSS 语法:
a {
color: #000;
&:hover {
color: #f00;
}
}
代码的第二个版本是 SASS。它使用缩进,与前面的代码相同,但是用 SASS 编写:
a
color: #000;
&:hover
color: #f00;
您可以在 mixin 中看到更大的差异。要在 SCSS 中调用 mixin,请写以下内容:
@include nameOfMixin()
要在 SASS 中调用 mixin,请写以下内容:
+nameOfMixin()
正如您所看到的,SASS 比 SCSS 更短。由于快捷方式和自动化过程,强烈建议使用 SASS 而不是 SCSS——写 Less——获得更多。
我个人使用 SASS。为什么?第一个原因是它的结构。它看起来非常类似于 Jade(一种 HTML 预处理器)。它们两者都基于缩进,很容易对 Jade 代码进行样式化。第二个原因是函数的较短版本(特别是 mixin)。第三个原因是它的可读性。有时,当您的代码更大时,SCSS 中的嵌套看起来像一个大混乱。例如,如果您想将嵌套类更改为任何其他元素,您必须更改您的{}。在 SASS 中,您只需处理缩进。
简短比较
我一直在使用 Less 和 SASS。为什么我最终选择了 SASS?因为以下原因:
-
这是一个成熟的预处理器
-
它具有非常好的数学运算
-
它有扩展(Compass,Bourbon)
推荐使用 Compass,因为:
-
它具有一系列现代 mixin
-
它创建精灵
大多数预处理器都具有相同的选项,您选择的原因是您自己的偏好。在本书中,我将使用 SASS 和 Compass。在下表中,您可以找到一个简短的比较:
| Less | Stylus | SASS | |
|---|---|---|---|
| 变量 | 是 | 是 | 是 |
| 嵌套 | 是 | 是 | 是 |
| 混合 | 是 | 是 | 是 |
| 数学 | 是 | 是 | 是 |
| 额外的混合集合 | 否 | 否 | 是(Compass/Bourbon) |
SASS 基础
使用 SASS 预处理器非常简单。您可以以两种方式使用它:SCSS 和 SASS 本身。SCSS 语法看起来像扩展的 CSS。您可以使用新的大括号嵌套您的定义。SASS 语法基于缩进(类似于 Python 语言)。
变量 - 在哪里以及如何使用
使用变量是 SASS 的基本功能,在大多数现代浏览器上使用的 CSS 中几乎不可能。变量可用于您想要参数化的每个元素,例如颜色、边距、填充和字体。
要在 SASS 中定义变量,您只需要使用$符号并在其后添加您的变量名称。
在 SCSS 中:
$color_blue: blue;
用法:
.className {
color: $color_blue;
}
简单的混合 - 在哪里以及如何使用(@mixin,@include)
如前一节所述,变量可用于参数化代码。第二个最为人所知的功能是添加一些预定义的代码块,您可以使用一些更短的版本来调用。
在 SCSS 中,您可以预定义它的方式:
@mixin animateAll($time) {
-webkit-transition: all $time ease-in-out;
-moz-transition: all $time ease-in-out ;
-o-transition: all $time ease-in-out;
transition: all $time ease-in-out;
}
然后通过以下方式调用:
@include animateAll(5s)
在 SASS 版本中:
=animateAll($time)
-webkit-transition: all $time ease-in-out
-moz-transition: all $time ease-in-out
-o-transition: all $time ease-in-out
transition: all $time ease-in-out
并通过以下方式调用:
+animateAll(5s)
示例:
SASS:
.animatedElement
+animateAll(5s)
编译后的 CSS:
.animatedElement {
-webkit-transition: all 5s ease-in-out;
-moz-transition: all 5s ease-in-out;
-o-transition: all 5s ease-in-out;
transition: all 5s ease-in-out;
}
扩展类(@extend)
@extend在 SASS 代码中的作用是什么?例如,您有一部分代码在所有字体中重复:
.font-small {
font-family: Arial;
font-size: 12px;
font-weight: normal;
}
您不希望在下一个选择器中重复此部分代码。您将在 SASS 中编写:
.font-small-red {
@extend .font-small;
color: red;
}
生成的代码如下所示:
.font-small, .font-small-red {
font-family: Arial;
font-size: 12px;
font-weight: normal;
}
.font-small-red {
color: red;
}
这个 SASS 功能非常适合构建优化的代码。请记住在项目中使用它而不是混合,这将生成更多的代码。
导入文件(@import)
在 CSS 中,您可以使用@import将 CSS 文件导入一个根文件。例如:
@import "typography.css"
@import "grid.css"
在 SASS 中,您可以将 SASS/SCSS 文件导入一个自动合并选项中。例如,如果您有两个文件想要包含在一个 SASS 文件中,您需要编写以下代码:
@import "typography"
@import "grid"
如您在上述代码中所见,您不需要在import中添加文件的扩展名,因为它会自动加载 SASS 或 SCSS 文件。您唯一需要记住的是在这个例子中只有一个名为typography的文件。
让我们看看它在实际代码中的表现。假设我们有两个文件,_typography.sass和_grid.sass。
文件_grid.sass:
.grid-1of2
float: left
width: 50%
.grid-1of4
float: left
width: 25%
.grid-1of5
float: left
width: 20%
文件_typography.sass:
body
font-size: 12px
h1, h2, h3, h4, h5, h6
font:
family: Arial
h1
font:
size: 36px
h2
font:
size: 32px
h3
font:
size: 28px
h4
font:
size: 24px
h5
font:
size: 20px
h6
font:
size: 16px
现在让我们创建一个style.sass文件:
@import _typography
@import _grid
编译style.sass后,您将看到一个style.css文件:
body {
font-size: 12px;
}
h1, h2, h3, h4, h5, h6 {
font-family: Arial;
}
h1 {
font-size: 36px;
}
h2 {
font-size: 32px;
}
h3 {
font-size: 28px;
}
h4 {
font-size: 24px;
}
h5 {
font-size: 20px;
}
h6 {
font-size: 16px;
}
.grid-1of2 {
float: left;
width: 50%;
}
.grid-1of4 {
float: left;
width: 25%;
}
.grid-1of5 {
float: left;
width: 2%;
}
如您所见,两个文件合并成一个 CSS 文件,因此我们还对代码进行了小优化,因为我们减少了对服务器的请求次数。如果有三个文件,我们将有三个请求(style.css,然后typography.css和grid.css)。现在只会有一个请求。
在 SASS 中使用&
有时,在嵌套中,您需要使用您当前描述的选择器的名称。作为问题的最佳描述,您需要首先描述一个链接:
a {
color: #000;
}
然后:
a:hover {
color: #f00;
}
在 SCSS 中,您可以使用&来做到这一点:
a {
color: #000;
&:hover {
color: #f00;
}
}
在 SASS 中:
a
color: #000
&:hover
color: #f00
您可以使用此元素解决其他问题,例如组合名称:
.classname {}
.classname_inside {}
在 SCSS 中:
.classname {
&_inside {
}
}
在 SASS 中:
.classname
&_inside
自 SASS 3.5 以来,这个选项已经成为可能。在创建基于 BEM 方法的代码时,这将非常有帮助。
Compass 功能
Compass 是一个非常有用的 SASS 框架,特别是当您使用大量图标/可重用图像时。您需要做的是将所有图像收集到项目中的一个文件夹中。例如,yourfolder/envelope.png和yourfloder/star.png。
然后在您的 SASS 代码中:
@import "compass/utilities/sprites"
@import "yourfolder/*.png"
@include all-yourfolder-sprites
然后在您的代码中,您可以使用图像作为示例:
.simple-class-envelope
@extend .yourfolder-envelope
.simple-class-star
@extend .yourfolder-star
它将向您的类添加代码:
.simple-class-envelope {
background-image: url('spriteurl.png');
background-position: -100px -200px;
}
其中-100px和-200px是您精灵中的偏移量的示例。
简单的自动化(使用 Gulp)
每当我们编译项目文件(例如 Compass、Jade、图像优化等),我们都在考虑如何自动化和加快这个过程。第一个想法是一些终端片段和编译调用者。但我们可以使用grunt.js和gulp.js。Grunt 和 Gulp 是什么?简而言之——任务运行器。您可以定义一系列任务,这些任务您一直重复,将它们分组到一些逻辑结构中,并运行。
在大多数项目中,您可以使用它们来自动化 SASS/Compass 编译过程。
我假设您已经安装了 Node.js、Ruby、sass 和 Compass。如果没有,我建议您首先这样做。要安装所有列出的软件,您需要访问:
-
nodejs.org/en/安装 Node.js -
www.ruby-lang.org/en/安装 Ruby -
sass-lang.com/安装 SASS -
compass-style.org/安装 Compass -
gulpjs.com/在您的机器上全局安装 Gulp
在这些页面上,您可以找到有关如何安装所有这些软件的指南和教程。
然后,您需要为项目创建一个基本结构。最好创建文件夹:
-
src:在这个文件夹中,我们将保存我们的源文件 -
dist:在这个文件夹中,我们将保存我们的编译文件
在src文件夹中,请创建一个css文件夹,其中将保存我们的 SASS 文件。
然后在root文件夹中运行以下命令行:
npm init
npm install gulp-compass gulp --save-dev
在gulpfile.js中添加以下代码行:
var gulp = require('gulp'),
compass = require('gulp-compass');
gulp.task('compass', function () {
return gulp.src('src/styles/main.sass')
.pipe(compass({
sass: 'src/styles',
image: 'src/images',
css: 'dist/css',
sourcemap: true,
style: 'compressed'
}));
});
gulp.task('default', function () {
gulp.watch('src/css/**/*.sass', ['compass']);
});
现在,您可以在命令行中运行您的自动化程序:
gulp
这将从您的gulpfile.js运行default任务,该任务将向具有.sass扩展名的文件添加监视器,这些文件位于src/css文件夹中。每次更改此位置中的任何文件时,您的compass任务将运行。这意味着它将运行compass任务并为我们创建一个源映射。我们可以使用默认的compass命令,但gulp.js是现代前端开发人员工作流程的一部分。我们将在下一章中向这个自动化程序添加新功能。
让我们深入分析一下代码:
gulp.task('default', function () {
gulp.watch('src/css/**/*.sass', ['compass']);
});
上述代码定义了默认任务。它附加了一个监视器,用于检查srs/css/**/*.sass位置的 sass 文件。这意味着src/css文件夹中的每个文件和任何后续文件夹,例如src/css/folder/file.sass,都将有一个监视器。当此位置的文件发生更改时,数组[compass]中定义的任务将运行。我们的task compass是数组中唯一的元素,但它当然可以扩展(我们将在下一章中进行)。
现在让我们分析task compass:
gulp.task('compass', function () {
return gulp.src('src/styles/main.sass')
.pipe(compass({
sass: 'src/styles',
image: 'src/images',
css: 'dist/css',
sourcemap: true,
style: 'compressed'
}));
});
它将编译gulp.src('src/styles/main.sass)文件,并将编译后的文件保存在pipe(gulp.dest('style.css'))中。compass任务在pipe中定义:
.pipe(compass({
sass: 'src/styles',
image: 'src/images',
css: 'dist/css',
sourcemap: true,
style: 'compressed'
}))
此任务的第一行定义了 SASS 文件的源文件夹。第二行定义了图像文件夹。第三行设置了 CSS 文件的目标位置。第四行设置为为文件生成源映射(以便更容易调试)。第五行定义了保存的 CSS 文件的样式;在这种情况下,它将被压缩(这意味着它将准备用于生产代码)。
像素完美的布局工具
在常见的工作流程中,图形设计师创建网站/应用程序的设计。然后,在开发过程中,项目处于质量保证(QA)阶段。有时它只关注项目的功能方面,但在良好的工作流程中,它检查了图形设计阶段。在 QA 过程中,设计师参与其中,他/她将找到代码中所有不好的像素。如何检查像素完美项目中的所有细节?
问题是关于移动项目。在需要在浏览器中灵活时如何检查它是否仍然是像素完美的?您将需要在描述的范围内进行。例如,您必须为具有移动、平板和桌面三种视图的网页创建 HTML/CSS。您将需要插件,这些插件将帮助您构建像素完美的布局。
Pixelfperfect 插件
Pixelperfect 插件将帮助您在浏览器中将设计与您的 HTML/CSS 进行比较。此插件可在 Firefox 和 Chrome 上使用。要使用它,您需要对设计进行截图并将其添加到插件中。然后,您可以设置图像的位置和不透明度。这个插件是前端开发人员中最常用的之一,用于创建像素完美的 HTML 布局。

MeasureIT 插件
这个插件将帮助您在元素、字体等之间保持适当的距离。正如您在下面的截图中所看到的,它看起来像是在您的网页上的标尺。它很容易使用-只需单击浏览器中的插件图标,然后单击网站(它将启动标尺),并将光标移动到您想要知道距离的地方,然后就完成了!

检查兼容性
一些 CSS 特性在所有浏览器中都不起作用。一些新属性需要特定于浏览器的前缀(如-ms、-o、-webkit)才能在所有现代浏览器中正常工作。但是如何检查您是否可以在项目中使用某些属性呢?当然,您可以自己检查,但最简单的方法是在caniuse.com/上进行检查。您可以打开这个网页并检查您可以使用哪些属性。

代码中的良好假设
在创建 CSS 代码时,您必须记住以下初始假设,这将帮助您保持清晰和非常可读的代码。这些假设如下:
-
命名约定-您需要记住,您的代码需要是类的确切名称。
-
使用注释,但不是到处都是,只在需要它们的地方。是的,但什么时候需要它们?当您有一些异常或者当您需要一些快速修复浏览器时,它们尤其需要。通过注释,您可以描述代码块,例如页脚/页眉的视图,或者任何其他元素。
-
尽量保持可读和逻辑的代码。但是不合逻辑的代码是什么样的呢?看下面的两个例子:
示例 1 如下:
.classname {
font-size: 12px;
color: red;
font-weight: bold;
text-align: center;
margin: 10px;
padding-left: 2px;
text-transform: uppercase;
}
示例 2 如下:
.classname {
margin: 10px;
padding-left: 2px;
font-size: 12px;
font-weight: bold;
text-align: center;
text-transform: uppercase;
color: red;
}
哪种代码看起来更好?是的,当然是第二个例子,因为它有分组声明。首先是框模型的描述,然后是字体和文本行为,最后是颜色。您可以尝试将其保持在另一个层次结构中,这将对您更具可读性。
在 SASS 中使用示例 2:
.classname
margin: 10px
padding:
left: 2px
font:
size: 12px
weight: bold
text:
align: center
transform: uppercase
color: red
是不是更短更合乎逻辑?
-
创建适当的选择器(这将在本章后面描述)。
-
为您的文件创建一个弹性结构。
创建适当的选择器
CSS 编码人员的主要问题是创建适当的选择器。了解选择器中的优先级是强制性的。它将帮助您在代码中省略!important语句,并帮助您创建更小、更可读的文件。
使用 ID
在 CSS 中使用 ID 是相当不好的行为。HTML 的基础规定 ID 是唯一的,应该在 HTML 代码中只使用一次。最好在 CSS 中省略 ID,并仅在需要样式化某些元素时使用它们:
#id_name {
property: value;
}
在 CSS 代码中使用 ID 是不好的行为,因为基于 ID 的选择器比基于类的选择器更强。当您看到代码的某些部分仍然由另一个选择器前置时,这在旧代码中是令人困惑的,因为它添加在 ID 的父级选择器中,如下所示:
#someID .class {
/* your code */
}
在您的项目中最好避免这个问题。首先,仔细考虑一下,基于 ID 的选择器在这个地方是否是一个好主意,是否可以用任何其他“较弱”的选择器替换它。
使用类
类是 HTML/CSS 编码者的最佳朋友。它们是可重用的元素,您可以定义,然后在 HTML 代码中尽可能多地重用,例如:
.class_name {
property: value;
}
分组选择器
您可以对选择器进行分组和嵌套。首先,让我们嵌套它们:
.class_wrapper .class_nested {
property: value;
}
然后让我们将它们分组:
.class_wrapper_one,
.class_wrapper_two {
property: value;
}
有趣的选择器
在 CSS 代码中,您需要成为选择器专家。这是一个非常重要的技能,可以创建正确的选择器,以匹配 DOM 结构中的特定元素。让我们提供一些关于选择器的基础知识。
相邻兄弟组合符号+
在 CSS 中,加号可以用在选择器中,您需要选择紧跟在加号左侧元素后面的元素,例如:
p + a {
property: value;
}
这个选择器将返回a,它紧跟在p选择器后面,就像下面的例子中一样:
<p>Text</p>
<a>Text</a>
但在以下情况下不起作用:
<p>Text</p>
<h1>Text</h1>
<a>Text</a>
子组合符号">"
使用元素(>)在选择器中,您可以匹配每个直接在元素中的元素。让我们分析下面的例子:
p >a {
property: value;
}
这个选择器将返回所有在<p>元素中但没有更深层嵌套的<a>元素,例如:
<p>
<a>text</a>
</p>
但在以下情况下不起作用:
<p>
<span>
<a>text</a>
</span>
</p>
相邻兄弟组合符号~
使用~,您可以创建一个选择器,它将匹配 DOM 结构中的每个平行元素,例如:
p ~ a {
color: pink;
}
这个选择器将在以下情况下起作用:
<p></p>
<a></a>
和:
<p>Text</p>
<span>Text</span>
<a>Text</a>
通过属性获取元素
有时,无法根据元素、类和 ID 创建选择器。这就是您需要寻找任何其他可能性来创建正确选择器的时刻。可以通过它们的属性(data、href等)获取元素:
[attribute] {
property: value;
}
它将返回以下内容:
<p attribute>text</p>
并且还将返回以下内容:
<p attribute="1">text</p>
具有确切值的属性 [attribute="value"]
在真实的 CSS/HTML 代码中,有时您需要基于具有确切值的属性创建选择器,例如类型为文本的输入或元素数据属性设置为某个值。可以使用类似于此示例代码的选择器:
input[type="text"] {
background: #0000ff;
}
将匹配:
<input type="text">
以 [attribute^="value"] 开头的属性
当您想要匹配以某个特定字符串开头的属性的元素时,这个选择器非常有用。让我们来看一个例子:
<div class="container">
<div class="grid-1of4">Grid 2</div>
<div class="grid-1of2">Grid 1</div>
<div class="grid-1of4">Grid 3</div>
</div>
SASS 代码:
.grid-1of2
width: 50%
background: blue
.grid-1of4
width: 25%
background: green
[class^="grid"]
float: left
编译后的 CSS:
.grid-1of2 {
width: 50%;
background: blue;
}
.grid-1of4 {
width: 25%;
background: green;
}
[class^="grid"] {
float: left;
}
让我们分析 SASS 代码中的这个片段:
[class^="grid"]
float: left
这个选择器将匹配每个具有以grid开头的属性的元素。在我们的例子中,这将匹配.grid-1of2和.grid-1of4。当然,我们可以用 SASS 来做到这一点:
.grid-1of2, .grid-1of4
float: left
并在编译后的代码中获取它:
.grid-1of2, .grid-1of4 {
float: left;
}
但让我们想象一下,我们有大约10或者40个类,就像下面的例子一样:
.grid-2of4
width: 50%
.grid-3of4
width: 75%
.grid-1of5
width: 20%
.grid-2of5
width: 40%
.grid-3of5
width: 60%
.grid-4of5
width: 80%
在编译后的 CSS 中:
.grid-2of4 {
width: 50%;
}
.grid-3of4 {
width: 75%;
}
.grid-1of5 {
width: 20%;
}
.grid-2of5 {
width: 40%;
}
.grid-3of5 {
width: 60%;
}
.grid-4of5 {
width: 80%;
}
现在我们想要对这些元素应用float: left,如下所示:
.grid-1of2, .grid-1of4, .grid-2of4, .grid-3of4, .grid-1of5, .grid-2of5, .grid-3of5, .grid-4of5
float: left
在 CSS 中:
.grid-1of2, .grid-1of4, .grid-2of4, .grid-3of4, .grid-1of5, .grid-2of5, .grid-3of5, .grid-4of5 {
float: left;
}
使用基于[attribute^="value"]的选择器更容易,并匹配所有以 grid 字符串开头的类的元素:
[class^="grid"]
float: left
空格分隔的属性值 [attribute~="value"]
使用这个选择器,您可以匹配所有在包含描述为“value”的字符串的“attributes”列表中的元素。让我们分析下面的例子。
HTML:
<div class="container">
<div data-style="green font10">Element green font10</div>
<div data-style="black font24">Element black font24</div>
<div data-style="blue font17">Element blue font17</div>
</div>
现在在 SASS 中:
[data-style~="green"]
color: green
[data-style~="black"]
color: black
[data-style~="blue"]
color: blue
[data-style~="font10"]
font:
size: 10px
[data-style~="font17"]
font:
size: 17px
[data-style~="font24"]
font:
size: 24px
编译后的 CSS:
[data-style~="green"] {
color: green;
}
[data-style~="black"] {
color: black;
}
[data-style~="blue"] {
color: blue;
}
[data-style~="font10"] {
font-size: 10px;
}
[data-style~="font17"] {
font-size: 17px;
}
[data-style~="font24"] {
font-size: 24px;
}
在浏览器中的效果如下:
![空格分隔的属性值 [attribute~="value"]](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00009.jpeg)
属性值以 [attribute$="value"] 结尾
在之前的某个部分中,我们有一个基于属性开头的选择器的示例。但是如果我们需要一个属性结尾呢?有了这个功能,就有了基于模式的选择器[attribute$="value"]。让我们来看下面的示例代码:
<div class="container">
<a href="/contact-form">Contact form</a><br>
<a href="/contact">Contact page</a><br>
<a href="/recommendation-form">Recommendation form</a>
</div>
SASS:
[href$="form"]
color: yellowgreen
font:
weight: bold
编译后的 CSS:
[href$="form"] {
color: yellowgreen;
font-weight: bold;
}
在浏览器中的效果如下:
![属性值以 [attribute$="value"] 结尾](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00010.jpeg)
使用选择器[href$="form"],,我们匹配了所有属性href以字符串form结尾的元素。
包含字符串的属性 [attribute*="value"]
使用这个选择器,您可以匹配每个包含任何位置的字符串值的元素。让我们分析下面的例子代码。
HTML:
<div class="container">
<a href="/contact-form">Contact form</a><br>
<a href="/form-contact">Contact form</a><br>
<a href="/rocommendation-form">Recommendation form</a><br>
<a href="/rocommendation-and-contact-form">Recommendation and contact form</a>
</div>
SASS:
[href*="contact"]
color: yellowgreen
font:
weight: bold
编译的 CSS:
[href*="contact"] {
color: yellowgreen;
font-weight: bold;
}
在浏览器中我们将看到:
![包含字符串的属性 [attribute*="value"]](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00011.jpeg)
使用选择器[href*="contact"],我们匹配了包含contact字符串的每个元素在属性href的值中。
在 CSS 中使用!important
哈...这是 CSS 中的魔法词,你可以在一些特殊情况下看到。使用!important,你甚至可以覆盖 HTML 中由 JavaScript 添加的内联代码。
如何使用?非常简单:
element {
property: value !important;
}
记住要正确使用它,并且在您真正需要它的情况下使用它。不要在您的代码中过度使用它,因为它可能会在将来产生很大的影响,特别是在有人阅读您的代码并尝试调试它的情况下。
准备您的项目
开始您的项目并计划是最重要的过程之一。您需要为保持变量和 mixin 创建一个简单的策略,并创建适当的文件结构。本章介绍了在规划文件结构和项目中文件的部分化中最常见的问题。
文件结构
当您开始一个项目时,最重要的是制定一个良好的计划。首先,您需要分开设置:
-
字体
-
变量
-
混合
然后您需要对项目进行部分化。您需要为所有站点中可重复的元素创建文件:
-
页眉
-
页脚
-
表单
然后您需要准备下一个部分化-样式和元素的特定视图,例如:
-
查看主页
-
查看博客
-
查看单个帖子
-
查看联系页面
如何在项目中保存变量
您可以在变量中保存什么?是的,这肯定是一个好问题:
-
颜色(字体,背景和元素的颜色)
-
全局字体大小(如 H1-H6,p 等)
-
网格分隔符
-
全局填充/边距
如何以及在哪里保存 mixin(本地和全局)
在这个文件中,您可以收集您最常用的 mixin。我将其分为本地和全局。在全局 mixin 中,我正在收集我在所有项目中使用的最常用的 mixin。
在本地 mixin 中,我建议收集您仅在此项目中使用的 mixin:
-
专用渐变
-
字体样式包括字体系列大小等等
-
悬停/活动状态等等
将排版样式保存在单独的文件中
这个文件是专门为所有最重要的文本元素而设计的:
-
h1-h6 -
p -
a -
strong -
span
此外,您还可以添加类似以下的类:
-
.h1-h6 -
.red .blue(或者您知道将在您的文本中重复的任何其他内容) -
.small,.large
为什么应该使用类似.h1-.h6的类?
是的,这是一个非常明显的问题。有时您不能重复h1-h6元素,但是,例如,在博客上,您需要使它们与h1相同的字体样式。这是这种样式的最佳用法,例如(HTML 结构):
<h1> Main title</h1>
<h2>Subtitle</h2>
<p>... Text block ... </p>
<h2>Second subtitle</h2>
<p>... Text block ... </p>
<p class="h2">Something important</p>
<p>... Text block ... </p>
<p class="h1">Something important</p>
<p>... Text block ... </p>
特定元素的视图
在下面列出的文件中,您可以收集在某些特定视图中可见的所有元素。例如,在博客结构中,您可以有单个帖子或页面视图。因此,您需要创建文件:
_view_singlepost.sass
_view_singlepage.sass
_view_contactpage.sass
提示
下载示例代码
您可以从www.packtpub.com的帐户中下载本书的示例代码文件。如果您在其他地方购买了本书,您可以访问www.packtpub.com/support并注册,以便直接将文件发送到您的电子邮件。
您可以按照以下步骤下载代码文件:
-
使用您的电子邮件地址和密码登录或注册我们的网站。
-
将鼠标指针悬停在顶部的SUPPORT选项卡上。
-
点击代码下载和勘误。
-
在搜索框中输入书名。
-
选择您要下载代码文件的书籍。
-
从下拉菜单中选择您购买本书的地方。
-
点击代码下载。
您还可以通过在 Packt Publishing 网站上的图书网页上点击代码文件按钮来下载代码文件。可以通过在搜索框中输入书名来访问该页面。请注意,您需要登录您的 Packt 账户。
文件下载完成后,请确保使用最新版本的解压缩或提取文件夹:
-
WinRAR / 7-Zip for Windows
-
Zipeg / iZip / UnRarX for Mac
-
7-Zip / PeaZip for Linux
摘要
在本章中,您收集了关于现代 CSS 工作流程基础知识的信息。我们从选择 IDE 开始,然后专注于通过使用片段、预处理器和流程自动化来加快流程。
在下一章中,我们将专注于 CSS 理论的基础知识,包括 CSS 的盒模型、定位和显示模式。
第二章:基础的掌握
本章将掌握盒子模型、浮动故障排除定位和显示类型。在本章之后,您将更加了解 HTML 和 CSS 的基础知识。
在本章中,我们将涵盖以下主题:
-
了解传统盒子模型
-
浮动元素的基础知识
-
在网页上定位元素的基础
-
了解显示类型
传统的盒子模型
对盒子模型的理解是 CSS 理论的基础。您必须了解宽度、高度、边距和边框对盒子大小的影响,以及如何管理它以匹配网站上的元素。面试中对编码人员和前端开发人员的主要问题基于盒子模型理论。让我们开始这一重要的章节,这将是以后每个主题的基础。
填充/边距/边框/宽度/高度
盒子的最终宽度和高度的组成部分如下:
-
宽度
-
高度
-
边距
-
填充
-
边框
为了更好地理解盒子模型,以下是谷歌浏览器检查器的图像:

为了更清晰地理解盒子模型,让我们分析以下图像:

在上图中,您可以看到在盒子模型中,我们有以下四个边缘:
-
内容边缘
-
填充边缘
-
边框边缘
-
边距边缘
盒子的宽度和高度基于以下内容:
-
内容的宽度/高度
-
填充
-
边框
-
边距
默认盒子尺寸中盒子内容的宽度和高度由以下属性控制:
-
最小宽度
-
最大宽度
-
宽度
-
最小高度
-
最大高度
-
高度
盒子模型的一个重要问题是背景属性的行为方式。背景将包括在内容部分和填充部分(到填充边缘)。
让我们获取一个代码并尝试指向盒子模型的所有元素。
HTML 代码:
<div class="element">
Lorem ipsum dolor sit amet consecteur
</div>
CSS 代码:
.element {
background: pink;
padding: 10px;
margin: 20px;
width: 100px;
height: 100px;
border: solid 10px black;
}
在浏览器中,我们将看到以下内容:

在谷歌浏览器的检查器视图如下:

让我们检查盒子模型的区域如何放置在以下具体示例中:

面试的前端开发人员的基本任务是:
盒子/元素的样式描述如下:
.box {
width: 100px;
height: 200px;
border: 10px solid #000;
margin: 20px;
padding: 30px;
}
请计算此元素的最终宽度和高度(实际所需的空间)。
因此,您可以看到,问题在于计算盒子的宽度和高度。
宽度的组成部分如下:
-
宽度
-
左边框
-
右边框
-
左填充
-
右填充
此外,用于盒子占用空间的宽度的图像:
-
左边距
-
右边距
高度的组成部分如下:
-
高度
-
顶部边框
-
底部边框
-
顶部填充
-
底部填充
此外,用于盒子占用空间的高度的图像:
-
顶部边距
-
底部边距
因此,当您总结这些元素时,您将得到以下方程:
宽度:
Box width = width + borderLeft + borderRight + paddingLeft + paddingRight
Box width = 100px + 10px + 10px + 30px + 30px = 180px
空间宽度:
width = width + borderLeft + borderRight + paddingLeft + paddingRight + marginLeft + marginRight
width = 100px + 10px + 10px + 30px + 30px + 20px + 20 px = 220px
高度:
Box height = height + borderTop + borderBottom + paddingTop + paddingBottom
Box height = 200px + 10px + 10px + 30px + 30px = 280px
空间高度:
Space height = height + borderTop + borderBottom + paddingTop + paddingBottom + marginTop + marginBottom
Space height = 200px + 10px + 10px + 30px + 30px + 20px + 20px = 320px
您可以在实际浏览器中检查如下所示:

省略传统盒子模型的问题(盒子尺寸)
盒子模型的基本理论是非常难学的。您需要记住所有宽度/高度的元素,即使您设置了宽度和高度。初学者最难理解的是填充,它不应计入宽度和高度的组成部分。它应该是在盒子内部,并且应该影响这个值。为了改变这些行为,CSS3 支持自 Internet Explorer 8 以来,引入了盒子尺寸。
您可以设置如下值:
box-sizing: border-box
这对您有什么好处?最终,盒子的宽度和高度的计算将更容易,因为盒子的填充和边框在盒子内部。因此,如果我们正在进行我们之前的课程:
.box {
width: 100px;
height: 200px;
border: 10px solid #000;
margin: 20px;
padding: 30px;
}
我们可以轻松计算宽度和高度:
Width = 100px
Height = 200px
此外,框所占用的空间:
-
空间宽度= 140px(因为 20px 的边距在左右两侧)
-
空间高度= 240px(因为 20px 的边距在顶部和底部两侧)
以下是来自 Google Chrome 的示例:

因此,如果您不想重复传统框模型的所有问题,您应该全局为所有元素使用它。当然,对于旧项目,例如需要对旧项目进行一些小改动的新客户,不建议使用它。如果您添加以下代码:
* {
width: 100px;
}
由于这个属性对现在基于传统框模型的所有元素都有继承,所以可能会带来更多的伤害。但对于所有新项目,您应该使用它。
浮动元素
浮动框在现代布局中被广泛使用。浮动框的理论特别在网格系统和 CSS 框架中的内联列表中被使用。例如,Zurb Foundation 框架中的类和 mixin 内联列表是基于浮动的。
浮动元素的可能性
元素可以浮动到左侧和右侧。当然,也有一种方法可以重置浮动。可能的值如下:
float: left; // will float element to left
float: right; // will float element to right
float: none; // will reset float
最常见的浮动问题
当您使用浮动元素时,可能会遇到一些问题。浮动元素最常见的问题如下:
-
太大的元素(因为宽度、左/右边距、左/右填充和基于框模型的宽度计算不当)
-
未清除的浮动
所有这些问题都会产生特定的效果,您可以轻松识别并进行修复。
当元素太大时,可以通过它们不在一行中来识别。您首先应该检查的是是否应用了box-sizing: border-box,然后检查宽度、填充和边距。
您可以轻松识别未清除的浮动,当一些元素的浮动结构来自下一个容器时。这意味着您的浮动容器中没有清除浮动。
定义清除浮动/类/混合
当我开始开发 HTML 和 CSS 代码时,有一种方法可以使用.cb或.clear类来清除浮动,这两种方法都定义如下:
.clearboth, .cb {
clear: both
}
此元素是在所有浮动元素之后的容器中添加的。这一点很重要,要记住清除浮动,因为包含浮动元素的容器不会继承最高浮动元素的高度(其高度将等于0),例如:
<div class="container">
<div class="float">
… content ...
</div>
<div class="float">
… content ...
</div>
<div class="clearboth"></div>
</div>
CSS 如下所示:
.float {
width: 100px;
height: 100px;
float: left;
}
.clearboth {
clear: both
}
现在,有一种更好、更快的方法来清除浮动。您可以使用“清除浮动”元素来实现,如下所示:
.clearfix:after {
content: "";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
您可以在 HTML 代码中使用它:
<div class="container clearfix">
<div class="float">
... content ...
</div>
<div class="float">
... content ...
</div>
</div>
</div>
打开“清除浮动”的主要原因是您可以节省一个标签(带有clearboth类)。推荐的用法是基于 SASS 中定义的“清除浮动”mixin,如下所示:
=clear fix
&:after
content: ""
visibility: hidden
display: block
height: 0
clear: both
因此,每次您需要在某个容器中清除浮动时,都需要调用它。例如,让我们看看之前的代码:
<div class="container">
<div class="float">
… content ...
</div>
<div class="float">
… content ...
</div>
</div>
容器可以描述如下:
.container
+clear fix
使用浮动元素的示例
浮动元素最常见的用法是网格。网格主要用于构造网页上显示的数据。在本章中,让我们简要检查一下网格的草图。在接下来的章节中,我们将专注于使用 mixin 自动创建网格。
让我们创建一些 HTML 代码:
<div class="row">
<div class="column_1of2">
Lorem
</div>
<div class="column_1of2">
Lorem
</div>
</div>
<div class="row">
<div class="column_1of3">
Lorem
</div>
<div class="column_1of3">
Lorem
</div>
<div class="column_1of3">
Lorem
</div>
</div>
<div class="row">
<div class="column_1of4">
Lorem
</div>
<div class="column_1of4">
Lorem
</div>
<div class="column_1of4">
Lorem
</div>
<div class="column_1of4">
Lorem
</div>
</div>
并创建一些 SASS 代码:
*
box-sizing: border-box
=clear fix
&:after
content: ""
visibility: hidden
display: block
height: 0
clear: both
.row
+clear fix
.column_1of2
background: orange
width: 50%
float: left
&:nth-child(2n)
background: red
.column_1of3
background: orange
width: (100% / 3)
float: left
&:nth-child(2n)
background: red
.column_1of4
background: orange
width: 25%
float: left
&:nth-child(2n)
background: red
最终效果如下:

正如您所看到的,我们创建了一个基本网格结构。在放置 HTML 代码的地方,Lorem是一个完整的lorem ipsum,用来说明网格系统。
显示类型
CSS 中有几种显示类型,其定义和行为是前端开发人员的基础。最常见和基本的显示值如下:
-
内联
-
块
-
内联块
-
表格/表格单元格
-
Flex(这将在本书的后续部分中进一步描述)
块级元素
块级元素总是从新的一行开始。块级元素最重要的属性是宽度和高度,可以从 CSS 代码中进行更改。为了更好地理解,让我们来看下面的截图:

很容易看到,所有的块级元素都占据尽可能多的宽度。
主要使用的 HTML 块级元素如下:
-
address -
article -
aside -
blockquote -
canvas -
div -
footer -
form -
h1,h2,h3,h4,h5,h6 -
header -
main -
nav -
ol -
output -
p -
pre -
section -
table -
ul -
video
内联元素
内联元素可以被描述为占据所需的空间的元素。可以通过以下图像最好地描述:

主要使用的 HTML 内联级元素如下:
-
acronym -
cite -
code -
dfn -
strong -
samp -
var -
a -
bdo -
br -
img -
map -
object -
script -
span -
sub -
sup -
button -
input -
label -
select -
textarea
内联块显示
内联元素是具有内联和块级元素属性的元素。内联元素占据所需的空间,但另外您可以设置它们的宽度、高度和填充。在下面添加的图像中,您可以看到以下代码:
<body>
<p> Block element </p>
<span>Inline element</span>
<p class="width300"> Block element width 300 </p>
<span class="width300">Inline element width 300</span>
<span class="width300 dib"> Block element width 300 </span>
</body>
用 SASS 代码描述:
p, span
background: red
&.width300
width: 300px
.dib
display: inline-block
编译为 CSS:
p, span {
background: red;
}
p.width300,
span.width300 {
width: 300px;
}
.dib {
display: inline-block;
}

正如您可以轻松看到的,第一个元素是一个块级元素,它占据尽可能多的宽度。第二个元素是内联的。第三个是一个具有固定宽度(300 像素)的块级元素。第四个元素是具有固定宽度(300 像素)的内联元素,但它没有适当的显示类型,因此未应用到该元素。此外,最后一个元素是一个 span,其正常的显示类型是内联的,但在 CSS 中设置为内联块。在此操作之后,您可以设置元素的宽度,并且此外,它会自然地浮动到前一个内联元素。
您可以在哪些地方使用其他类型的元素 - 导航
与显示类型相关的最常见问题是内联导航。为了更好地理解,让我们创建一个如下的标记:
<nav class="main-navigation">
<ul>
<li>
<a href="#">First element</a>
</li>
<li>
<a href="#">Second element</a>
</li>
<li>
<a href="#"> Third element</a>
</li>
</ul>
</nav>
使元素在一行中的最简单方法是使用float:left,例如:
.main-navigation
ul
+clear fix /* This will prevent problems of cleared float */
list-style: none
li
float: left
第二个想法是在li元素上使用display: inline-block:
.main-navigation
ul
list-style: none
li
display: inline-block
您可以在哪些地方使用其他类型的元素 - 等高框的问题
有一个问题,在网页上重复出现,您需要附加一些 JavaScript 代码来应用相同的高度。过去是必须这样做的。首先,测量框的高度,然后将更大的高度设置为将应用于另一个框的高度。最后,将高度应用于所有等高框。
如今,您可以使用table-cell值的显示。
HTML 代码:
<div class="equalizer">
<div class="equalized">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</div>
<div class="equalized">
Lorem ipsum dolor sit amet, consectetur adipisicing elit.
</div>
<div class="equalized">
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nam, soluta voluptatem accusamus totam possimus corporis inventore consequuntur unde ut deserunt reiciendis quis aspernatur, ea quisquam numquam veniam illo, cum culpa.
</div>
</div>
SASS 代码:
.equalizer
display: table
background: orange
.equalized
display: table-cell
width: 300px
background: yellow
在浏览器中的效果如下所示:

CSS 元素定位
在 CSS 中理解位置是前端开发人员的关键技能之一。它可以帮助您改变网页上每个元素的行为。此外,通过混合位置,您可以改变内部(子)元素的行为。
静态、相对、绝对、固定 - 差异
静态位置是位置的默认值,包括网页上的每个元素。
相对位置使元素相对于自身。您可以通过以下代码轻松理解它:
<p>
Lorem
<span> ipsum</span>
</p>
并创建 SASS:
span
position: relative
top: -10px
在附加样式之前,您应该看到的如下所示:

此外,在附加样式之后,您将看到以下内容:

正如您所看到的,当我们将位置更改为relative并使用 top、left、right 或 bottom 属性移动它时,我们将从当前位置移动元素。
此外,相对定位的元素可以被设置为绝对定位内部元素的作用域,例如,HTML:
<div class="relative">
<div class="absolute"></div>
</div>
SASS:
.relative
width: 200px
height: 200px
background: orange
position: relative
.absolute
width: 40px
height: 40px
background: red
position: absolute
left: 100px
top: 30px
在浏览器中的效果如下所示:

橙色框是一个.relative元素。较小的框是绝对定位的,并与relative元素相关。
absolute定位可以像上面的例子一样使用。但是当没有父相对元素时会发生什么?绝对定位的元素将与 HTML DOM 元素相关联。
固定元素严格固定在浏览器中。因此,当您将 position: fixed应用于任何元素并给它 top: 0和 left: 0时,该元素将固定在浏览器的左上角。即使进行滚动操作,元素的位置也不会相对于浏览器发生变化。
以下代码将展示固定元素的行为。
HTML:
<body>
<div class="fixed">
position: fixed
</div>
<ul>
<li>Lorem</li>
<li>Ipsum</li>
<li>Dolor</li>
<li>Sit</li>
<li>Amet</li>
</ul>
</body>
SASS:
body
padding-top: 100px
background: red
.fixed
position: fixed
text-align: center
top: 0
left: 0
height: 100px
width: 100%
background: blue
ul
height: 2000px
如您在上述代码中所见,body元素具有padding-top,其值等于.fixed元素的高度。这是由fixed元素引起的,通常情况下,当您移除填充时,fixed元素将覆盖body内容(它将覆盖此元素)。以下截图显示了滚动操作之前的浏览器,下一截图显示了滚动操作之后的浏览器。两个截图都包含了浏览器的边框,以显示正确的滚动操作。


可以添加到具有relative/fixed/absolute位置的元素的重要属性如下:
-
左侧
-
右侧
-
顶部
-
底部
-
Z-index
在编写位置时常见的问题是通过应用right值来覆盖left值。示例代码如下:
.element
position: absolute
left: 10px
right: 20px
.element仍将固定在其左侧位置。如何将其附加到右侧位置?
.element
position: absolute
left: auto
right: 20px
固定图像的列表(右侧或左侧)和描述
这是一个与列表相关的常见问题。具有固定宽度和高度的固定图像的文章列表在一侧,而右侧具有弹性内容可能会在没有relative和absolute位置的情况下出现问题。以下是一个例子。
HTML:
<article>
<div class="image">
<img src="img/image.jpg"/>
</div>
<div class="content">
<p class="header">Header</p>
<p class="description">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua</p>
</div>
</article>
SASS:
*
box-sizing: border-box
article
position: relative
padding: 10px
left: 220px
height: 220px
background: red
.image
position: absolute
left: 10px
top: 10px
background: #000
width: 200px
height: 200px
.content
width: 100%
编译后的 CSS 代码:
* {
box-sizing: border-box;
}
article {
position: relative;
padding: 10px;
padding-left: 220px;
height: 220px;
background: red;
}
article .image {
position: absolute;
left: 10px;
top: 10px;
background: #000;
width: 200px;
height: 200px;
}
article .content {
width: 100%;
}
在浏览器中的效果如下所示:

调整浏览器大小后的效果如下所示:

当您想要在右侧获取图像时,您需要进行以下更改:
article
position: relative
padding: 10px
right: 220px // change here
height: 220px
background: red
.image
position: absolute
right: 10px // change here
top: 10px
background: #000
width: 200px
height: 200px
编译后的 CSS:
* {
box-sizing: border-box;
}
article {
position: relative;
padding: 10px;
padding-right: 220px;
height: 220px;
background: red;
}
article .image {
position: absolute;
right: 10px;
top: 10px;
background: #000;
width: 200px;
height: 200px;
}
在浏览器中的效果如下所示:

总结
本章为专业使用 CSS 建立了坚实的基础。您已经了解了盒模型、位置和浮动元素的知识。下一章将讲述关于伪类的故事。
第三章:掌握伪元素和伪类
使用 CSS 添加网站上的简单交互自从伪类可用以来就已经很常见了。了解如何在网站上使用这个功能非常重要。伪元素可以在诸如 Internet Explorer 8/9 +之类的浏览器中使用,并且可以帮助处理一些在网页上重复出现的元素,这些元素在大多数情况下是通过空的spans和divs添加的,例如按钮中的图形细节,三角形等。使用伪元素,您可以在不创建 DOM 元素的情况下添加这些元素。
绘制基本图形是一项非常重要的技能,特别是当你将它们与伪元素链接在一起时,你可以在其中添加它们。添加三角形或其他特定元素可能是一个非常重要的功能,因为你不必将这些图形元素作为背景或img元素进行裁剪。
本章将掌握 CSS 代码中的伪元素,伪类和基本图形的绘制。最后,在每个部分中,您可以将这些元素组合成实用且可重用的代码。
在本章中,我们将:
-
学习伪类的使用
-
学习伪元素的使用
-
学习如何绘制基本图形
-
在 SASS 中创建大量可重用的混合
伪类
伪类用于描述元素在特定操作后的行为。伪类支持的操作如下:
-
鼠标悬停
-
鼠标点击/触摸
-
输入焦点
伪类的另一个用途是匹配特定容器中的元素,描述了容器中的顺序:
-
第一个子元素,最后一个子元素
-
任何子元素
-
任何类型的子元素
伪类的最重要特性可以在链接(带有href属性的<a>元素)上看到。
我们如何检查:活动状态,悬停状态?
悬停状态可以在将鼠标指针移动到链接上时进行检查。这个属性最简单的用法可以通过以下代码进行检查:
HTML:
<a href="#"> Title of link</a>
SASS:
a
color: #000
background: #fff
a:hover
color: #fff
background: #000
生成的 CSS 代码:
a {
color: #000;
background: #fff;
}
a:hover {
color: #fff;
background: #000;
}
使用上述代码,当你将鼠标悬停在链接上时,链接的颜色和背景将会改变。
用法-多级菜单
多级菜单是悬停状态的最常见用法。下拉菜单可以使用简单的 HTML 和 CSS 开发。您几乎可以在每个网站上看到它。了解如何构建它可以成为更复杂解决方案的基础。让我们构建一个多级导航,并以以下内容为基础:
HTML 代码:
<ul>
<li>
<a href="#">Level one - item one</a>
<ul>
<li><a href="#">Level two - item one</a></li>
<li><a href="#">Level two - item two</a></li>
<li><a href="#">Level two - item three</a></li>
<li><a href="#">Level two - item four</a></li>
</ul>
</li>
<li>
<a href="#">Level two - item one</a>
<ul>
<li><a href="#">Level two - item one</a></li>
<li><a href="#">Level two - item two</a></li>
<li><a href="#">Level two - item three</a></li>
<li><a href="#">Level two - item four</a></li>
</ul>
</li>
<li>
<a href="#">Level one - item three</a>
<ul>
<li><a href="#">Level three - item one</a></li>
<li><a href="#">Level three - item two</a></li>
<li><a href="#">Level three - item three</a></li>
<li><a href="#">Level three - item four</a></li>
</ul>
</li>
<ul>
SASS 代码:
ul
list-style: none
padding: 0
ul > li
float: left
display: inline-block
position: relative
margin-right: 10px
&:hover
ul
display: block
width: 200px
ul ul
display: none
position: absolute
left: 0
li
display: block
编译后的 CSS:
ul {
list-style: none;
padding: 0;
}
ul >li {
float: left;
display: inline-block;
position: relative;
margin-right: 10px;
}
ul >li:hover ul {
display: block;
width: 200px;
}
ul ul {
display: none;
position: absolute;
left: 0;
}
ul ul li {
display: block;
}
在任何元素上悬停时的效果可以在以下截图中看到:

在悬停在第二个元素后:

用法- CSS 悬停行
在简短的 HTML 表格中,阅读所有内容很容易。但是在您有大量数据(特别是在金融网站上)分配在许多行和列中的情况下,很容易使表格变得难以阅读。有几种方法可以简化阅读过程。最简单的方法是为所有行添加悬停效果。每次指向一行时,它都会改变背景颜色。让我们使用以下 HTML 代码:
<table>
<thead>
<tr>
<th> Col one header</th>
<th> Col two header</th>
<th> Col three header</th>
</tr>
</thead>
<tbody>
<tr>
<td> Col one header</td>
<td> Col two header</td>
<td> Col three header</td>
</tr>
<tr>
<td> Col one header</td>
<td> Col two header</td>
<td> Col three header</td>
</tr>
<tr>
<td> Col one header</td>
<td> Col two header</td>
<td> Col three header</td>
</tr>
<tr>
<td> Col one header</td>
<td> Col two header</td>
<td> Col three header</td>
</tr>
</tbody>
</table>
假设行数(tbody中的tr元素)几乎是无限的。这可能会给我们带来一个非常长的表格。为了方便阅读,我们可以为每一行添加悬停效果,如下所示:
SASS:
tbody
tr:hover
background: #d3d3d3
编译后的 CSS:
tbody tr:hover {
background: #d3d3d3;
}
每次悬停在每一行上时,您可以看到以下截图中显示的效果(灰色行被悬停):

伪类的用法
新的伪类为 CSS/HTML 编码人员打开了新的视野。大多数功能,如first-child,last-child和nth-child,都是通过 JavaScript 代码添加的。例如,使用 jQuery 代码,您可以获取一个列表元素,并向第一个/最后一个/nth 元素添加特定类,然后正确创建选择器,您可以添加 CSS 代码。
但是当它被浏览器原生支持时,最好使用 CSS。让我们收集关于这个功能的基本知识。
如何使用:first-child,:last-child,:nth-child()
这些伪元素的简短介绍如下:
-
:first-child:这指向其父元素的第一个子元素 -
:last-child:这指向其父元素的最后一个子元素 -
:nth-child():这指向与()中包装的模式匹配的元素
检查其工作原理的最简单方法是创建一个带有新元素的无序列表:
<ul>
<li>Element one</li>
<li>Element two</li>
<li>Element three</li>
<li>Element four</li>
<li>Element five</li>
<li>Element six</li>
<li>Element seven</li>
<li>Element eight</li>
</ul>
假设我们需要为列表的元素添加样式。我们需要添加的第一个样式仅与列表的第一个元素相关。最简单的方法是向该元素添加特定的类,如下所示:
<li class="first_element>Element one</li>
然后为其添加特定的 CSS/SASS 代码:
SASS 代码:
.first_element
color: #f00
编译为 CSS:
.first_element {
color: #f00;
}
使用新伪类:
li:first-child
color: #00f
或:
li:nth-child(1)
color: #00f
编译为:
li:first-child {
color: #00f;
}
li:nth-child(1) {
color: #00f;
}
我们需要追加的第二种样式是使最后一个元素的文本颜色变为蓝色。最简单的方法是更改 HTML 代码:
<li class="last_element">Element eight</li>
然后为其添加特定的 CSS/SASS 代码:
.last_element
color: #00f
编译为:
.last_element {
color: #00f;
}
使用新伪类:
li:last-child
color: #00f
编译为:
li:last-child {
color: #00f;
}
在这种情况下,我们不关心列表中元素的数量。列表的最后一个元素将始终具有前面的 CSS 代码。
为第八个元素添加样式,如下所示:
li:nth-child(8)
color: #00f
编译后:
li:nth-child(8) {
color: #00f;
}
在这种情况下,我们关心的是计数元素。列表的第八个元素将始终具有前面的 CSS 代码。
假设我们想要使第五个元素变为橙色。最简单的方法是更改 HTML 代码:
<li class="fifth_element">Element five</li>
然后追加 CSS 代码:
.fifth_element
color: orange
使用伪类,我们可以这样绘制 SASS:
li:nth-child(5)
color: orange
在浏览器中的代码:

用法-为表格添加样式
实际示例对于学习是最好的。我们可以使用伪类的所有属性的最常见的情况是表格。让我们看一下以下 HTML 代码:
<table>
<thead>
<tr>
<th> Col one header</th>
<th> Col two header</th>
<th> Col three header</th>
</tr>
</thead>
<tbody>
<tr>
<td> Col one content</td>
<td> Col two content</td>
<td> Col three content</td>
</tr>
<tr>
<td> Col one content</td>
<td> Col two content</td>
<td> Col three content</td>
</tr>
<tr>
<td> Col one content</td>
<td> Col two content</td>
<td> Col three content</td>
</tr>
<tr>
<td> Col one content</td>
<td> Col two content</td>
<td> Col three content</td>
</tr>
</tbody>
</table>
让我们为表格添加斑马条纹样式;这样可以更轻松地阅读表格:
tbody
tr:nth-child(2n)
background: #d3d3d3
编译后的 CSS:
tbody tr:nth-child(2n) {
background: #d3d3d3;
}
这种样式将为表格中的每个第二个元素添加灰色背景,如下面的屏幕截图所示:

探索:nth-child 参数
作为:nth-child基于选择器的参数,您可以使用以下任何一个:
-
Even:这将匹配所有偶数元素
-
Odd:这将匹配所有奇数元素
此外,您可以使用an+b参数,例如:
-
3n+1:这将匹配具有索引(从 1 开始计数)的元素:1, 4, 7, 10,…
-
–n+5:这将匹配从 1 到 5 的元素
-
2n+4:这将匹配元素:4, 6, 8, 10, 12, …
如何使用:nth-last-child
这个伪类与nth-child类似。不同之处在于nth-child从列表的开头开始工作,而nth-last-child从列表的末尾开始工作:
-
Even:这将匹配从最后一个元素开始的所有偶数元素
-
Odd:这将匹配从最后一个元素开始的所有奇数元素
您可以使用an+b参数,就像我们在nth-child中使用的那样:
-
3n+1:这将匹配具有索引(从最后一个元素开始计数)的元素:1, 4, 7, 10,…
-
–n+5:这将匹配最后五个元素
-
2n+4:这将匹配元素:4, 6, 8, 10, 12, …(从最后一个元素开始计数)
如何使用:first-of-type、:last-of-type、:nth-of-type 和:nth-last-of-type
这些伪类与容器中的元素相关联,其中聚集了一些元素。它的工作方式类似于 nth-child 机制。为了更好地理解,让我们从以下 HTML 代码开始:
<div class="parent">
<span>First span</span><br/>
<strong>First strong</strong><br/>
<span>Second span</span><br/>
<strong>Second strong</strong><br/>
<span>Third span</span><br/>
<strong>Third strong</strong><br/>
<span>Fourth span</span><br/>
<strong>Fourth strong</strong><br/>
<span>Fifth span</span>
</div>
SASS 代码:
.parent
span
&:first-of-type
color: red
&:last-of-type
color: red
strong
&:nth-of-type(2)
color: pink
&:nth-last-of-type(2)
color: magenta
编译为 CSS:
.parent span:first-of-type {
color: red;
}
.parent span:last-of-type {
color: red;
}
.parent strong:nth-of-type(2) {
color: pink;
}
.parent strong:nth-last-of-type(2) {
color: magenta;
}
让我们解释一下:
-
.parent span:first-of-type:这将匹配
.parent div (<div class="parent">)中的第一个元素,即span -
.parent span:last-of-type:这将匹配
.parent中的最后一个元素,即span -
.parent strong:nth-of-type(2):这将匹配第二个元素,即
strong -
.parent strong:nth-last-of-type(2):这将匹配从最后一个元素开始计数的第二个元素,即强调,如下面的屏幕截图所示:
![如何使用:first-of-type,:last-of-type,:nth-of-type 和:nth-last-of-type]()
使用:empty 伪类的空元素
有时,您需要处理列表,其中需要使用一段 CSS 代码处理空元素,另一段 CSS 代码处理有内容的元素。最简单的方法是向其元素添加empty类,而无需干扰 HTML 代码。让我们看看 HTML 代码:
<ul>
<li class="box">Black text</li>
<li class="box"></li>
<li class="box">Black text</li>
<li class="box"></li>
<li class="box"></li>
<li class="box">Black text</li>
<li class="box"></li>
</ul>
和 SASS 代码:
ul
list-style: none
.box
background: white
color: black
text-align: center
height: 100px
width: 100px
float: left
.box:empty
color: black
background: black
编译为 CSS:
ul {
list-style: none;
}
.box {
background: white;
color: black;
text-align: center;
height: 100px;
width: 100px;
float: left;
}
.box:empty {
color: black;
background: black;
}
这将在浏览器中显示以下视图:

很容易分析上述代码。所有空元素(没有子元素的元素)都具有黑色背景。所有具有子元素的元素都具有白色背景和黑色文本。
使用伪类支持表单样式
您可以使用 CSS 代码支持表单的验证和简单交互。在接下来的几节中,您将看到如何使用 CSS 选择器进行简单验证和输入的简单交互。使用适当的 CSS 代码,您还可以检查任何元素是否为必填或禁用。让我们看看这是如何完成的。
使用:valid 和:invalid 进行验证
以前的验证是使用 JavaScript 代码完成的。使用适当的 CSS 代码,您只需使用良好的选择器即可完成。让我们使用 HTML 和 CSS 代码进行检查:
HTML 代码:
<form class="simple_validation">
<input type="number" min="5" max="10" placeholder="Number">
<input type="email" placeholder="Email">
<input type="text" required placeholder="Your name"/>
</form>
SASS 代码:
.simple_validation
padding: 10px
width: 400px
box-sizing: border-box
&:valid
background: lightgreen
&:invalid
background: lightcoral
input
display: block
margin: 10px 0
width: 100%
box-sizing: border-box
&:valid
border: 3px solid green
&:invalid
border: 3px solid red
编译后的 CSS:
.simple_validation {
padding: 10px;
width: 400px;
box-sizing: border-box;
}
.simple_validation:valid {
background: lightgreen;
}
.simple_validation:invalid {
background: lightcoral;
}
.simple_validation input {
display: block;
margin: 10px 0;
width: 100%;
box-sizing: border-box;
}
.simple_validation input:valid {
border: 3px solid green;
}
.simple_validation input:invalid {
border: 3px solid red;
}
在上面的示例中,您可以检查有效和无效伪类的工作原理。每次将电子邮件输入到电子邮件字符串中,而该字符串不是电子邮件地址时,输入框将具有红色边框,并且表单的背景颜色将更改为浅红色(lightcoral)。在输入数字的情况下也是如此,该数字需要在 5 到 10 的范围内。另外,对于类型为文本的输入,添加了 required 属性。如果没有输入,它具有:invalid伪类。
添加输入状态::focus,:checked,:disabled
焦点伪类与当前接收焦点的输入相关。请记住,用户可以使用鼠标指针和键盘上的 Tab 键来完成此操作。伪类 checked 与输入类型为复选框和单选按钮相关,并匹配状态更改为已选中的元素。为了展示它的确切工作原理,让我们修改我们在上一节中使用的 HTML 代码:
HTML 代码:
<form class="simple_validation">
<input type="number" min="5" max="10" placeholder="Number">
<input type="email" placeholder="Email">
<input type="text" required placeholder="Your name"/>
<input type="checkbox" id="newsletter"></input>
<label for="newsletter">checked</label>
</form>
SASS 代码:
.simple_validation
padding: 10px
width: 400px
box-sizing: border-box
&:valid
background: lightgreen
&:invalid
background: lightcoral
label
display: inline-block
&:before
content: 'Not '
input
display: block
margin: 10px 0
width: 100%
box-sizing: border-box
&:valid
border: 3px solid green
&:invalid
border: 3px solid red
&:focus
background: orange
color: red
border: 3px solid orange
&[type="checkbox"]
display: inline-block
width: 20px
&:checked
& + label
color: red
&:before
content: 'Is '
编译后的 CSS:
.simple_validation {
padding: 10px;
width: 400px;
box-sizing: border-box;
}
.simple_validation:valid {
background: lightgreen;
}
.simple_validation:invalid {
background: lightcoral;
}
.simple_validation label {
display: inline-block;
}
.simple_validation label:before {
content: "Not ";
}
.simple_validation input {
display: block;
margin: 10px 0;
width: 100%;
box-sizing: border-box;
}
.simple_validation input:valid {
border: 3px solid green;
}
.simple_validation input:invalid {
border: 3px solid red;
}
.simple_validation input:focus {
background: orange;
color: red;
border: 3px solid orange;
}
.simple_validation input[type="checkbox"] {
display: inline-block;
width: 20px;
}
.simple_validation input[type="checkbox"]:checked + label {
color: red;
}
.simple_validation input[type="checkbox"]:checked + label:before {
content: "Is ";
}
上面的示例为表单添加了更多的交互性。第一个新功能是将焦点元素的颜色更改为红色,其背景/边框更改为橙色。第二个功能是与复选框相关的交互。在将其状态更改为已选中后,它将更改:before元素(这将在下一节中更好地描述)。在初始化时,:before元素设置为"Not"。使用 HTML 代码完全给出"Not checked"。复选框选中后,before元素更改为"Is",并显示完整字符串等于"Is checked"。
让我们看看在浏览器中它将是什么样子。以下屏幕截图出现在页面的开头:

当复选框被选中时,将出现以下内容:

标签的 before 元素发生了可见的变化,如下面的屏幕截图所示,它还显示了输入的焦点:
添加输入状态::focus,:checked,:disabled
验证后的表单如下:

额外的方面-给占位符着色
是的,当然!您需要为占位符添加样式。您可以这样做,但是需要额外添加前缀:
对于 Internet Explorer:
:-ms-input-placeholder
对于 Firefox:
:-moz-placeholder
对于 WebKit 浏览器:
::-webkit-input-placeholder
使用 CSS 绘制基本图形
绘图原语是图形基础中最简单和主要的情况。在 CSS 中,它可以在常见情况下使用,比如为按钮或任何其他 DOM 元素添加细节。让我们学习在 CSS 中绘制原语的基础知识。
如何画一个矩形/正方形
在 CSS 中最容易绘制的原语是矩形。让我们使用以下代码绘制一个简单的矩形:
HTML 代码:
<div class="rectangle"></div>
SASS 代码:
.rectangle
width: 100px
height: 200px
background: black
编译后的 CSS:
.rectangle {
width: 100px;
height: 200px;
background: black;
}
这将在浏览器中绘制一个矩形,如下所示:

要画一个正方形,我们需要创建以下代码:
HTML 代码:
<div class="square"></div>
SASS 代码:
.square
width: 100px
height: 100px
background: black
编译后的 CSS:
.square {
width: 100px;
height: 100px;
background: black;
}
可重用的混合器用于正方形和矩形:
=rectangle($w, $h, $c)
width: $w
height: $h
background: $c
=square($w, $c)
width: $w
height: $w
background: $c
如何画一个圆
画一个圆非常简单。这种方法是基于边框半径和一个简单的矩形,如下面的例子所示:
HTML 代码:
<div class="circle"></div>
SASS 代码:
.circle
width: 100px
height: 100px
border-radius: 50%
background: black
编译后的 CSS:
.circle {
width: 100px;
height: 100px;
border-radius: 50%;
background: black;
}
在浏览器中,你将看到以下内容:

SASS 混合器:
=circle($size, $color)
width: $size
height: $size
border-radius: 50%
background: $color
如何画一个环
画一个环非常类似于画一个圆。模式是一样的,但是有一个适当的边框。让我们从初始的环标记开始:
HTML 代码:
<div class="ring"></div>
SASS 代码:
.ring
width: 100px
height: 100px
border-radius: 50%
border: 2px solid black
background: none
编译后的 CSS:
.ring {
width: 100px;
height: 100px;
border-radius: 50%;
border: 2px solid black;
background: none;
}
在浏览器中,你将看到以下内容:

SASS 混合器:
=ring($size, $color, $width)
width: $size
height: $size
border-radius: 50%
border: $width solid $color
background: none
如何用 CSS 画一个三角形
画一个三角形是基于边框的一个技巧:
HTML 代码:
<div class="triangle-up"></div><br>
<div class="triangle-down"></div><br>
<div class="triangle-left"></div><br>
<div class="triangle-right"></div>
br元素仅用于在不同行中显示所有元素。
SASS 代码:
.triangle-up
width: 0
height: 0
border-left: 10px solid transparent
border-right: 10px solid transparent
border-bottom: 10px solid black
.triangle-down
width: 0
height: 0
border-left: 10px solid transparent
border-right: 10px solid transparent
border-top: 10px solid black
.triangle-left
width: 0
height: 0
border-top: 10px solid transparent
border-bottom: 10px solid transparent
border-left: 10px solid black
.triangle-right
width: 0
height: 0
border-top: 10px solid transparent
border-bottom: 10px solid transparent
border-right: 10px solid black
编译后的 CSS:
.triangle-up {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-bottom: 10px solid black;
}
.triangle-down {
width: 0;
height: 0;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
border-top: 10px solid black;
}
.triangle-left {
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-left: 10px solid black;
}
.triangle-right {
width: 0;
height: 0;
border-top: 10px solid transparent;
border-bottom: 10px solid transparent;
border-right: 10px solid black;
}
在浏览器中,你将看到以下内容:

SASS 混合器:
=triangleRight($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height/2 0 $height/2 $width
border-color: transparent transparent transparent $color
=triangleLeft($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height/2 $width $height/2 0
border-color: transparent $color transparent transparent
=triangleTop($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: 0 $width/2 $height $width/2
border-color: transparent transparent $color transparent
=triangleBottom($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height $width/2 0 $width/2
border-color: $color transparent transparent transparent
伪元素
使用伪元素真的很重要,可以省略需要特定 HTML 代码的重复代码元素。伪元素的主要目的是减少 HTML 代码中的 DOM 元素。
什么是:before 和:after?
:before和:after是伪元素,你可以添加到 HTML 元素中。一个元素被添加为内联元素到一个选定的元素中。要获得before和after伪元素的基础,你可以绘制如下的 HTML 代码:
<a>Element</a>
并附加以下 SASS 代码:
a
border: 1px solid #000
&:before
content: 'before'
color: orange
&:after
content: 'after'
color: orange
编译后的 CSS:
a {
border: 1px solid #000;
}
a:before {
content: "before";
color: orange;
}
a:after {
content: "after";
color: orange;
}
上述代码的输出如下:

我们在哪里可以使用:before 和:after?
让我们假设一个任务,我们需要为列表中的每个元素添加一些文本。例如,我们有一个如下所示的列表:
<ul>
<li>Mike</li>
<li>Ravi</li>
<li>Adam</li>
<li>Greg</li>
<li>Anna</li>
</ul>
我们需要添加每个人都是前端开发者:
ul
li
&:before
content: "My name is "
color: #f00
&:after
content: ". I'm Front End Developer"
color: #f00
编译后的 CSS:
ul li:before {
content: "My name is ";
color: #f00;
}
ul li:after {
content: ". I'm Front End Developer";
color: #f00;
}
在浏览器中,你将看到以下内容:

让我们使我们之前的代码可重用,并让我们创建一个带有箭头的按钮。HTML 代码将如下所示:
<a href="#">Button</a>
让我们将之前创建的三角形混合器重新用到以下 SASS 代码的最后一行 CSS 代码中:
=triangleRight($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height/2 0 $height/2 $width
border-color: transparent transparent transparent $color
a
display: inline-block
border: 1px solid #000
radius: 5px
padding: 10px 40px 10px 10px
position: relative
text-decoration: none
color: #000
&:after
display: block
position: absolute
right: 10px
top: 50%
margin-top: -5px
content: ''
+triangleRight(10px, 10px, #000)
编译后的 CSS:
a {
display: inline-block;
border: 1px solid #000;
border-radius: 5px;
padding: 10px 40px 10px 10px;
position: relative;
text-decoration: none;
color: #000;
}
a:after {
display: block;
position: absolute;
right: 10px;
top: 50%;
margin-top: -5px;
content: "";
width: 0;
height: 0;
border-style: solid;
border-width: 5px 0 5px 10px;
border-color: transparent transparent transparent #000;
}
这将在浏览器中给我们以下结果:

第一个字母和第一行-简单的文本操作
在网页上,有些情况下,你需要为文本的第一行和文本的第一个字母添加样式。使用 CSS,你必须使用适当的选择器来做到这一点。让我们使用以下 HTML 代码:
<p>Paragraph lorem ipsm Lorem ipsum dolor sit amet, consectetur adipisicing elit. Totam nisi soluta doloribus ducimus repellat dolorum quas atque, tempora quae, incidunt at eius eaque sit, culpa eum ut corporis repudiandae.</p>
在 SASS 文件中:
p
&:first-letter
color: orange
font:
weight: bold
size: 20px
&:first-line
color: pink
编译后的 CSS:
p:first-letter {
color: orange;
font-weight: bold;
font-size: 20px;
}
p:first-line {
color: pink;
}
上述代码将把文本的第一行颜色改为粉色。第一个字母将被改为橙色颜色,粗体,20px大小。
如何改变选择颜色?使用::selection
公司有他们自己的颜色调色板。有时你需要自定义页面上选择的颜色。这可以通过:selection伪元素来实现:
SASS 代码:
::-moz-selection,
::selection
background: red
color: white
编译后的 CSS:
::-moz-selection,
::selection {
background: red;
color: white;
}
使用上述代码,每当你在页面上选择某些内容时,选择的颜色将变为红色,字体颜色将变为白色。
总结
在本章中,您学习了 CSS 代码中伪类、伪元素和基本图形的绘制基础。作为前端开发人员,您将经常使用这些 CSS 元素。伪类为您提供基本的交互性(悬停、激活),并扩展了选择器的可能性(:nth-child、:first-child、:last-child)。通过伪元素,您可以用 CSS 代码扩展 HTML 的可能性(:before、:after、:first-letter、:first-line),并且可以为选择设置样式。
在下一章中,您将获得有关媒体查询的基本知识,这是响应式网站的基础。
第四章:响应式网站-为特定设备准备您的代码
在这一章中,您将了解响应式网页设计(RWD)以及如何准备项目。它将涵盖现代网站的问题和优化技术。这一章将是关于媒体查询的知识基础-如何准备它们以及如何调整特定设备。
在这一章中,我们将涵盖以下主题:
-
RWD 方法
-
使用媒体查询
响应式网站的基础
几乎所有现代网站都可以在桌面和移动设备(手机、平板电脑)上显示。正确调整 CSS 和 HTML 代码是创建响应式网站的主要假设。基本的响应式网站构建过程是基于代码的调整,一旦完成,网站就可以在所有设备上正确显示。现在,响应式网站的响应性稍微增强了。它不仅是创建 CSS/HTML/JS 代码和考虑设计方面,还要考虑移动设备上的性能。带有 Web 浏览器的移动设备现在是人们浏览网站的主要设备。让我们看看创建响应式网站的主要方法。
桌面优先方法
这种方法曾经是 CSS 框架中的主要方法。HTML 和 CSS 代码的主要目的是在桌面浏览器中查看网页。然后提供基于桌面代码的移动版本。最后的过程是调整移动设备的代码。它看起来像是削减网站的功能,并调整桌面视图以适应较小的移动设备。
移动优先方法
这种方法在所有现代 CSS 框架(Twitter bootstrap,Foundation framework)中都有使用。首先,代码是为移动设备准备的,然后再为较大的设备(从平板电脑到台式电脑屏幕)进行缩放。这种方法现在更为常见,也更好,因为移动设备的代码不必像在桌面优先方法中那样是 CSS 技巧、HTML 重复和 JS 机制的组合。
哪种方法适合您?这完全取决于项目类型。并非在所有情况下您都是从头开始制作项目。有时,您有一些旧代码,需要调整到移动设备上。在这种情况下,您总是被迫使用桌面优先方法。在可以从头开始编写代码的情况下,建议使用移动优先方法。
在 HTML 中调整视口
响应式网站的一个重要元素是正确的 HTML 视口 meta 标签。视口描述应该添加在 HTML 文档的头部。它描述了网页在移动设备上的行为方式。有一堆大多数使用的视口,我们稍后会进行分析。最常用的是以下视口:
<head>
<!-- ... -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- ... -->
</head>
这意味着无论何时在移动设备上打开项目,它都将具有设备的宽度,并且项目将具有等于1的初始比例。稍微增强的视口看起来像下面这样:
<head>
<!-- ... -->
<meta name="viewport"content="width=device-width, initial-scale=2.0">
<!-- ... -->
</head>
第一个和第二个视口之间的主要区别是最大缩放。这意味着在移动设备上双击或捏合手势后,将进行缩放,但此缩放的最大范围设置为2。视口的一个更安全的选项如下:
<head>
<!-- ... -->
<meta name="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=1">
<!-- ... -->
</head>
为什么更安全?例如,在某些情况下,我们在内容上有一些固定的窗口,它们也不会被缩放,也不会给用户带来不好的体验:
<head>
<!-- ... -->
<meta name="viewport"content="width=600, initial-scale=1.0">
<!-- ... -->
</head>
这个viewport设置将缩放网站,使其表现得像在桌面上打开的网页,浏览器的宽度设置为600。初始比例设置如前面的例子一样,等于1。
选择正确的视口
所以问题是:推荐使用哪个viewport?这是一个很好的问题。最好的体验可以通过以下方式保留:
<head>
<!-- ... -->
<meta name="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=2.0">
<!-- ... -->
</head>
为什么?因为我们正在根据设备的宽度进行缩放,而且我们不会停止页面的缩放。但最安全的选择如下:
<head>
<!-- ... -->
<meta name="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=1">
<!-- ... -->
</head>
这将防止缩放,这可能会让调整变得很烦人,特别是在旧项目中,我们有老式的模态窗口类型。
折叠区域之上
这种方法与代码的优化密切相关。它也与网页的移动版和桌面版相关。现代网页加载了很多东西:CSS 文件、JS 文件、图片以及视频和音频等媒体文件。在这么长的队列中,你会发现当页面加载的处理时间,比如说 10 秒,你无法在所有文件加载完之前看到内容。在信息页面的情况下,你应该先看到标题和主要内容,但在这么长的队列中几乎是不可能的。
上述的折叠方法将特定的样式附件分开,描述页面上最重要的元素,比如标题、副标题和文本内容。需要将这些style附件分开,并将它们内联到head部分,例如:
<head>
<!-- ... -->
<style>
/* here we have a section for inline most important styles */
</style>
<!-- ... -->
<link rel="stylesheet"type="text/css"href="link_to_rest_of_styles.css">
<!-- ... -->
</head>
这意味着这个内联部分将首先被浏览器解析,在长时间的加载过程中,它将首先为读者准备好最重要的元素,然后再加载页面所需的其他资源。
媒体查询 - 你可以在哪里使用它
媒体查询是在 CSS 代码中设置的过滤器,有助于描述网站在各种显示器(屏幕、打印)上的显示。在媒体查询中,最常用的过滤器是最小/最大宽度、最小/最大高度、最小/最大像素比和最小/最大宽高比。
如何构建媒体查询
首先创建一个媒体查询,然后创建更复杂的过滤器是相当简单的。基本的媒体查询看起来如下:
@media screen and (min-width: 640px)
.element
background: #000
编译后的 CSS:
@media screen and (min-width: 640px) {
.element {
background: #000;
}
}
通过这个媒体查询,你可以过滤出所有最小宽度为 640px 的屏幕的 CSS 声明。让我们试着让它更复杂一些,让我们尝试为特定设备创建更多的媒体查询。
媒体查询是如何工作的?
媒体查询是过滤器,如前所述。但让我们试着在代码和浏览器中看看。这个简单的章节将向你展示如何调整代码以适应特定的屏幕分辨率,并为创建更高级的媒体查询奠定基础:
<div class="mobile_only">Mobile only</div>
<div class="tablet_only">Tablet only</div>
<div class="desktop_only">Desktop only</div>
<div class="mobile_and_tablet">Mobile and tablet</div>
<div class="tablet_and_desktop">Tablet and desktop</div>
<div class="all">All views</div>
现在代码看起来如下(没有任何样式):

现在我们需要做一些方法:
-
移动视图是宽度小于等于 400px 的所有分辨率
-
平板视图是宽度小于等于 700px 的所有分辨率
-
桌面视图是宽度大于 701px 的所有分辨率
现在,基于上述方法,让我们创建样式和媒体查询:
编译后的 CSS:
.mobile_only,
.tablet_only,
.desktop_only,
.mobile_and_tablet,
.tablet_and_desktop {
display: none;
}
/* Mobile only */
@media screen and (max-width: 400px) {
body {
background: red;
}
.mobile_only {
display: block;
}
}
/* Mobile and tablet */
@media screen and (max-width: 700px) {
.mobile_and_tablet {
display: block;
}
}
/* Tablet only */
@media screen and (min-width: 401px) and (max-width: 700px) {
body {
background: blue;
}
.tablet_only {
display: block;
}
}
/* Tablet and desktop */
@media screen and (min-width: 401px) {
.tablet_and_desktop {
display: block;
}
}
/* Desktop only */
@media screen and (min-width: 701px) {
body {
background: green;
}
.desktop_only {
display: block;
}
}
现在让我们在宽度为 350px 的浏览器中检查一下:

在上述视图中,我们可以看到所有在 CSS 文件中描述的元素,带有以下注释:
-
/* 仅限移动设备 */ -
/* 移动和平板 */
在宽度为 550px 的浏览器中的输出如下:

在上述视图中,我们可以看到所有在 CSS 文件中描述的元素,带有以下注释:
-
/* 仅限平板 */ -
/* 移动和平板 */ -
/* 平板电脑和台式机 */
在宽度为 850px 的浏览器中的输出如下:

在上述视图中,我们可以看到所有在 CSS 文件中描述的元素,带有以下注释:
-
/* 平板和台式机 */ -
/* 仅限桌面 */
前面的代码揭示了媒体查询过滤器的工作原理。你如何创建一个在特定视图中可见的代码,以及如何为真实项目创建方法?在接下来的项目中,我们将研究可以过滤的内容,因为媒体查询不仅仅与设备的宽度有关。让我们开始吧!
特定视图/设备的媒体查询
媒体查询可以在许多不同的情况下使用。如前所述,我们可以使用媒体查询来设置特定的最小和最大宽度:
@media screen and (min-width: 640px)
@media screen and (max-width: 640px)
在前面的媒体查询中,第一个例子是所有最小宽度为640像素的分辨率,第二个例子是所有最大宽度为640像素的分辨率。前端开发人员处理基本桌面和像素密度更大的屏幕上的像素比。如何用 CSS 过滤它们?让我们来看看这个媒体查询:
@media (-webkit-min-device-pixel-ratio: 2)
正如我们所知,视网膜设备的像素比等于2。我们还可以用范围构建更复杂的过滤器:
@media screen and (min-width: 640px) and (max-width: 1024px)
在这种情况下,我们正在过滤所有宽度匹配从640像素到1024像素的分辨率。但是我们如何编写一个媒体查询过滤器,以匹配一些特定的设备呢?假设我们想为具有视网膜显示屏的新一代 iPad 编写代码:
@media only screen
and (min-device-width: 768px)
and (max-device-width: 1024px)
and (-webkit-min-device-pixel-ratio: 2)
正如我们所知,移动设备有两种方向:横向和纵向。那么我们如何在媒体查询中匹配这种情况呢?对于纵向视图,请使用以下内容:
@media only screen
and (min-device-width: 768px)
and (max-device-width: 1024px)
and (orientation: portrait)
and (-webkit-min-device-pixel-ratio: 2)
而对于横向视图,请使用以下内容:
@media only screen
and (min-device-width: 768px)
and (max-device-width: 1024px)
and (orientation: landscape)
and (-webkit-min-device-pixel-ratio: 1)
通过媒体查询,您还可以过滤打印视图。为此,您需要附加以下代码:
@media print
如何为移动设备选择合适的媒体查询
为了创建良好的媒体查询过滤器并在其中设置良好的范围,您首先必须选择设备和分辨率。然后,您必须根据最流行的分辨率创建适当的媒体查询。回到过去,设备和标准分辨率的范围较小。因此,主要设置如下:
@media (max-width: 768px)
// Cover small devices
.element
font-size: 12px
@media (min-width: 768px) and (max-width: 1024px)
// Cover medium devices
.element
font-size: 14px
@media (min-width: 1024px)
// Cover large devices
.element
font-size: 16px
编译后的 CSS:
@media (max-width: 768px) {
.element {
font-size: 12px;
}
}
@media (min-width: 768px) and (max-width: 1024px) {
.element {
font-size: 14px;
}
}
@media (min-width: 1024px) {
.element {
font-size: 16px;
}
}
当然,在每个项目中,您可以为异常情况添加一些特定的媒体查询,这样在质量分析过程之后,CSS 文件中可能会出现更多的过滤器。
如今,一种方法是在一个媒体查询步骤中覆盖尽可能多的设备:
@media only screen
.element
font-size: 16px
@media only screen and (max-width: 640px)
// Cover small devices
.element
font-size: 12px
@media only screen and (min-width: 641px)
// Cover devices which resolution is at minimum medium
.element
font-size: 14px
@media only screen and (min-width: 641px) and (max-width: 1024px)
// Cover medium devices
.element
font-size: 15px
@media only screen and (min-width: 1025px)
// Cover devices which resolution is at minimum large
.element
font-size: 16px
编译后的 CSS:
@media only screen {
.element {
font-size: 16px;
}
}
@media only screen and (max-width: 640px) {
.element {
font-size: 12px;
}
}
@media only screen and (min-width: 641px) {
.element {
font-size: 14px;
}
}
@media only screen and (min-width: 641px) and (max-width: 1024px) {
.element {
font-size: 15px;
}
}
@media only screen and (min-width: 1025px) {
.element {
font-size: 16px;
}
}
为了更好地覆盖和更好地编写代码,让我们在这个媒体查询列表中添加一个max-width步骤:
@media only screen and (max-width: 1024px)
.element
font-size: 15px
编译后的 CSS:
@media only screen and (min-width: 1025px) {
.element {
font-size: 16px;
}
}
这个媒体查询将一次覆盖小型和中型设备。目前,桌面网站最常见的分辨率是1280px。让我们将这个范围添加到媒体查询中:
@media only screen and (min-width: 1025px) and (max-width: 1280px) {}
@media only screen and (min-width: 1281px) {}
用于媒体查询的 SASS mixin
让我们为 mixin 创建媒体查询,这将帮助我们保持代码清晰。正如我们所知,我们必须将显示类型和断点作为参数添加进去:
@mixin mq($display, $breakpoint)
@media #{$display} and (#{$breakpoint})
@content
现在让我们收集我们的标准断点:
@mixin mq($display, $breakpoint)
@media #{$display} and #{$breakpoint}
@content
$mq_small_only: "(max-width: 640px)"
$mq_medium_only: "(min-width: 641px) and (max-width: 1024px)"
$mq_small_and_medium: "(max-width: 1024px)"
+mq("screen", $mq_small_only)
.slider
width: 100%
height: 300px
+mq("screen", $mq_medium_only)
.slider
width: 100%
height: 400px
+mq("screen", $mq_small_and_medium)
.slider
max-width: 1200px
width: 100%
编译后的 CSS:
@media screen and (max-width: 640px) {
.slider {
width: 100%;
height: 300px;
}
}
@media screen and (min-width: 641px) and (max-width: 1024px) {
.slider {
width: 100%;
height: 400px;
}
}
@media screen and (max-width: 1024px) {
.slider {
max-width: 1200px;
width: 100%;
}
}
前面的代码是三个步骤的选择,但您可以添加另一个作为练习,以覆盖上一节中的所有步骤。
用法示例-主导航
让我们想象一下,我们想解决与导航相关的经典问题。在大多数情况下,它在桌面视图中是内联的,但在移动视图中变成了元素下的列表元素。让我们从 HTML 开始:
<nav class="main-navigation">
<ul>
<li>
<a href="#">First element</a>
</li>
<li>
<a href="#">Second element</a>
</li>
<li>
<a href="#"> Third element</a>
</li>
</ul>
</nav>
在 SASS 代码中,我们将使用之前创建的 mixin 来进行媒体查询和清除浮动。以下是完整的 SASS 文件:
@mixin mq($display, $breakpoint)
@media #{$display} and #{$breakpoint}
@content
$mq_small_only: "(max-width: 640px)"
$mq_medium_only: "(min-width: 641px) and (max-width: 1024px)"
$mq_small_and_medium: "(max-width: 1024px)"
=clear fix
&:after
content: " "
visibility: hidden
display: block
height: 0
clear: both
body
padding: 0
margin: 0
.main-navigation
ul
+clearfix /* This will prevent problems of cleared float */
list-style: none
padding: 0
background: greenyellow
border:
bottom: 1px solid darkgreen
li
float: left
display: block
a
padding: 10px
width: 100%
display: block
background: greenyellow
text-decoration: none
color: darkgreen
&:hover
background: darkgreen
color: greenyellow
+mq("screen", $mq_small_and_medium)
.main-navigation
ul
list-style: none
border: none
li
float: none
width: 100%
a
border:
bottom: 1px solid darkgreen
编译后的 CSS:
body {
padding: 0;
margin: 0;
}
.main-navigation ul {
list-style: none;
padding: 0;
background: greenyellow;
border-bottom: 1px solid darkgreen;
}
.main-navigation ul:after {
content: "";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
.main-navigation li {
float: left;
display: block;
}
.main-navigation a {
padding: 10px;
width: 100%;
display: block;
background: greenyellow;
text-decoration: none;
color: darkgreen;
}
.main-navigation a:hover {
background: darkgreen;
color: greenyellow;
}
@media screen and (max-width: 1024px) {
.main-navigation ul {
list-style: none;
border: none;
}
.main-navigation li {
float: none;
width: 100%;
}
.main-navigation a {
border-bottom: 1px solid darkgreen;
}
}

前面的屏幕截图是在全局 CSS 相关的桌面视图中制作的。下一个屏幕截图与@media屏幕和(最大宽度:1024px)有关。正如你所看到的,我们改变了导航的显示方式,并为触摸设备提供了更多的灵活性。导航中的较大项目更容易点击(在这个例子中,按钮更长):

总结
在本章中,您学习了创建响应式网站的主要方法以及移动和桌面优先的含义。然后,我们通过响应式网站的性能基础知识扩展了知识。最后,您了解了媒体查询的基本知识以及如何创建它们以覆盖所有特定的显示类型。在下一章中,您将学习有关 CSS 代码中的图像的知识。
在下一章中,您还将学习有关 CSS 背景和可以使用的新功能的知识。我们将重复图像,裁剪图像,并将它们定位到容器中。让我们看看我们可以用背景做些什么。
第五章:在 CSS 中使用背景图像
几乎所有页面上都有背景图像。本章将描述如何在现代设备的广泛范围上正确显示图像,包括手机和平板电脑。
在本章中,我们将涵盖以下主题:
-
使用背景图像
-
如何为背景图像设置正确的位置
-
如何设置背景位置的大小
-
视网膜和移动设备上的图像
CSS 背景
CSS 背景在现代 Web 浏览器中非常有用。何时应该使用背景,何时应该使用img标签?这是一个简单的问题 - 每个作为内容元素的图像都应插入到img标签中,每个作为布局元素的图像都应移动到 CSS 背景中。
在本章中,我们将尝试始终使用相同的图像来说明每个属性和值的工作原理。这个图像将是一个有边框的圆,肯定会显示正确的纵横比(如果它不好,它看起来更像省略号),并且有了边框,您可以检查图像的重复工作。图像的宽度和高度都等于 90 像素。

背景重复
在处理背景时有许多可用选项。第一个是图像重复。默认值是在x和y轴上重复图像。因此,当您设置,例如:
Background-image: url(/* here url to your img*/)
我们的 SASS 示例:
.container
width: 1000px
height: 500px
border: 3px solid red
background-image: url(image.jpg)
编译的 CSS:
.container {
width: 1000px;
height: 500px;
border: 3px solid red;
background-image: url(image.jpg);
}
对于所有容器,边框都是红色的,以便更好地查看容器的范围。
HTML:
<body>
<div class="container">
</div>
</body>
此代码将给我们带来以下视图:

对于所有容器,边框都是红色的,以便更好地查看容器的范围。这意味着图像在背景中在x和y轴上重复。让我们添加以下代码并检查它将如何编译以及对我们的视图会产生什么影响:
.container
width: 1000px
height: 500px
border: 3px solid red
background:
image: url(image.jpg)
repeat: repeat
编译的 CSS:
.container {
width: 1000px;
height: 500px;
border: 3px solid red;
background-image: url(image.jpg);
background-repeat: repeat;
}
我们可以使用background-repeat的另一个选项和行为:
-
- repeat-x:这将重复背景x轴![背景重复]()
-
- repeat-y:这将重复背景y轴
![背景重复]()
- repeat-y:这将重复背景y轴
-
- no-repeat:这将不会重复背景![背景重复]()
背景大小
使用新的 CSS 功能,可以设置背景大小。大小可以设置如下:
background-size: 30px 50px
让我们获取先前的 HTML 代码并附加新的 SASS 代码:
.container
width: 1000px
height: 500px
border: 3px solid red
background:
image: url(image.jpg)
repeat: repeat
size: 30px 50px
编译的 CSS:
.container {
width: 1000px;
height: 500px;
border: 3px solid red;
background-image: url(image.jpg);
background-repeat: repeat;
background-size: 30px 50px;
}
此代码的输出将如下所示:

如果我们想要为图像设置容器的完整宽度,并自动计算其高度以保持图像的纵横比,执行以下操作:
background-size: 100% auto

当然,我们可以将fill选项从x轴更改为y轴。让我们将100%的值更改为height,将width更改为auto:
.container
width: 1000px
height: 500px
border: 3px solid red
background:
image: url(image.jpg)
repeat: repeat
size: 100% auto
编译为:
.container {
width: 1000px;
height: 500px;
border: 3px solid red;
background-image: url(image.jpg);
background-repeat: repeat;
background-size: 100% auto;
}
输出将如下所示:

contain值将更改其宽度和高度以包含容器。使用此选项,纵横比将得到保持:
background-size: contain
cover值将更改其宽度和高度以覆盖容器。使用此选项,纵横比将得到保持:
background-size: cover
背景位置
在大多数设计中,您将需要设置背景在框中的位置。可以使用 CSS 设置背景位置如下:
background-position: top left

background-position: right

如果要使背景在两个轴上居中,执行以下操作:
background-position: center center

如果要将背景对齐到右下角,请执行以下操作:
background-position: bottom right

要设置背景偏移量(以像素为单位),请执行以下操作:
background-position: 600px 200px

多重背景
在过去,使用多个背景与添加具有单独背景的新 DOM 元素相关联。所有这些元素将绝对定位在相对容器中。如今,我们可以在一个容器中使用 CSS 使用多个背景,而无需任何额外的 HTML 代码。
让我们使用相同的 HTML 代码和相同的图像,然后将这个图像定位在容器中的以下位置:
-
顶部左侧
-
顶部中心
-
顶部右侧
-
左侧中心
-
中心中心
-
右侧中心
-
底部左侧
-
底部中心
-
底部右侧
CSS 代码:
.container {
width: 1000px;
height: 500px;
border: 3px solid red;
background-image:
url(image.jpg), /* URL of image #1 */
url(image.jpg), /* URL of image #2 */
url(image.jpg), /* URL of image #3 */
url(image.jpg), /* URL of image #4 */
url(image.jpg), /* URL of image #5 */
url(image.jpg), /* URL of image #6 */
url(image.jpg), /* URL of image #7 */
url(image.jpg), /* URL of image #8 */
url(image.jpg); /* URL of image #9 */
background-repeat: no-repeat;
background-position:
left top, /* position of image #1 */
center top, /* position of image #2 */
right top, /* position of image # 3*/
left center, /* position of image #4 */
center center, /* position of image #5 */
right center, /* position of image #6 */
bottom left, /* position of image #7 */
bottom center, /* position of image #8 */
bottom right; /* position of image #1 */
background-size:
50px auto, /* size of image #1 */
auto auto, /* size of image #2 */
auto auto, /* size of image #3 */
auto auto, /* size of image #4 */
200px auto, /* size of image #5 */
auto auto, /* size of image #6 */
auto auto, /* size of image #7 */
auto auto, /* size of image #8 */
50px auto; /* size of image #9 */
}
现在,让我们在 SASS 中描述它:
.container
width: 1000px
height: 500px
border: 3px solid red
background:
image: url(image.jpg), url(image.jpg), url(image.jpg), url(image.jpg), url(image.jpg),url(image.jpg), url(image.jpg), url(image.jpg), url(image.jpg)
repeat: no-repeat
position: left top, center top, right top, left center, center center, right center, bottom left, bottom center, bottom right
size: 50px auto, auto auto, auto auto, auto auto, 200px auto, auto auto, auto auto, auto auto, 50px auto
最终视图将如下所示:

如何创建和使用精灵
什么是精灵?精灵是一种带有图像的图像。但是你如何在你的代码中使用它,为什么应该在你的 CSS 中使用它?因为它可以使你的网站更快,而且创建起来相当简单。让我们来看看下面的图片:

这是一个具有在x和y轴上设置偏移的基本精灵。那么我们如何从这个大图像中提取IMG 3?
.image3
display: inline-block
width: 100px
height: 100px
background:
image: url(image.jpg)
repeat: no-repeat
position: -200px 0
编译后的 CSS:
.image3 {
display: inline-block;
width: 100px;
height: 100px;
background-image: url(image.jpg);
background-repeat: no-repeat;
background-position: -200px 0;
}
为了更好地理解精灵网格,让我们拿着名为IMG 6的对象:
.image6
display: inline-block
width: 100px
height: 100px
background:
image: url(image.jpg)
repeat: no-repeat
position: -200px -100px
编译后:
.image6 {
display: inline-block;
width: 100px;
height: 100px;
background-image: url(image.jpg);
background-repeat: no-repeat;
background-position: -200px -100px;
}
好的。但是创建精灵非常无聊和耗时。这个过程如何自动化?使用 Compass 非常容易。我们只需要将所有图像收集到一个名为newsprite的文件夹中。精灵的最佳格式是 PNG,以保持适当的透明度。假设我们在这个文件夹中有以下三个 PNG 文件:
-
circle-blue.png -
circle-red.png -
circle-white.png
图像将如下所示:

现在我们需要对我们的自动化工具进行一些改变:
var gulp = require('gulp'),
compass = require('gulp-compass');
gulp.task('compass', function () {
return gulp.src('src/styles/main.sass')
.pipe(compass({
sass: 'src/styles',
image: 'src/images',
css: 'dist/css',
generated_images_path: 'dist/images',
sourcemap: true,
style: 'compressed'
}))
.on('error', function(err) {
console.log(err);
});
});
gulp.task('default', function () {
gulp.watch('src/styles/**/*.sass', ['compass']);
gulp.watch('src/images/**/*', ['compass']);
});
我们改变了以下定义图像目标的行:
generated_images_path: 'dist/images'
现在我们需要在compass中添加一个代码来运行精灵创建器:
@import "compass"
@import "newsprite/*.png"
@include all-newsprite-sprites(true)
在上述代码的第一行,我们正在导入compass库。在第二行,我们正在将我们的图像映射为sprites。在第三行,我们正在导入一个带有sprites的文件夹。括号中的值在编译后的 CSS 代码中给出了类的尺寸。现在让我们分析编译后的 CSS:
.newsprite-sprite,
.newsprite-circle-blue,
.newsprite-circle-red,
.newsprite-circle-white {
background-image: url('../images/newsprite-s70c66611b2.png');
background-repeat: no-repeat
}
.newsprite-circle-blue {
background-position: 0 0;
height: 90px;
width: 90px
}
.newsprite-circle-red {
background-position: 0 -90px;
height: 90px;
width: 90px
}
.newsprite-circle-white {
background-position: 0 -180px;
height: 90px;
width: 90px
}
如您所见,生成的代码与文件结构和名称相关,例如:
.newsprite-circle-red
其中:
-
newsprite: 这是一个文件夹/精灵名称 -
circle-white: 这是文件名
Compass 正在为生成的精灵图像添加前缀,例如:
background-image: url('../images/newsprite-s70c66611b2.png');
和生成的文件:

现在让我们稍微改变一下代码,让我们使用 sprite-map。首先,我们需要创建 HTML 代码,最终在浏览器中看到效果:
<div class="element-circle-white"></div>
<div class="element-circle-red"></div>
<div class="element-circle-blue"></div>
然后在 SASS 文件中:
@import "compass/utilities/sprites"
$circles: sprite-map("newsprite/*.png", $spacing: 2px, $layout: diagonal)
.element-circle-blue
background-image: sprite-url($circles)
background-position: sprite-position($circles, circle-blue)
@include sprite-dimensions($circles, circle-blue)
.element-circle-red
background-image: sprite-url($circles)
background-position: sprite-position($circles, circle-red)
@include sprite-dimensions($circles, circle-red)
.element-circle-white
background-image: sprite-url($circles)
background-position: sprite-position($circles, circle-white)
@include sprite-dimensions($circles, circle-white)
.element-circle-blue,
.element-circle-red,
.element-circle-white
float: left
生成的 CSS:
.element-circle-blue {
background-image: url('../images/newsprite-s31a73c8e82.png');
background-position: 0 -180px;
height: 90px;
width: 90px
}
.element-circle-red {
background-image: url('../images/newsprite-s31a73c8e82.png');
background-position: -90px -90px;
height: 90px;
width: 90px
}
.element-circle-white {
background-image: url('../images/newsprite-s31a73c8e82.png');
background-position: -180px 0;
height: 90px;
width: 90px
}
.element-circle-blue, .element-circle-red, .element-circle-white {
float: left
}
在上述代码中,我们没有像之前那样添加所有带有它们尺寸的类。当你不想添加很多未使用的代码时,这一点很重要。现在我们只使用了需要的sprite部分。让我们深入分析一下:
$circles: sprite-map("newsprite/*.png", $spacing: 2px, $layout: diagonal)
这行代码定义了我们的图像(即@import "newsprite/*.png")。第二个参数定义了sprite中图像之间的间距($spacing: 2px);在这种情况下是2px。最后一个参数定义了layout样式。在这种情况下,sprite中的图像将如下所示:

有了这个参数,我们可以使用以下值:
-
垂直:精灵的元素将放置在一个垂直线上
-
水平:精灵的元素将放置在一条水平线上
-
对角线:精灵的元素将放置在对角线上
-
智能:元素将被调整为尽可能小的区域
让我们分析代码的下一部分:
background-image: sprite-url($circles)
background-position: sprite-position($circles, circle-red)
@include sprite-dimensions($circles, circle-red)
在上述代码的第一行,我们得到了$circle变量,其定义如下:
$circles: sprite-map("newsprite/*.png", $spacing: 2px, $layout: diagonal)
这一行添加了背景图像。第二行是获取名为circle-red的图像在$circle变量(sprite)中的位置。最后一行包括了这个类中circle-red的宽度和高度。
在浏览器中,我们可以看到以下视图:

base64 的用法
这是一种与页面加载优化和请求最小化紧密相关的技术。从概念上讲,优化与尽可能减少请求数量有关。所以让我们假设我们有 10 个需要在页面上加载的图像背景。第一个请求是用于 CSS,接下来的 10 个请求发送到服务器是用于图像。但是我们怎样才能在一个请求中完成呢?我们可以使用base64编码。
让我们从理论上看一下它是什么样子的:
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
这是我们对图像进行编码的主要方法。最终,它看起来像这样:
background-image: url(data:image/gif;base64,<encoded data>)
嘿!但是我怎么把我的图像改成编码数据呢?这是一个很好的问题。打开你的终端,尝试使用以下命令:
openssl base64 -in <imgfile> -out <outputfile>
完成这个操作后,你需要做的就是将输出文件内容从前一个命令的<encode data>复制过来。
视网膜问题
视网膜是高分辨率显示器。这种显示器唯一的问题是如何将设备的宽度和高度加倍,然后压缩到保持容器中。这听起来很容易。最简单的方法是将尽可能多的元素移动到字体和 HTML 元素/伪元素中。但我们如何处理 CSS 中的背景图像呢?
让我们从基础知识开始。对于普通屏幕,我们需要具有标准尺寸的图像。图像的宽度和高度都等于 90 像素。
HTML:
<div class="element"></div>
SASS:
.element
background:
image: url(img/circle-blue.png)
repeat: no-repeat
width: 90px
height: 90px
编译后的 CSS:
.element {
background-image: url(img/circle-blue.png);
background-repeat: no-repeat;
width: 90px;
height: 90px;
}
如果我们想要在视网膜显示器上正确显示这个图像,我们需要改变一下代码。这个改变与视网膜显示器的密度有关。视网膜显示器的像素比是等于2的。我们需要改变的只是元素的宽度和高度,并调整这个框中的背景图像:
.element
background:
image: url(img/circle-blue.png)
repeat: no-repeat
size: 50% 50%
width: 45px
height: 45px
编译后的 CSS:
.element {
background-image: url(img/circle-blue.png);
background-repeat: no-repeat;
background-size: 50% 50%;
width: 45px;
height: 45px;
}
现在.element已经准备好在视网膜显示器上以正确的质量显示。但它会比需要的大小小两倍。在这种情况下,我们需要做的就是从更大的分辨率的图像开始。例如,设计是为浏览器准备的,在浏览器中,主包装器的宽度应该是 1000 像素;所以你应该要求设计师将这个包装器的宽度设计为 200 像素。在更大的设计中,你正在切割需要在视网膜显示器上需要的切片。然后你应该为标准密度切割图像。你可以只留下视网膜图像,但这可能会影响性能,因为更大的图像将始终在浏览器中下载。为了避免这个问题,最好添加一个适当的媒体查询。在描述的例子中,我们在视网膜显示器的情况下全局添加文件的普通版本(img/circle-blue.png),这是由媒体查询识别的,因此将加载两倍大的图像(img/circle-blue@2x.png)。
.element
background:
image: url(img/circle-blue.png)
repeat: no-repeat
width: 45px
height: 45px
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi)
.element
background:
image: url(img/circle-blue@2x.png)
repeat: no-repeat
size: 50% 50%
width: 45px
height: 45px
编译后的 CSS:
.element {
background-image: url(img/circle-blue.png);
background-repeat: no-repeat;
width: 45px;
height: 45px;
}
@media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
.element {
background-image: url(img/circle-blue@2x.png);
background-repeat: no-repeat;
background-size: 50% 50%;
width: 45px;
height: 45px;
}
}
接下来是代码的一部分:
background-size: 50% 50%
这部分代码可以与以下内容交换:
background-size: contain
在这种情况下,图像将调整到添加背景的框的宽度和高度。
总结
在这一章中,你获得了关于背景图像的基本知识。你还学会了如何定位背景图像,设置它们的大小,以及如何通过sprites和base64编码解决主要性能问题。
在下一章中,你将获得关于表单样式的基本知识。你还将深入了解如何用 CSS 代码处理输入。
第六章:样式化表单
样式化表单是最具挑战性的任务之一,特别是当表单需要在桌面和移动设备上创建时。为什么?
在本章中,我们将涵盖以下主题:
-
如何为简单样式创建良好的结构
-
使用表单选择器
-
如何样式化表单
-
在表单中 CSS 的可能和不可能
表单-最常见的问题
你认识任何一个没有在 HTML/CSS 中构建过任何表单的前端开发人员吗?你认识任何一个喜欢做这项工作的人吗?是的...调整它并不简单,但你需要学会理解你可以用 HTML/CSS 做什么,以及在哪里需要使用 JavaScript 代码来使其更容易甚至可能。
最常见的限制如下:
-
因为输入框没有内容,所以不能使用伪元素
:before和:after(:before和:after出现在内容之前或之后) -
全局输入样式的使用并不好,因为有很多类型的输入(文本、密码、提交)
-
在所选框中显示元素的样式化根本不可能(有时更容易使用一些 JavaScript 插件来启用额外的结构,这样更容易进行样式化)
表单-启用超级功能
如前所述,在输入框中,无法使用:before和:after伪元素。但是有一个快速的技巧可以做到这一点,这将在接下来的章节中更好地描述,那就是将其包装在其他元素中。这总是有助于保持一些标签和输入组,并另外允许附加:before和:after伪元素。
例如,采用以下简单的 HTML 表单代码:
<form>
<input type="text" placeholder="Login"/>
<input type="password" placeholder="Password"/>
</form>
现在你只需要添加包装元素:
<form>
<div class="inputKeeper">
<input type="text" placeholder="Login"/>
</div>
<div class="inputKeeper">
<input type="password" placeholder="Password"/>
</div>
</form>
有什么不同?很容易看出来。第一个表单输出如下:

第二个表单如下:

如何样式化简单输入
输入样式基于选择器<input> <select> <textarea>。但是<input>类型存在问题。它将收集所有类型:
<input type="text">
<input type="submit">
<input type="password">
<input type="checkbox">
对于密码输入:
input[type="password"]
For submit input:
input[type="submit"]
让我们将这些输入整合到一个在网站上最常见的登录表单中。
HTML 代码:
<form>
<input type="text" placeholder="login"/>
<input type="password" placeholder="password"/>
<input type="submit" />
</form>
在浏览器中,它将如下所示:

让我们稍微改变结构,用包装的 div:
<form>
<div class="loginWrapper">
<input type="text" placeholder="login"/>
</div>
<div class="passwordWrapper">
<input type="password" placeholder="password"/>
</div>
<div class="submitWrapper">
<input type="submit" />
</div>
</form>
现在我们有了一个基本代码来开始样式化:

现在我们可以开始创建样式:
SASS:
*
box-sizing: border-box
form
width: 300px
input
margin-bottom: 5px
width: 100%
input[type="text"]
border: 2px solid blue
input[type="password"]
border: 2px solid green
input[type="submit"]
background: #000
color: #fff
width: 100%
生成的 CSS:
* {
box-sizing: border-box;
}
form {
width: 300px;
}
input {
margin-bottom: 5px;
width: 100%;
}
input[type="text"] {
border: 2px solid blue;
}
input[type="password"] {
border: 2px solid green;
}
input[type="submit"] {
background: #000;
color: #fff;
width: 100%;
}
现在,在了解了正确的选择器并添加了基本的 CSS 之后,我们的表单看起来像这样:

让我们看看提交按钮。我们需要去掉它的边框。在这个迭代中,让我们添加一些伪元素。让我们更新我们的 SASS 代码如下:
=ring($size, $color, $width)
width: $size
height: $size
border-radius: 50%
border: $width solid $color
background: none
=triangleRight($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height/2 0 $height/2 $width
border-color: transparent transparent transparent $color
*
box-sizing: border-box
form
width: 300px
input
margin-bottom: 5px
width: 100%
input[type="text"]
border: 2px solid blue
input[type="password"]
border: 2px solid green
input[type="submit"]
background: #000
color: #fff
width: 100%
.loginWrapper,
.passwordWrapper,
.submitWrapper
position: relative
&:after
content: ''
display: inline-block
position: absolute
top: 50%
right: 10px
.loginWrapper,
.passwordWrapper
&:after
margin-top: -6px
right: 10px
+ring(4px, #000, 2px)
.submitWrapper
&:after
margin-top: -3px
right: 10px
+triangleRight(6px, 6px, #fff)
生成的 CSS:
* {
box-sizing: border-box;
}
form {
width: 300px;
}
input {
margin-bottom: 5px;
width: 100%;
}
input[type="text"] {
border: 2px solid blue;
}
input[type="password"] {
border: 2px solid green;
}
input[type="submit"] {
background: #000;
color: #fff;
width: 100%;
}
.loginWrapper,
.passwordWrapper,
.submitWrapper {
position: relative;
}
.loginWrapper:after,
.passwordWrapper:after,
.submitWrapper:after {
content: "";
display: inline-block;
position: absolute;
top: 50%;
right: 10px;
}
.loginWrapper:after,
.passwordWrapper:after {
margin-top: -6px;
right: 10px;
width: 4px;
height: 4px;
border-radius: 50%;
border: 2px solid #000;
background: none;
}
.submitWrapper:after {
margin-top: -3px;
right: 10px;
width: 0;
height: 0;
border-style: solid;
border-width: 3px 0 3px 6px;
border-color: transparent transparent transparent #fff;
}
结果输出如下:

我们可以看到,我们忽略了:before和:after伪元素的问题。
不要忘记占位符
使用 HTML5,我们在所有浏览器中都支持占位符属性。它为我们提供了一个机会来添加以下描述:
::-webkit-input-placeholder
color: red
::-moz-placeholder
color: red
::-ms-input-placeholder
color: red
编译后的 CSS:
::-webkit-input-placeholder {
color: red;
}
::-moz-placeholder {
color: red;
}
::-ms-input-placeholder {
color: red;
}
结果输出如下:

基于 input[type="text"]和标签的复杂表单
那么让我们从复杂和弹性表单的样式开始。假设我们需要创建一个带有标签和输入的表单,其中标签始终位于左侧,输入正在调整大小。让我们来看 HTML 结构:
<form class="" action="index.html" method="post">
<fieldset>
<legend>Personal data</legend>
<div class="fieldKeeper">
<label for="input_name">Your name</label>
<input id="input_name" type="text" name="name" value="">
</div>
<div class="fieldKeeper">
<label for="input_surname">Your surname</label>
<input id="input_surname" type="text" name="name" value="">
</div>
<div class="fieldKeeper">
<label for="input_address">Address</label>
<input id="input_address" type="text" name="name" value="">
</div>
</fieldset>
<fieldset>
<legend>Login data</legend>
<div class="fieldKeeper">
<label for="input_login">Login</label>
<input id="input_login" type="text" name="name" value="" placeholder="Your login">
</div>
<div class="fieldKeeper">
<label for="input_password">Password</label>
<input id="input_password" type="password" name="password" value="" placeholder="Password">
</div>
<div class="fieldKeeper">
<label for="input_password_confirm">Confirm password</label>
<input id="input_password_confirm" type="password" name="confirm_password" value="" placeholder="Confirmed password">
</div>
</fieldset>
</form>
在浏览器中,上述代码将如下所示:
![基于 input[type="text"]和标签的复杂表单](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00082.jpeg)
如你所见,它现在几乎表现得像应该的样子,但它的输入宽度不是 100%。当你将其改为 100%时,标签将移动到输入框上。所以我们可以做的是将输入框包装在另一个div中,并使用填充和绝对/相对位置的技巧。让我们将我们的 HTML 代码改为首个fieldset:
<fieldset>
<legend>Login data</legend>
<div class="fieldKeeper">
<label for="input_login">Login</label>
<div class="inputKeeper">
<input id="input_login" type="text" name="name" value="" placeholder="Your login">
</div>
</div>
<div class="fieldKeeper">
<label for="input_password">Password</label>
<div class="inputKeeper">
<input id="input_password" type="password" name="password" value="" placeholder="Password">
</div>
</div>
<div class="fieldKeeper">
<label for="input_password_confirm">Confirm password</label>
<div class="inputKeeper">
<input id="input_password_confirm" type="password" name="confirm_password" value=""
placeholder="Confirmed password">
</div>
</div>
</fieldset>
在第一个fieldset中进行这个改变后,您将看到代码在有或没有额外的inputKeeper div的情况下的行为。让我们使用以下 SASS 代码:
.fieldKeeper
position: relative
fieldset
width: auto
border: 2px solid green
legend
text-transform: uppercase
font:
size: 10px
weight: bold
label
position: absolute
width: 200px
display: inline-block
left: 0
font:
size: 12px
.inputKeeper
padding:
left: 200px
input
width: 100%
编译后的 CSS:
.fieldKeeper {
position: relative;
}
fieldset {
width: auto;
border: 2px solid green;
}
legend {
text-transform: uppercase;
font-size: 10px;
font-weight: bold;
}
label {
position: absolute;
width: 200px;
display: inline-block;
left: 0;
font-size: 12px;
}
.inputKeeper {
padding-left: 200px;
}
input {
width: 100%;
}
现在您在浏览器中看到的是:
![基于 input[type="text"]和标签的复杂表单](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00083.jpeg)
在更大的屏幕上,您将看到以下内容:
![基于 input[type="text"]和标签的复杂表单](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00084.jpeg)
正如我们所看到的,对于没有额外包装的标签,绝对位置会导致标签覆盖输入的问题。额外的包装给了我们一个机会来添加填充。在这个填充的位置,我们可以使用绝对位置推动标签。在将包装器附加到第二部分之后,它应该在浏览器中看起来如下:
![基于 input[type="text"]和标签的复杂表单](https://gitee.com/OpenDocCN/freelearn-html-css-zh/raw/master/docs/prof-c3/img/00085.jpeg)
如何样式化文本区域
textarea的样式化非常简单,非常类似于文本输入的样式化。其中一个区别是可以调整textarea的机会。这与input[type="text"]文本框相同,可以有一个占位符,因此您可以为其添加样式。让我们准备一个简单的 HTML 代码,以便对textarea进行简短的调查:
<textarea placeholder="Here describe your skills"></textarea>
现在在浏览器中,您将看到以下内容:

请记住,在开放和关闭标签之间不要添加任何空格或行尾,因为它将被视为textarea的内容。这将导致占位符出现问题。
和 SASS 代码:
textarea
width: 300px
height: 150px
resize: none
border: 2px solid green
编译后的 CSS:
textarea {
width: 300px;
height: 150px;
resize: none;
border: 2px solid green;
}
在浏览器中,您将看到以下内容:

作为调整大小属性的值,您可以使用以下值:
-
none:这将在两个轴上禁用调整大小 -
vertical:这将启用垂直调整大小并阻止水平调整大小 -
horizontal:这将启用水平调整大小并阻止垂直调整大小 -
both:这将在两个轴上启用调整大小
选择框的样式化(下拉菜单)
该样式化select(下拉菜单)并不像应该那样简单。在大多数情况下,您需要使用一些 JavaScript 插件来使其更容易。但是您可以用简单的 CSS/HTML 代码做些什么呢?让我们看看以下代码:
<select>
<option>Please choose one option...</option>
<option>Option one</option>
<option>Option two</option>
<option>Option three</option>
<option>Option four</option>
<option>Option five</option>
</select>
上述代码将生成一个未经样式化的选择框,如下所示:

并且在焦点动作之后,它会产生以下输出:

现在我们能做些什么呢?让我们尝试添加更多的风味。首先,让我们将其包装到额外的元素中:
<div class="selectWrapper">
<select>
<option>Please choose one option...</option>
<option>Option one</option>
<option>Option two</option>
<option>Option three</option>
<option>Option four</option>
<option>Option five</option>
</select>
</div>
现在让我们添加一个 SASS 代码:
=triangleBottom($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height $width/2 0 $width/2
border-color: $color transparent transparent transparent
.selectWrapper
width: 300px
border: 2px solid green
overflow: hidden
position: relative
&:after
content: ''
position: absolute
+triangleBottom(10px, 6px, red)
right: 5px
margin-top: -3px
top: 50%
select
background: #fff
color: black
font:
size: 14px
border: none
width: 105%
编译后的 CSS:
.selectWrapper {
width: 300px;
border: 2px solid green;
overflow: hidden;
position: relative;
}
.selectWrapper:after {
content: "";
position: absolute;
width: 0;
height: 0;
border-style: solid;
border-width: 6px 5px 0 5px;
border-color: red transparent transparent transparent;
right: 5px;
margin-top: -3px;
top: 50%;
}
select {
background: #fff;
color: black;
font-size: 14px;
border: none;
width: 105%;
}

正如您所看到的,这种方法相当棘手。我们使选择框比容器宽一点,以将原生控件移出。然后我们向容器添加了溢出隐藏。此外,我们添加了 after 元素以添加一个三角形。
总结
在本章中,您了解了如何样式化表单。处理所有这些表单确实有些棘手,但正如您所看到的,总会有一些解决方案(例如,使用额外的包装器)。我建议您创建一个简单的框架,以便您可以处理表单。这使您完全准备好样式化表单。
在下一章中,我们将尝试解决 CSS 中最常见的问题,例如元素居中、处理显示类型等。这将展示旧学校和新学校方法与新的 CSS 功能可能性。
第七章:解决经典问题
作为前端开发人员,您总是在处理经典的 CSS 问题。最常见和重复的问题是在两个轴上居中元素和不透明度。使用当前的 CSS,您可以做得非常简单,但您需要有基础知识才能知道如何做。关于浏览器先前版本的回退的知识可以在一些其他进阶技术中使用。这就是为什么它们被添加到这一章节中。
在本章中,我们将:
-
学习如何在两个轴上居中元素
-
学习如何处理不透明度
-
汇集前面的技巧,并创建类似于时尚灯箱效果的效果
居中元素
居中元素是自第一个 CSS 版本以来就已知的一个方面。页面上总是有一些需要在某个容器或浏览器中垂直或水平居中的元素/元素。居中一些元素的最简单方法是将元素附加到表元素中,并在 HTML 中添加垂直对齐和水平对齐属性:
<td valign="middle" align="center> </td>
但是在现代 CSS 中我们该如何做到这一点呢?有两种居中方式:
-
水平
-
垂直
让我们解决这个问题。
内联元素-水平居中
假设我们有一段文本需要居中。这很简单。我们只需要添加text-align: center就可以了。在我们将要实现的示例中,我们将容器的背景设置为red,元素的背景设置为white以查看它是如何工作的。
让我们从这段 HTML 代码开始:
<p class="container">
<span class="element">Centered</span>
</p>
和 SASS 代码:
.container
background: red
padding: 20px
.element
background: white
CSS:
.container {
background: red;
padding: 20px;
}
.element {
background: white;
}
在浏览器中我们将看到以下内容:

要使框居中,如前面提到的,我们需要在容器中添加text-align: center:
SASS:
.container
text-align: center
background: red
padding: 20px
.element
background: white
现在在浏览器中,我们可以看到以下内容:

假设我们有两个块元素,我们想要调整它们如前面的例子那样。我们需要做什么?我们需要将显示类型更改为inline或inline-block。让我们稍微改变 HTML 代码:
<div class="container">
<div class="element">Centered</div>
</div>
现在加入之前添加的 SASS 代码,我们的示例将表现得与以下屏幕截图类似:

如前面的屏幕截图所示,块元素占据了全部可能的宽度。我们需要做的是修改 SASS 代码:
.container
text-align: center
background: red
padding: 20px
.element
background: white
display: inline-block
CSS:
.container {
text-align: center;
background: red;
padding: 20px;
}
.element {
background: white;
display: inline-block;
}
现在在浏览器中,我们可以看到以下内容:

块元素-在两个轴上居中
让我们从前一章的代码开始,这将是我们 CSS 样式的基础。这是container中的元素:
<div class="container">
<div class="element">Centered</div>
</div>
添加了带颜色的 SASS 代码以更好地显示问题:
.container
background: black
.element
width: 400px
height: 400px
background: red
CSS:
.container {
background: black;
}
.element {
width: 400px;
height: 400px;
background: red;
}
在起始点,我们在浏览器中的代码将如下所示:

如前面的屏幕截图所示,我们的带有居中内容的容器现在位于黑色容器的左侧。假设这是需要居中并粘贴到页面顶部的页面容器:
.container
background: black
height: 800px
.element
width: 400px
height: 400px
background: red
margin: 0 auto
编译:
.container {
background: black;
height: 800px;
}
.element {
width: 400px;
height: 400px;
background: red;
margin: 0 auto;
}
最重要的一行是加粗的那一行。这使我们的容器居中,如下面的屏幕截图所示:

那么我们该怎么做才能使它在两个轴上居中呢?用已知元素的宽度和高度的老式方法是将容器的相对位置添加到元素的绝对位置。元素需要从顶部和左侧移动 50%。然后我们需要使用负边距将元素向上和向左移动已知高度的一半:
.container
position: relative
.element
position: absolute
width: 100px
height: 100px
left: 50%
right: 50%
margin-left: -50px
margin-top: -50px
CSS:
.container {
position: relative;
}
.element {
position: absolute;
width: 100px;
height: 100px;
left: 50%;
right: 50%;
margin-left: -50px;
margin-top: -50px;
}
输出将如下所示:

正如您在前面的截图中所看到的,该元素在两个轴上都居中。最大的问题是元素的静态宽度和高度。是的,当然,有一种方法可以添加 JavaScript 代码来实现它,但最好使用原生 CSS 函数。所以让我们尝试使用transform属性来实现它。
使用 transform 进行居中
在上一节中,我们一直在尝试解决居中元素的问题。让我们用 transform 声明来扩展它。我们将在下一章中深入了解 transform,以了解它如何与旋转和缩放一起工作,但是对于本章,我们需要添加以下代码:
.container
position: relative
.element
position: absolute
left: 50%
right: 50%
transform: translate(-50%, -50%)
在前面的代码中,最后一行产生了与上一节中相同的效果,定义了负左和上边距。这段代码的最佳特点是我们可以在任何地方添加它,而不需要知道宽度和高度。在下一章中,我们将学习 flexbox,它可以用于元素的居中。
处理不透明度
不透明度在项目中经常出现。例如,当您在页面上创建一些模型窗口或类似灯箱的画廊时。它通常用于在主窗口下添加的图层(覆盖元素),在大多数情况下,该图层在 JavaScript 中添加了onclick事件监听器,点击时隐藏窗口。您如何创建这种效果?过去是如何做到的?让我们从一个简单的 HTML 代码开始:
<header> Header </header>
<main> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Architecto dolore doloremque dolores iure laudantium magni mollitia quam ratione, temporibus ut? Aperiam necessitatibus perspiciatis qui ratione vel! Adipisci eligendi sint unde. </main>
<footer> Footer </footer>
SASS:
header, footer, main
padding: 50px
text-align: center
header, footer
background: red
main
background: green
编译后:
header, footer, main {
padding: 50px;
text-align: center;
}
header, footer {
background: red;
}
main {
background: green;
}
现在它将看起来像下面这样:

我们需要做的是在当前可见容器之上添加一个带有不透明度的图层。让我们在当前添加的代码之后追加这段代码:
<div class="window_container">
<div class="window">Content of our window</div>
</div>
现在我们需要做的是将容器位置更改为fixed,并将元素位置更改为absolute。让我们添加一些代码来增加更多的样式,以便更好地看到我们工作的效果:
.window_container
position: fixed
width: 100%
height: 100%
top: 0
left: 0
background: black
.window
position: absolute
width: 200px
height: 200px
background: white
top: 50%
left: 50%
-webkit-transform: translate(-50%, -50%)
-moz-transform: translate(-50%, -50%)
-ms-transform: translate(-50%, -50%)
-o-transform: translate(-50%, -50%)
transform: translate(-50%, -50%)
编译后:
.window_container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: black;
}
.window {
position: absolute;
width: 200px;
height: 200px;
background: white;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
在浏览器中,我们将看到白色的居中块在黑色容器上,如下所示:

前面的代码将成为下一节的基础,我们将看到opacity和rgba之间的差异。
不透明度与 RGBA-差异及其使用场景
让我们尝试将先前添加到 HTML/SASS 结构中的.window_container元素设置为透明。最简单的方法是添加opacity:.5。所以让我们尝试将以下代码添加到我们当前的 SASS 代码中:
.window_container
opacity: .5
position: fixed
width: 100%
height: 100%
top: 0
left: 0
background: black
CSS:
.window_container {
opacity: 0.5;
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: black;
}
在浏览器中的效果将如下截图所示:

正如我们在前面的截图中所看到的,不透明度被.window_container内的元素继承。这不是我们想要的方式,所以我们必须更改 CSS(SASS)或 HTML 代码。如果我们想更改 HTML 代码,可以这样做:
<div class="window_container"> </div>
<div class="window">Content of our window</div>
SASS 代码将在窗口描述中更改。我们只会将位置更改为fixed:
.window
position: fixed
在浏览器中的效果将如下所示:

正如我们在前面的截图中所看到的,在浏览器中,已经实现了效果,但是我们的 HTML 结构有点混乱。我们已经同时将两个元素添加到了与一个元素相关的 HTML 代码中。所以让我们回到我们章节开头的代码,其中.window在.window_container中。这是我们将使用rgba的地方。确保负责窗口的 HTML 代码如下所示:
<div class="window_container">
<div class="window">Content of our window</div>
</div>
我们需要做的是更改window_container的背景颜色定义,并追加我们的rgba。正如我们所知,我们可以以几种方式定义元素的颜色:
-
添加颜色名称(
black,white,red,...) -
十六进制颜色定义(
#ff00ff,#fff,...) -
基于 RGB(
rgb(0,0,0),rgb(255,255,255))的颜色 -
基于 HSL(
hsl(100, 90%, 50%))的颜色 -
RGBA(
rgb(0,0,0, .4),rgb(255,255,255, .7))基于红绿蓝+ alpha 通道 -
HSLA(
hsl(100, 90%, 50%, .8))基于色调、饱和度、亮度+ alpha 通道
在我们的情况下,我们将使用rgba。window_container的最终 SASS 代码如下:
.window_container
position: fixed
width: 100%
height: 100%
top: 0
left: 0
background: rgba(0,0,0,.5)
.window
position: fixed
width: 200px
height: 200px
background: white
top: 50%
left: 50%
-webkit-transform: translate(-50%, -50%)
-moz-transform: translate(-50%, -50%)
-ms-transform: translate(-50%, -50%)
-o-transform: translate(-50%, -50%)
transform: translate(-50%, -50%)
编译:
.window_container {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
background: rgba(0, 0, 0, 0.5);
}
.window {
position: fixed;
width: 200px;
height: 200px;
background: white;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
-moz-transform: translate(-50%, -50%);
-ms-transform: translate(-50%, -50%);
-o-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
如您所见,opacity声明被移除了。颜色定义为 RGBA。其余代码保持不变。在浏览器中的代码如下所示:

过去的不透明度 - 用于旧 IE 版本的回退
对于旧浏览器的回退方式与当您想要使用边框半径时的方式类似 - 您需要使用图像。最终是如何完成的呢?当图形在图形软件中被裁剪时,覆盖层被裁剪为一个小的透明图像,例如,PNG 1 像素 x1 像素。然后将其添加为背景,并在x和y轴上重复。
/* FALLBACK */
.window_container
background-image: url(<1x1.png>)
background-repeat: repeat
总结
在本章中,您了解了 CSS 中最常见的经典问题:居中和不透明度。您解决了这个问题,并了解了解决方案的利弊。此外,您还了解了如何在旧浏览器中解决不透明度问题。
在下一章中,您将学习有关现代 CSS 方面的知识,如 flexbox 渐变、阴影、变换和数据属性。您还将学习一些可以应用到您的代码中的技巧。让我们继续下一章。
第八章:Flexbox 变换的使用
CSS 仍在发展。作为前端开发人员,每年您都需要关注当前趋势和可以为元素设置的新属性。当然,有很多限制,但在某些情况下,这些限制不存在,例如在新浏览器或选定的移动应用程序中,或者因为设置了要求。在本章中,我们将涵盖以下主题:
-
Flexbox
-
变换属性
Flexbox
Flexbox 是当前 CSS 项目中使用的最响亮和最现代的布局方法之一。使用 flexbox,您可以为网页创建一个比基于浮动框更灵活的结构。为什么?我们将在本章中进行检查和调查。您需要记住的是,自 Internet Explorer 的第 11 个版本起就支持 flexbox。
让我们来看看 flexbox 的基础知识:

如您在前面的屏幕截图中所见,有一个与 flexbox 相关的新字典:
-
主轴(绿色箭头)
-
主轴开始(红线)
-
主轴结束(红线)
-
主轴尺寸(黑线)
-
交叉轴(绿色箭头)
-
交叉开始(红线)
-
交叉结束(红线)
-
交叉尺寸(黑线)
flexbox 的初始化非常简单。您只需要将以下代码添加到容器中:
.flexContainer
display: -webkit-box
display: -moz-box
display: -ms-flexbox
display: -webkit-flex
display: flex
编译后的代码是:
.flexContainer {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
flexbox 的使用仍然需要前缀以实现跨浏览器兼容性。这是创建可重用 mixin 的一个很好的理由:
=displayFlex
display: -webkit-box
display: -moz-box
display: -ms-flexbox
display: -webkit-flex
display: flex
现在我们可以创建与以下相同的.flexContainer:
.flexContainer
+displayFlex
编译后的代码是:
.flexContainer {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
}
让我们在容器中创建一些元素:
<div class="flexContainer">
<div class="flexElement">Element 1</div>
<div class="flexElement">Element 2</div>
<div class="flexElement">Element 3</div>
</div>
让我们稍微装饰一下我们的 CSS 代码,以查看 flexbox 的行为:
=displayFlex
display: -webkit-box
display: -moz-box
display: -ms-flexbox
display: -webkit-flex
display: flex
.flexContainer
+displayFlex
background: red
编译后的代码是:
.flexContainer {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
background: red;
}
现在我们将在浏览器中看到以下视图:

如您在前面的屏幕截图中所见,容器未达到浏览器中的最大可能高度,但确实达到了其全宽。内部元素向左浮动。现在让我们稍微改变 SASS 代码:
.flexContainer
+displayFlex
height: 100%
background: red
.blue
background: blue
.green
background: green
.yellow
background: yellow
编译后的代码是:
.flexContainer {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
height: 100%;
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
让我们在 HTML 代码中添加一个颜色类:
<div class="flexContainer">
<div class="flexElement blue">Element 1</div>
<div class="flexElement green">Element 2</div>
<div class="flexElement yellow">Element 3</div>
</div>
在浏览器中,您将看到以下内容:

如您在前面的屏幕截图中所见,容器具有全宽和高,并且内部元素的行为类似于内联元素,但继承自容器的全高。这是因为属性称为align-item,其默认值为stretch。让我们更深入地了解此属性的值。
Flexbox 属性 align-items
这是我们可以添加到flexContainer的属性之一。它有一些我们可以设置的值。目前,我们知道默认的 stretch 值的行为。让我们研究其余可能的值。在所有值之前,让我们稍微改变 HTML 和 CSS 代码,以更好地查看所有行为。
让我们修改 HTML 代码如下:
<div class="flexContainer">
<div class="flexElement blue h200px">Element 1</div>
<div class="flexElement green h300px">Element 2</div>
<div class="flexElement yellow h100px">Element 3</div>
</div>
让我们附加以下 SASS 代码:
.h100px
height: 100px
.h200px
height: 200px
.h300px
height: 300px
CSS 文件是:
.h100px {
height: 100px;
}
.h200px {
height: 200px;
}
.h300px {
height: 300px;
}
可以使用的 flex 的不同值如下:
stretch(默认)![Flexbox 属性 align-items]()
提示
对于此值 stretch,您需要删除添加盒子高度(h100px,h200px,h300px)的类。
-
flex-start![Flexbox 属性 align-items]()
-
flex-end![Flexbox 属性 align-items]()
-
center![Flexbox 属性 align-items]()
-
baseline
在这种情况下,为了更好地理解这种行为,让我们更改我们的代码以查看如何指定基线:
<div class="flexContainer">
<div class="flexElement blue h200px">Element 1</div>
<div class="flexElement green h300px">Element 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Possimus necessitatibus est quis sequi, sapiente quos corporis, dignissimos libero quibusdam beatae ipsam quaerat? Excepturi magni voluptas dicta inventore necessitatibus omnis officia.</div>
<div class="flexElement yellow h100px">Element 3</div>
</div>
在 SASS 中,代码可以编写为:
.h100px
height: 100px
font-size: 30px
margin-top: 20px
.h200px
height: 200px
font-size: 20px
.h300px
height: 300px
font-size: 8px
CSS 代码将是:
.h100px {
height: 100px;
font-size: 30px;
margin-top: 20px;
}
.h200px {
height: 200px;
font-size: 20px;
}
.h300px {
height: 300px;
font-size: 8px;
}
前面代码的输出如下:

从顶部的盒子位置是从盒子中的第一行文本指定的基线设置的。有意义的是为h100px盒子添加了一个 margin-top,以查看基线是从子元素集中的任何一个盒子计算的。
好的。但是当我们添加一个没有文本内容的框时,这个例子会如何表现呢?让我们修改 HTML 代码如下:
<div class="flexContainer">
<div class="flexElement blue h200px">Element 1</div>
<div class="flexElement yellow h100px w100px"></div>
<div class="flexElement green h300px">Element 2 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Possimus necessitatibus est quis sequi, sapiente quos corporis, dignissimos libero quibusdam beatae ipsam quaerat? Excepturi magni voluptas dicta inventore necessitatibus omnis officia.</div>
<div class="flexElement yellow h100px">Element 3</div>
</div>
让我们在 SASS 代码中添加w100px类:
.w100px
width: 100px
CSS:
.w100px {
width: 100px;
}
前面代码的输出如下:

正如我们在前面的屏幕截图中看到的那样,基线由黄色空框的底部线指定。
Flexbox 属性 flex-wrap
我们可以为 flex 容器设置的下一个属性之一是flex-wrap。此属性与框中的换行有关。我们可以将nowrap,wrap和wrap-reverse设置为值。它们的行为如何?
-
nowrap(默认) -
wrap -
wrap-reverse
正如你所看到的,wrap和wrap-reverse的工作方式相同,但有一个简单的区别:wrap-reverse改变了伸缩项的顺序。
Flexbox 属性 justify-content
justify-content属性也与容器有关:
-
flex-start -
flex-end -
center -
space-between -
space-around
Flexbox 属性 align-content
项目的对齐与flexContainer有关。您需要记住,当您至少有两行项目时,效果才会可见。因此,让我们更改以下示例代码:
HTML:
<div class="flexContainer">
<div class="flexElement blue h100px">Element 1</div>
<div class="flexElement green h200px">Element 2</div>
<div class="flexElement blue h100px">Element 3</div>
<div class="flexElement green h200px">Element 4</div>
<div class="flexElement blue h100px">Element 5</div>
<div class="flexElement green h200px">Element 6</div>
</div>
SASS 代码是:
=displayFlex
display: -webkit-box
display: -moz-box
display: -ms-flexbox
display: -webkit-flex
display: flex
.flexContainer
height: 600px
width: 900px
+displayFlex
flex-wrap: wrap
background: red
.blue
background: blue
.green
background: green
.yellow
background: yellow
.h100px
height: 100px
font-size: 30px
margin-top: 20px
.h200px
height: 200px
font-size: 20px
.h300px
height: 300px
font-size: 8px
.w100px
width: 100px
.flexElement
width: 300px
CSS 代码是:
.flexContainer {
height: 600px;
width: 900px;
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
flex-wrap: wrap;
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
.h100px {
height: 100px;
font-size: 30px;
margin-top: 20px;
}
.h200px {
height: 200px;
font-size: 20px;
}
.h300px {
height: 300px;
font-size: 8px;
}
.w100px {
width: 100px;
}
.flexElement {
width: 300px;
}
-
flex-start -
flex-end -
center -
space-between -
space-around -
stretch
在最后一个例子中,所有与高度相关的类都已被删除:h100px,h200px。
Flexbox 属性 flex-direction
flexbox 的不同属性如下:
-
row -
row-reverse -
column -
column-reverse
您可以添加到您的收藏中的有用的 mixin 如下:
=displayFlex
display: -webkit-box
display: -moz-box
display: -ms-flexbox
display: -webkit-flex
display: flex
=flexOrder($number)
-webkit-box-ordinal-group: $number
-moz-box-ordinal-group: $number
-ms-flex-order: $number
-webkit-order: $number
order: $number
使用 flexbox-创建页面结构
当您开始处理项目时,您会将准备好的布局作为图形文件,并且需要在浏览器中使其可用和交互。让我们从当前最知名的结构开始:
<div class="flexContainer">
<header>Header</header>
<aside>Side menu</aside>
<main>Content</main>
<footer>Footer - Copyright fedojo.com</footer>
</div>
因此,我们希望将标题放在顶部,左侧主体放在右侧,页脚放在底部:
.flexContainer
+displayFlex
-webkit-flex-flow: row wrap
flex-flow: row wrap
& > *
padding: 10px
flex: 1 100%
header
background: red
footer
background: lightblue
main
background: yellow
flex: 3 1 auto
aside
background: green
flex: 0 0 auto
CSS 文件是:
.flexContainer {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
}
.flexContainer > * {
padding: 10px;
flex: 1 100%;
}
.flexContainer header {
background: red;
}
.flexContainer footer {
background: lightblue;
}
.flexContainer main {
background: yellow;
flex: 3 auto;
}
.flexContainer aside {
background: green;
flex: 1 auto;
}
浏览器中的效果将如下:

当您希望将侧边栏宽度更改为静态值时,您可以在侧边菜单的 SASS 声明中添加一个小的更改:
aside
background: green
flex: 0 0 auto
width: 100px
它将在 CSS 中:
.flexContainer aside {
background: green;
flex: 0 auto;
width: 100px;
}
这将保持左侧列的静态宽度。
使用 flexbox-在移动/平板视图中更改框的顺序
当您在创建 HTML 布局时调整到桌面和移动设备时,可能会出现一些情况,您需要更改框的顺序。桌面的简单示例如下:
-
第一个元素需要在顶部
-
第二个元素需要在底部
移动设备的简单示例如下:
-
第二个元素需要在顶部
-
第一个元素需要在底部
让我们使用以下 HTML 代码:
<div class="container">
<div class="first">First</div>
<div class="second">Second</div>
</div>
让我们创建几行 SASS 代码:
=displayFlex
display: -webkit-box
display: -moz-box
display: -ms-flexbox
display: -webkit-flex
display: flex
=flexOrder($number)
-webkit-box-ordinal-group: $number
-moz-box-ordinal-group: $number
-ms-flex-order: $number
-webkit-order: $number
order: $number
.container > *
padding: 20px
.first
background: lightblue
.second
background: lightcyan
@media screen and (max-width: 600px)
.container
+displayFlex
-webkit-flex-flow: row wrap
flex-flow: row wrap
& > *
width: 100%
.first
+flexOrder(2)
.second
+flexOrder(1)
在 CSS 中:
.container > * {
padding: 20px;
}
.first {
background: lightblue;
}
.second {
background: lightcyan;
}
@media screen and (max-width: 600px) {
.container {
display: -webkit-box;
display: -moz-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-flex-flow: row wrap;
flex-flow: row wrap;
}
.container > * {
width: 100%;
}
.container .first {
-webkit-box-ordinal-group: 2;
-moz-box-ordinal-group: 2;
-ms-flex-order: 2;
-webkit-order: 2;
order: 2;
}
.container .second {
-webkit-box-ordinal-group: 1;
-moz-box-ordinal-group: 1;
-ms-flex-order: 1;
-webkit-order: 1;
order: 1;
}
}
在桌面上,当视口宽度大于600px时,您可以看到以下内容:

在小于600px的视图上,您可以看到以下内容:

更多关于 transform 的内容
变换对于前端开发人员非常有用,因为你可以仅使用 CSS 执行基本的图形操作。在 CSS 的早期版本中,这只能通过 JavaScript 实现。在之前的章节中,我们使用transform来将元素居中在容器中。现在让我们尝试更深入地理解它,并检查我们还能做些什么:
HTML 文件如下:
<table>
<tr>
<td>no transform</td>
<td><div class="transform_none">no transform</div></td>
</tr>
<tr>
<td>rotate</td>
<td><div class="transform_rotate">rotate</div></td>
<td><div class="transform_rotatex">rotateX</div></td>
<td><div class="transform_rotatey">rotateY</div></td>
<td><div class="transform_rotatez">rotateZ</div></td>
</tr>
<tr>
<td>skew</td>
<td><div class="transform_skew">skew</div></td>
<td><div class="transform_skewx">skewX</div></td>
<td><div class="transform_skewy">skewY</div></td>
</tr>
<tr>
<td>scale</td>
<td><div class="transform_scale">scale</div></td>
<td><div class="transform_scalex">scaleX</div></td>
<td><div class="transform_scaley">scaleY</div></td>
<td><div class="transform_scalez">scaleZ</div></td>
</tr>
<tr>
<td>translate</td>
<td><div class="transform_translate">translate</div></td>
<td><div class="transform_translatex">translateX</div></td>
<td><div class="transform_translatey">translateY</div></td>
<td><div class="transform_translatez">translateZ</div></td>
</tr>
<tr>
<td>multiple</td>
<td><div class="transform_multiple01">multiple</div></td>
</tr>
</table>
SASS 文件如下:
table
border-collapse: collapse
td, th
border: 1px solid black
div[class^="transform_"]
width: 100px
height: 100px
background: lightblue
line-height: 100px
text:
align: center
transform: uppercase
font:
weight: bold
size: 10px
display: inline-block
td
text-align: center
vertical-align: middle
width: 150px
height: 150px
.transform_
/* Rotate */
&rotate
transform: rotate(25deg)
&rotatex
transform: rotateX(25deg)
&rotatey
transform: rotateY(25deg)
&rotatez
transform: rotateZ(25deg)
/* Skew */
&skew
transform: skew(10deg, 10deg)
&skewx
transform: skewX(10deg)
&skewy
transform: skewY(10deg)
/* Scale */
&scalex
transform: scaleX(1.2)
&scale
transform: scale(1.2)
&scaley
transform: scaleY(1.2)
/* Translate */
&translate
transform: translate(10px, 10px)
&translatex
transform: translate(10%)
&translatey
transform: translate(10%)
&translatez
transform: translate(10%)
/* Multiple */
&multiple01
transform: rotateX(25deg) translate(10px, 10px) skewX(10deg)
CSS 文件如下:
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid black;
}
div[class^="transform_"] {
width: 100px;
height: 100px;
background: lightblue;
line-height: 100px;
text-align: center;
text-transform: uppercase;
font-weight: bold;
font-size: 10px;
display: inline-block;
}
td {
text-align: center;
vertical-align: middle;
width: 150px;
height: 150px;
}
.transform_ {
/* Rotate */
/* Skew */
/* Scale */
/* Translate */
/* Multiple */
}
.transform_rotate {
transform: rotate(25deg);
}
.transform_rotatex {
transform: rotateX(25deg);
}
.transform_rotatey {
transform: rotateY(25deg);
}
.transform_rotatez {
transform: rotateZ(25deg);
}
.transform_skew {
transform: skew(10deg, 10deg);
}
.transform_skewx {
transform: skewX(10deg);
}
.transform_skewy {
transform: skewY(10deg);
}
.transform_scalex {
transform: scaleX(1.2);
}
.transform_scale {
transform: scale(1.2);
}
.transform_scaley {
transform: scaleY(1.2);
}
.transform_translate {
transform: translate(10px, 10px);
}
.transform_translatex {
transform: translate(10%);
}
.transform_translatey {
transform: translate(10%);
}
.transform_translatez {
transform: translate(10%);
}
.transform_multiple01 {
transform: rotateX(25deg) translate(10px, 10px) skewX(10deg);
}
在浏览器中的效果将如下所示:

在上面的示例中,在浏览器的示例视图中有一堆可能的变换。在第一行中,你可以看到没有任何变换的元素。在接下来的每一行中,你可以检查以下内容:
-
rotate
-
skew
-
scale
-
translate
-
multiple
变换的重要方面是可以在每种变换类型中使用的单位:
-
rotate:度数,例如,rotate(20deg, 40deg). -
skew:度数,例如,skew(30deg, 50deg). -
scale:数字,其中 1 = 100%,例如,scale(1.5, 1.5). -
translate:与宽度相关的单位,如像素百分比,例如,translate(50%, 50%)。重要信息:百分比与转换对象的尺寸相关。
在前面截图的最后一行中,有一个示例显示了如何在一行中链接多个变换。当你需要添加多个变换时,可以使用这个示例。
总结
在本章中,你了解了现代 CSS 的主要特性。你学会了 flexbox 的工作原理以及如何在项目中使用它。你分析了二维变换,这些变换可以在你的项目中使用。本章是对新 CSS 特性的介绍,将帮助你了解可能性。
在下一章中,我们将专注于渐变、阴影和动画。我们将创建线性和径向渐变框和文本阴影,并且还将了解calc函数的知识。
第九章:Calc, Gradients, and Shadows
在上一章中,我们分析了 flexbox 和基于 flexbox 模型的简单结构。在本章中,我们将专注于 CSS 的以下方面:
-
Calc 函数
-
渐变
-
阴影
-
CSS 动画。
-
使用 data-attribute
让我们开始吧!
calc()方法
你有没有遇到过混合单位的问题?例如,假设你需要制作一个方程 60%-10px?这些操作在旧浏览器中可能非常有用,而且现在在 CSS 中可以通过calc()方法实现。你如何使用它?让我们解决一个有两个浮动框的问题;一个具有固定宽度,第二个则根据可能的最大宽度进行调整。代码如下:
HTML:
<div class="container">
<div class="first">First</div>
<div class="second">Second</div>
</div>
SASS:
&:after
content: ""
display: table
clear: both
.container
+clearfix
& > *
float: left
height: 200px
padding: 10px
box-sizing: border-box
.first
width: 100px
background: red
.second
width: calc(100% - 100px)
background: blue
编译后的 CSS:
.container:after {
content: "";
display: table;
clear: both;
}
.container >* {
float: left;
height: 200px;
padding: 10px;
box-sizing: border-box;
}
.first {
width: 100px;
background: red;
}
.second {
width: calc(100% - 100px);
background: blue;
}
这是最终结果:

calc()函数给了我们一个机会去做简单的方程,比如百分比减去像素。在这个简单的例子中,你可以看到我们不需要使用 padding 和绝对位置的技巧。你可以正确使用calc()函数,问题就会得到解决。
CSS 中的渐变
有经验的前端开发人员还记得渐变是如何作为背景图像完成的。是的!那是模仿浏览器中的渐变的唯一想法。你需要从 PSD 文件中裁剪 1px 宽度和渐变高度(如果是垂直渐变;在水平渐变的情况下,高度是 1px,宽度由渐变的宽度指定)。然后,你需要将其添加到 CSS 中,并在背景中重复你的魔术图像。
现在,你可以在 CSS 中做到这一点!让我们从线性渐变开始。
线性渐变
线性渐变可以有两种类型:从上到下或从左到右。让我们从垂直渐变开始:
background: linear-gradient(to bottom, #000 0%, #f00 100%)
这段代码将生成一个从上到下的线性渐变。在顶部,颜色将是黑色,在底部将是红色。

然而,成为前端开发人员可能并不那么容易。这就是为什么你需要记住前缀:
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #000), color-stop(100%, #f00))
background: -moz-linear-gradient(top, #000 0%, #f00 100%)
background: -webkit-linear-gradient(top, #000 0%, #f00 100%)
background: -o-linear-gradient(top, #000 0%, #f00 100%)
background: -ms-linear-gradient(top, #000 0%, #f00 100%)
background: linear-gradient(to bottom, #000 0%, #f00 100%)
正如你所看到的,带前缀的定义占用了大量的代码,特别是当你需要为 IE9 提供回退时(最后一行带有 filter 定义)。
基本的水平渐变定义如下:
background: linear-gradient(left, #fff, #000)
这个例子将生成一个从左到右的渐变,右边是白色,左边是黑色。

这是带前缀的版本:
background: -webkit-gradient(linear, left top, right top, from(#fff), to(#000))
background: -webkit-linear-gradient(left, #fff, #000)
background: -moz-linear-gradient(left, #fff, #000)
background: -ms-linear-gradient(left, #fff, #000)
background: -o-linear-gradient(left, #fff, #000)
background: linear-gradient(left, #fff, #000)
多色渐变呢?当然是可能的:
background: linear-gradient(to right, black, red, white)
这是效果:

你也可以旋转渐变:
HTML:
<div class="gradient-04"></div>
SASS:
div[class^="gradient-"]
height: 200px
width: 200px
margin-bottom: 20px
.gradient-04
background: linear-gradient(45deg , black, red, white)
CSS:
div[class^="gradient-"] {
height: 200px;
width: 200px;
margin-bottom: 20px;
}
.gradient-04 {
background: linear-gradient(45deg, black, red, white);
}
在浏览器中的效果:

如果你想改变颜色之间的平衡呢?例如,也许你想在渐变中有更高浓度的黑色?这也是可能的:
SASS:
.gradient-05
background: linear-gradient(to right, black 40%, red 50%, white 100%)
CSS:
.gradient-05 {
background: linear-gradient(to right, black 40%, red 50%, white 100%);
}
在浏览器中的效果:

要理解这一点,你需要逐步检查这个例子:
black 40%:This line means that black color will be finished in 40% of width of the box
red 50%:This means that red color will be finished in 50% of width of the box
white 100%:This means that white color will be finished in 100% of width of the box
使用渐变 mixin
在本章中,你可以获得这些 mixin 并在你的项目中使用它们。我不喜欢每次都写很长的代码——只需写一次,然后重复简短版本。这就是为什么我准备了这两个简单的渐变:
=linearGradientFromTop($startColor, $endColor)
background: $startColor
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, $startColor), color-stop(100%, $endColor))
background: -moz-linear-gradient(top, $startColor 0%, $endColor 100%)
background: -webkit-linear-gradient(top, $startColor 0%, $endColor 100%)
background: -o-linear-gradient(top, $startColor 0%, $endColor 100%)
background: -ms-linear-gradient(top, $startColor 0%, $endColor100%)
background: linear-gradient(to bottom, $startColor 0%, $endColor 100%)
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#{$startColor}', endColorstr='#{$endColor}',GradientType=0 )
=linearGradientFromLeft($startColor, $endColor)
background-color: $startColor
background: -webkit-gradient(linear, left top, right top, from($startColor), to($endColor))
background: -webkit-linear-gradient(left, $startColor, $endColor)
background: -moz-linear-gradient(left, $startColor, $endColor)
background: -ms-linear-gradient(left, $startColor, $endColor)
background: -o-linear-gradient(left, $startColor, $endColor)
background: linear-gradient(left, $startColor, $endColor)
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#{$startColor}', endColorStr='#{$endColor}', gradientType='1')
在前面的混合示例中最重要的一点是,您需要使用hex颜色的完整表示。例如,您不能使用#f00来表示红色。您必须使用#ff0000。这是因为 IE9 及更低版本不支持渐变中较短的颜色表示。混合中的另一个重要事项是第一行,它仅设置背景颜色。这是所有不支持任何前缀/非前缀渐变版本的浏览器的回退。使用它,颜色仅设置为作为$startColor设置的颜色。混合中的第二行与基于 WebKit 的旧版本浏览器有关。最后一行与旧版 IE(9 及更低版本)有关。当然,如果没有使用或不需要,您不必在项目中保留此代码。您可以修改它以满足项目的要求。
径向渐变
在一些项目中,您需要添加径向渐变。径向渐变标准函数如下:
radial-gradient()
或者你可以使用:
background: repeating-radial-gradient()
让我们检查一个示例代码和渐变使用的可能性:
HTML:
<table>
<tr>
<td><div class="gradient-04"></div></td>
<td><div class="gradient-05"></div></td>
<td><div class="gradient-06"></div></td>
</tr>
<tr>
<td><div class="gradient-07"></div></td>
<td><div class="gradient-08"></div></td>
<td><div class="gradient-09"></div></td>
</tr>
<tr>
<td><div class="gradient-10"></div></td>
<td><div class="gradient-11"></div></td>
<td><div class="gradient-12"></div></td>
</tr>
</table>
SASS:
div[class^="gradient-"]
height: 200px
width: 200px
margin-bottom: 20px
//
.gradient-04
background: red
background: -webkit-radial-gradient(50% 50%, closest-side, red, black)
background: -o-radial-gradient(50% 50%, closest-side, red, black)
background: -moz-radial-gradient(50% 50%, closest-side, red, black)
background: radial-gradient(closest-side at 50% 50%, red, black)
.gradient-05
background: red
background: -webkit-radial-gradient(10% 10%, closest-side, red, black)
background: -o-radial-gradient(10% 10%, closest-side, red, black)
background: -moz-radial-gradient(10% 10%, closest-side, red, black)
background: radial-gradient(closest-side at 10% 10%, red, black)
.gradient-06
background: red
background: -webkit-radial-gradient(50% 10%, closest-side, red, black)
background: -o-radial-gradient(50% 10%, closest-side, red, black)
background: -moz-radial-gradient(50% 10%, closest-side, red, black)
background: radial-gradient(closest-side at 50% 10%, red, black)
.gradient-07
background: red
background: -webkit-radial-gradient(50% 50%, closest-corner, red, black)
background: -o-radial-gradient(50% 50%, closest-corner, red, black)
background: -moz-radial-gradient(50% 50%, closest-corner, red, black)
background: radial-gradient(closest-corner at 50% 50%, red, black)
.gradient-08
background: red
background: -webkit-radial-gradient(10% 10%, closest-corner, red, black)
background: -o-radial-gradient(10% 10%, closest-corner, red, black)
background: -moz-radial-gradient(10% 10%, closest-corner, red, black)
background: radial-gradient(closest-corner at 10% 10%, red, black)
.gradient-09
background: red
background: -webkit-radial-gradient(50% 10%, closest-corner, red, black)
background: -o-radial-gradient(50% 10%, closest-corner, red, black)
background: -moz-radial-gradient(50% 10%, closest-corner, red, black)
background: radial-gradient(closest-corner at 50% 10%, red, black)
.gradient-10
background: red
background: -webkit-repeating-radial-gradient(50% 50%, closest-corner, red, black)
background: -o-repeating-radial-gradient(50% 50%, closest-corner, red, black)
background: -moz-repeating-radial-gradient(50% 50%, closest-corner, red, black)
background: repeating-radial-gradient(closest-corner at 50% 50%, red, black)
.gradient-11
background: red
background: -webkit-repeating-radial-gradient(10% 10%, closest-corner, red, black)
background: -o-repeating-radial-gradient(10% 10%, closest-corner, red, black)
background: -moz-repeating-radial-gradient(10% 10%, closest-corner, red, black)
background: repeating-radial-gradient(closest-corner at 10% 10%, red, black)
.gradient-12
background: red
background: -webkit-repeating-radial-gradient(50% 10%, closest-corner, red, black)
background: -o-repeating-radial-gradient(50% 10%, closest-corner, red, black)
background: -moz-repeating-radial-gradient(50% 10%, closest-corner, red, black)
background: repeating-radial-gradient(closest-corner at 50% 10%, red, black)
CSS:
div[class^="gradient-"] {
height: 200px;
width: 200px;
margin-bottom: 20px;
}
.gradient-04 {
background: red;
background: -webkit-radial-gradient(50% 50%, closest-side, red, black);
background: -o-radial-gradient(50% 50%, closest-side, red, black);
background: -moz-radial-gradient(50% 50%, closest-side, red, black);
background: radial-gradient(closest-side at 50% 50%, red, black);
}
.gradient-05 {
background: red;
background: -webkit-radial-gradient(10% 10%, closest-side, red, black);
background: -o-radial-gradient(10% 10%, closest-side, red, black);
background: -moz-radial-gradient(10% 10%, closest-side, red, black);
background: radial-gradient(closest-side at 10% 10%, red, black);
}
.gradient-06 {
background: red;
background: -webkit-radial-gradient(50% 10%, closest-side, red, black);
background: -o-radial-gradient(50% 10%, closest-side, red, black);
background: -moz-radial-gradient(50% 10%, closest-side, red, black);
background: radial-gradient(closest-side at 50% 10%, red, black);
}
.gradient-07 {
background: red;
background: -webkit-radial-gradient(50% 50%, closest-corner, red, black);
background: -o-radial-gradient(50% 50%, closest-corner, red, black);
background: -moz-radial-gradient(50% 50%, closest-corner, red, black);
background: radial-gradient(closest-corner at 50% 50%, red, black);
}
.gradient-08 {
background: red;
background: -webkit-radial-gradient(10% 10%, closest-corner, red, black);
background: -o-radial-gradient(10% 10%, closest-corner, red, black);
background: -moz-radial-gradient(10% 10%, closest-corner, red, black);
background: radial-gradient(closest-corner at 10% 10%, red, black);
}
.gradient-09 {
background: red;
background: -webkit-radial-gradient(50% 10%, closest-corner, red, black);
background: -o-radial-gradient(50% 10%, closest-corner, red, black);
background: -moz-radial-gradient(50% 10%, closest-corner, red, black);
background: radial-gradient(closest-corner at 50% 10%, red, black);
}
.gradient-10 {
background: red;
background: -webkit-repeating-radial-gradient(50% 50%, closest-corner, red, black);
background: -o-repeating-radial-gradient(50% 50%, closest-corner, red, black);
background: -moz-repeating-radial-gradient(50% 50%, closest-corner, red, black);
background: repeating-radial-gradient(closest-corner at 50% 50%, red, black);
}
.gradient-11 {
background: red;
background: -webkit-repeating-radial-gradient(10% 10%, closest-corner, red, black);
background: -o-repeating-radial-gradient(10% 10%, closest-corner, red, black);
background: -moz-repeating-radial-gradient(10% 10%, closest-corner, red, black);
background: repeating-radial-gradient(closest-corner at 10% 10%, red, black);
}
.gradient-12 {
background: red;
background: -webkit-repeating-radial-gradient(50% 10%, closest-corner, red, black);
background: -o-repeating-radial-gradient(50% 10%, closest-corner, red, black);
background: -moz-repeating-radial-gradient(50% 10%, closest-corner, red, black);
background: repeating-radial-gradient(closest-corner at 50% 10%, red, black);
}
这是在浏览器中的效果:

如何添加盒子阴影
回到过去,CSS 中没有阴影功能。这个功能让您有机会向盒子(使用box-shadow)和文本(使用text-shadow)添加阴影效果。box-shadow是如何创建的?让我们来看看 CSS 中这个属性的参数:
box-shadow: horizontal-shadow vertical-shadow blur spread color
在所有参数之前,您可以添加内部。使用此属性,阴影将位于元素内部。
理解这一点最简单的方法是查看它在浏览器中的行为:
HTML:
<div class="container">
<div class="box_container">
<div class="box__bottom_right">bottom right</div>
</div>
<div class="box_container">
<div class="box__bottom_left">bottom left</div>
</div>
<div class="box_container">
<div class="box__top_right">top right</div>
</div>
<div class="box_container">
<div class="box__top_left">top left</div>
</div>
<div class="box_container">
<div class="box__blurred">blurred</div>
</div>
<div class="box_container">
<div class="box__notblurred">notblurred</div>
</div>
<div class="box_container">
<div class="box__spreaded">spreaded</div>
</div>
<div class="box_container">
<div class="box__innershadow">inner shadow</div>
</div>
</div>
SASS:
=clearfix
&:after
content: ""
display: table
clear: both
.container
+clearfix
width: 800px
& > *
float: left
.box_container
width: 200px
height: 200px
position: relative
div[class^="box__"]
width: 100px
height: 100px
position: absolute
background: lightblue
top: 50%
left: 50%
line-height: 100px
font:
size: 10px
text:
align: center
transform: translate(-50%,-50%)
.box__bottom_right
box-shadow: 5px 5px 5px 0 #000
.box__bottom_left
box-shadow: -5px 5px 5px 0 #000
.box__top_right
box-shadow: 5px -5px 5px 0 #000
.box__top_left
box-shadow: -5px -5px 5px 0 #000
.box__blurred
box-shadow: 0px 0px 10px 0 #000
.box__notblurred
box-shadow: 0px 0px 0 0 #000
.box__spreaded
box-shadow: 0px 0px 0 5px #000
.box__innershadow
box-shadow: inset 0px 0px 5px 0px #000
CSS:
.container {
width: 800px;
}
.container:after {
content: "";
display: table;
clear: both;
}
.container > * {
float: left;
}
.box_container {
width: 200px;
height: 200px;
position: relative;
}
div[class^="box__"] {
width: 100px;
height: 100px;
position: absolute;
background: lightblue;
top: 50%;
left: 50%;
line-height: 100px;
font-size: 10px;
text-align: center;
transform: translate(-50%, -50%);
}
.box__bottom_right {
box-shadow: 5px 5px 5px 0 #000;
}
.box__bottom_left {
box-shadow: -5px 5px 5px 0 #000;
}
.box__top_right {
box-shadow: 5px -5px 5px 0 #000;
}
.box__top_left {
box-shadow: -5px -5px 5px 0 #000;
}
.box__blurred {
box-shadow: 0px 0px 10px 0 #000;
}
.box__notblurred {
box-shadow: 0px 0px 0 0 #000;
}
.box__spreaded {
box-shadow: 0px 0px 0 5px #000;
}
.box__innershadow {
box-shadow: inset 0px 0px 5px 0px #000;
}
这是在浏览器中的效果:

在这个例子中,您可以查看如何设置垂直和水平阴影。此外,您还可以设置模糊扩散和其颜色。向垂直和水平阴影添加正值会将阴影分别移动到底部和右侧。当您添加负值时,它将移动到顶部和左侧。
如何添加文本阴影
为盒子添加阴影非常简单。但是我们如何为文本添加阴影?使用text-shadow属性是可能的。它的工作方式与box-shadow非常相似。这是定义:
text-shadow: horizontal-shadow vertical-shadow blur-radius color
让我们创建一个基于上一章代码的示例,以更好地理解text-shadow属性:
HTML:
<div class="container">
<div class="box_container">
<div class="box__bottom_right">bottom right</div>
</div>
<div class="box_container">
<div class="box__bottom_left">bottom left</div>
</div>
<div class="box_container">
<div class="box__top_right">top right</div>
</div>
<div class="box_container">
<div class="box__top_left">top left</div>
</div>
<div class="box_container">
<div class="box__blurred">blurred</div>
</div>
<div class="box_container">
<div class="box__notblurred">notblurred</div>
</div>
</div>
SASS:
=clearfix
&:after
content: ""
display: table
clear: both
.container
+clearfix
width: 00px
&>*
float: left
.box_container
width: 100px
height: 100px
position: relative
div[class^="box__"]
width: 100px
height: 100px
position: absolute
background: lightblue
top: 50%
left: 50%
line-height: 100px
font:
size: 10px
text:
align: center
transform: translate(-50%,-50%)
.box__bottom_right
text-shadow: 5px 5px 5px #000
.box__bottom_left
text-shadow: -5px 5px 5px #000
.box__top_right
text-shadow: 5px -5px 5px #000
.box__top_left
text-shadow: -5px -5px 5px #000
.box__blurred
text-shadow: 0px 0px 10px #000
.box__notblurred
text-shadow: 5px 5px 0 red
CSS:
.container {
width: 0px;
}
.container:after {
content: "";
display: table;
clear: both;
}
.container >* {
float: left;
}
.box_container {
width: 100px;
height: 100px;
position: relative;
}
div[class^="box__"] {
width: 100px;
height: 100px;
position: absolute;
background: lightblue;
top: 50%;
left: 50%;
line-height: 100px;
font-size: 10px;
text-align: center;
transform: translate(-50%, -50%);
}
.box__bottom_right {
text-shadow: 5px 5px 5px #000;
}
.box__bottom_left {
text-shadow: -5px 5px 5px #000;
}
.box__top_right {
text-shadow: 5px -5px 5px #000;
}
.box__top_left {
text-shadow: -5px -5px 5px #000;
}
.box__blurred {
text-shadow: 0px 0px 10px #000;
}
.box__notblurred {
text-shadow: 5px 5px 0 red;
}
这是在浏览器中的效果:

其他字体和文本功能
在过去的 5 年中,CSS 中的字体功能发生了很大变化。在过去,没有机会使用非标准字体,因为它被描述为互联网安全。这是使 Flash 技术更流行的问题之一,不仅因为完整的 Flash 页面,还因为可扩展的 Inman Flash Replacement(SIFR)。使用 SIFR,您只需要在 Adobe Flash 中附加您的字体并编译文件;然后您可以在网站上使用您的字体。但是您的 HTML 页面中有 Flash 实例。然后,有一种基于 JavaScript 的方法叫做cufon。您可以使用您的字体访问 cufon 页面,编译您的字体,然后在您的网站上附加cufon.js和您编译的字体(JS 文件)。在 JavaScript 中,您需要添加应该被交换的字体,最后您的字体就会在网站上可见。
如今,我们可以使用 font-face 在 Web 版本中使用自定义字体。
在浏览器中使用非标准字体
如果您想在浏览器中使用您的字体,您需要准备它。font-face 的基本定义基于原始 CSS 中的这个示例:
@font-face {
font-family: font_name;
src: url(your_font.woff);
}
如果您现在想使用您的字体,您需要在 CSS 中附加此示例代码:
.classOfElement {
font-family: font_name;
}
主要问题是,如果我有另一种字体格式,我该如何准备我的字体以在浏览器中使用?如果您有一个字体,您可以使用fontsquirrel.com生成最终的 CSS 视图以供使用。当然,还有一些其他地方可以搜索字体:
-
Google Fonts (
www.google.com/fonts) -
Typekit (
typekit.com/fonts)
在这里,您可以找到在您的项目中可以直接使用的字体。
使用 CSS 动画
CSS 动画是一个非常有用的功能。您无需使用 JavaScript 进行简单的动画,而且 CSS 动画受到 GPU(图形处理单元)的支持。CSS 动画可以做什么?让我们看下面的例子:
<div class="container">
<div class="rollin"></div>
</div>
SASS:
.container
width: 600px
border: 1px solid #000
.rollin
width: 100px
height: 100px
background: #000
animation:
duration: 1s
name: roll_in
iteration-count: 1
delay: 1s
fill-mode: backwards
@keyframes roll_in
from
margin-left: 100%
opacity: .3
to
margin-left: 0%
opacity: 1
这是生成的 CSS:
.container {
width: 600px;
border: 1px solid #000;
}
.rollin {
width: 100px;
height: 100px;
background: #000;
animation-duration: 1s;
animation-name: roll_in;
animation-iteration-count: 1;
animation-delay: 1s;
animation-fill-mode: backwards;
}
@keyframes roll_in {
from {
margin-left: 100%;
opacity: 0.3;
}
to {
margin-left: 0%;
opacity: 1;
}
}
在浏览器中的效果:

您可以在 SASS/CSS 文件中看到动画的进度。
CSS 动画的属性有:
-
animation-name: 此属性定义了应使用哪个@keyframs定义,例如:animation-name: roll_in -
animation-delay: 此属性定义了元素加载和动画开始之间的延迟时间,例如:animation-delay: 2s -
animation-duration: 此属性定义了动画的持续时间,例如:animation-duration: 2s -
animation-iteration-count: 此属性定义了动画应重复多少次,例如:animation- iteration-count: 2 -
animation-fill-mode: 此属性定义了元素在延迟时间方面的行为,例如:animation- fill-mode: backward
我如何在悬停时添加动画?让我们创建一个示例:
HTML:
<a href="" class="animation_hover">Element</a>
SASS:
.animation_hover
display: inline-block
padding: 20px
background: #d3d3d3
text-decoration: none
color: black
transition:
duration: .5s
property: all
&:hover
background: blue
color: white
CSS:
.animation_hover {
display: inline-block;
padding: 20px;
background: #d3d3d3;
text-decoration: none;
color: black;
transition-duration: 0.5s;
transition-property: all;
}
.animation_hover:hover {
background: blue;
color: white;
}
这是在浏览器中的最终结果:

您可以在悬停操作之前和之后看到元素。此外,还有一个过渡,为此按钮添加了一些动画效果。在这个动画声明中最重要的是什么?
transition-property
前面的声明给出了应该被动画化的值列表。这个列表的一个例子可能是:
Color, background-color
这个列表意味着颜色和背景颜色将被动画化。当您想要动画化所有属性时,可以使用all作为值。
数据属性
数据属性主要与 HTML 代码和 JavaScript 相关。使用数据属性,您可以描述 DOM 元素并在脚本中使用这些值,例如,用于排序、动画或任何其他目的。但它如何帮助您在 CSS 代码中呢?让我们考虑以下示例。
问题 - 悬停时加粗移动导航
这是网站上一个非常常见的问题。假设您有内联元素对悬停作出反应。悬停后,元素的字重从普通变为粗体。效果是悬停元素之后的每个元素都向右移动。让我们从 HTML 代码开始:
<ul>
<li><a href="#">First</a></li>
<li><a href="#">Second</a></li>
<li><a href="#">Third</a></li>
<li><a href="#">Fourth</a></li>
<li><a href="#">Fifth</a></li>
</ul>
SASS:
li, a
display: inline-block
text-align: center
a:hover
font-weight: bold
CSS:
li, a {
display: inline-block;
text-align: center;
}
a:hover {
font-weight: bold;
}
CSS:
li, a {
display: inline-block;
text-align: center;
}
a:hover {
font-weight: bold;
}
在浏览器中的效果,没有和有悬停操作:

红色标尺是结构中的指向性偏移。现在,让我们使用我们的antidotum。首先,我们需要轻微更改我们的 HTML 代码。这个变化与data-alt属性及其值有关。作为值,我们正在复制 DOM 元素的值:
HTML:
<ul class="bold_list_fix">
<li><a href="#" data-alt="First">First</a></li>
<li><a href="#" data-alt="Second">Second</a></li>
<li><a href="#" data-alt="Third">Third</a></li>
<li><a href="#" data-alt="Fourth">Fourth</a></li>
<li><a href="#" data-alt="Fifth">Fifth</a></li>
</ul>
SASS:
.bold_list_fix
a::after
display: block
content: attr(data-alt)
font-weight: bold
height: 1px
color: transparent
overflow: hidden
visibility: hidden
CSS:
.bold_list_fix a::after {
display: block;
content: attr(data-alt);
font-weight: bold;
height: 1px;
color: transparent;
overflow: hidden;
}
大功告成!正如您所看到的,这个技巧是基于:after伪元素,它现在被保留为一个不可见的元素。内容是通过从 HTML 代码中获取attr(data-alt)属性设置的。对这个内容,加粗特性被添加。这给了我们足够的空间,这在以前的代码中没有被占用。最后,元素不会向右移动。
摘要
在本章中,我们讨论了 CSS 渐变,因此您无需使用图像制作渐变。我们分析了box-shadow和text-shadow的使用。我们创建了一个简单的动画并分析了其参数。此外,我们在 CSS 代码中使用了数据属性。
在下一章中,我们将讨论 CSS 中的 DRY(即不要重复自己)并尝试创建一个基本框架,这将是您项目的起点。
第十章:不要重复自己-让我们创建一个简单的 CSS 框架
你有多少次做了一些工作,只是在下一个项目中重复了一遍?你有多少次想到了可重复使用的元素?在编码时,你应该考虑下一次在同一个或另一个项目上工作时可以省略多少操作。这意味着你需要使用以下内容:
-
自动化
-
代码模板或框架
这一章是关于构建可重用代码以及如何最终将其用作项目基础的。在这一章中,我们将涵盖以下主题:
-
为一个小而简单的 CSS 框架制定计划
-
创建你自己的网格系统
-
创建可重用元素
请记住,这段代码可以并且应该被扩展。所示的过程应该让你更加清楚如何利用你已经创建的框架来帮助自己,但仍然可以随着你的代码发展而发展。当然,你也可以使用其他框架。
文件结构
当你计划一个系统/框架时,文件结构是非常重要的。当你开始创建某些东西时,它需要一个演变。所以根据开发过程,你的系统在不断演变。当你的系统在演变时,它会发生很多变化。所以,让我们创建一个简单的结构:
-
有用的 mixin:
-
有用元素的简化形式
-
内联列表
-
基本元素
-
清除浮动
-
简单的渐变生成器
-
网格 mixin:
-
n 列中的第 n 列
-
表单:
-
输入/文本区样式助手
-
输入占位符
-
按钮:
-
内联(自动宽度)
-
全宽度
-
标准导航:
-
一级
-
两级
我们将使用 mixin 而不是已经创建的类。为什么?我们希望尽量减少 CSS 代码,这样当我们生成完整的 12 列网格时,我们将在媒体查询中的每个断点产生 12 个类。作为前端开发人员,我们希望创建尽可能少的代码。当然,我们可以重用一些类并用 SASS 扩展它们,但这个框架的主要方法是简单和可重用的 mixin。
有用元素的简化形式
在 CSS 代码(不仅仅是 CSS),每次重复代码的一部分时,你希望更快地获得最终效果。那么为什么不为一些 CSS 声明创建简短的形式呢?让我们看看我们可以做些什么来缩短它:
/* Text decoration */
=tdn
text-decoration: none
=tdu
text-decoration: underline
/* Text align */
=tac
text-align: center
=tar
text-align: right
=tal
text-align: left
/* Text transform */
=ttu
text-transform: uppercase
=ttl
text-transform: lowercase
/* Display */
=di
display: inline
=db
display: block
=dib
display: inline-block
/* Margin 0 auto */
=m0a
margin: 0 auto
现在,每次你想将一些文本转换为大写时,只需使用以下代码:
.sampleClass
+ttu
这是编译后的 CSS:
.sampleClass {
text-transform: uppercase;
}
另一个使用短 mixin 的例子是一个元素,它将显示为块元素,文本将居中显示:
.sampleClass
+db
+tac
这是编译后的 CSS:
.sampleClass {
display: block;
text-align: center;
}
其他 mixin
还有其他对我们的框架有用的 mixin:
-
渐变
-
动画
-
清除浮动
让我们从渐变 mixin 开始:
=linearGradientFromTop($startColor, $endColor)
background: $startColor /* Old browsers */
background: -moz-linear-gradient(top, $startColor 0%, $endColor 100%)
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, $startColor), color-stop(100%, $endColor))
background: -webkit-linear-gradient(top, $startColor 0%, $endColor 100%)
background: -o-linear-gradient(top, $startColor 0%, $endColor 100%)
background: -ms-linear-gradient(top, $startColor 0%, $endColor 100%)
background: linear-gradient(to bottom, $startColor 0%, $endColor 100%)
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#{$startColor}', endColorstr='#{$endColor}',GradientType=0 )
=linearGradientFromLeft($startColor, $endColor)
background-color: $startColor
background: -webkit-gradient(linear, left top, right top, from($startColor), to($endColor))
background: -webkit-linear-gradient(left, $startColor, $endColor)
background: -moz-linear-gradient(left, $startColor, $endColor)
background: -ms-linear-gradient(left, $startColor, $endColor)
background: -o-linear-gradient(left, $startColor, $endColor)
background: linear-gradient(left, $startColor, $endColor)
filter: progid:DXImageTransform.Microsoft.gradient(startColorStr='#{$startColor}', endColorStr='#{$endColor}', gradientType='1')
全部动画:
=animateAll($time)
-webkit-transition: all $time ease-in-out
-moz-transition: all $time ease-in-out
-o-transition: all $time ease-in-out
transition: all $time ease-in-out
清除浮动
不要忘记在你的私人 SASS 框架中的 mixin 中添加clearfix。你将使用它作为 mixin 的调用或作为一个类,并且所有其他元素将扩展之前创建的类:
=clearfix
&:after
content: " "
visibility: hidden
display: block
height: 0
clear: both
每次你想创建一个可重用的clearfix类时,可以这样做:
.clearfix
+clearfix
这是编译后的 CSS:
.clearfix:after {
content: " ";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
或者可以写一个更简短的版本:
.cf
+clearfix
这是编译后的 CSS:
.cf:after {
content: " ";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
现在,你可以在 SASS 代码中使用@extend来扩展它:
.element
@extend .cf
这是编译后的 CSS:
.cf:after, .element:after {
content: " ";
visibility: hidden;
display: block;
height: 0;
clear: both;
}
将绝对元素居中在另一个相对元素中:
/* Absolute center vertically and horizontally */
=centerVH
position: absolute
top: 50%
left: 50%
-ms-transform: translate(-50%,-50%)
-webkit-transform: translate(-50%,-50%)
transform: translate(-50%,-50%)
媒体查询
在每个响应式网页项目中,你都需要创建媒体查询。你需要选择要实施的步骤,然后开始根据这些步骤创建项目。
媒体查询模板
媒体查询非常简单易用。媒体查询的主要问题是可重用的步骤,你可以将它们保存在一个地方。在一些项目中,你需要添加更多的查询,因为项目可见性问题或一些额外的代码会影响你的代码。让我们专注于如何通过一些设置来做一次,然后在我们的代码中使用它。
基本设置集中在以下内容上:
-
移动设备(手机)
-
移动设备(平板)
-
桌面设备
-
桌面设备(大屏)
在某些情况下,你可以扩展这个列表,加入移动设备位置(纵向和横向),但是更少的媒体查询对于维护来说更好更容易。那么我们如何保持这些尺寸呢?
-
$small:320 像素 -
$medium:768 像素 -
$large:1024 像素
网格
在标准的 HTML/CSS 项目中,最常见的元素是网格。当然,你可以使用别人的网格或从 CSS 框架(如 Bootstrap 或 Foundation)中获取。从头开始创建它很难吗?并不是真的。在本章中,我们将创建一个基本的网格系统,并将使用它来看看它是如何创建行和列的。
标准网格 16/12
标准网格是基于 16 列或 12 列系统的。这两种系统的优势是什么?这取决于你的结构。例如,分析布局后,假设你需要:
-
3 列组合
-
2 列组合
-
6 列组合
因此,你可以使用 12 列系统。但是,正如你所看到的,你需要坚持这个系统,那么你如何创建自己的代码,使其更有弹性呢?你可以使用以下命名约定:
.grid-NofK
这里,N是列数,K是分隔符,例如:
.grid-3of12
.grid-5of6
当你在处理网格时,你需要记住有时你需要从左边推一些列。这种情况是当你需要创建.push类时:
.push-NofK
这种命名约定的优点是什么?没有静态分隔符。在经典网格中,你有一个有 12 列或 16 列及其组合的网格。这里是逐个类写的网格示例:
12 列网格:
.grid-1of12 {
width: 8.33%
}
.push-1of12 {
margin-left: 8.33%
}
.grid-2of12 {
width: 16.66%
}
.push-2of12 {
margin-left: 16.66%
}
.grid-3of12 {
width: 25%
}
.push-3of12 {
margin-left: 25%
}
.grid-4of12 {
width: 33.33%
}
.push-4of12 {
margin-left: 33.33%
}
.grid-5of12 {
width: 41.66%
}
.push-5of12 {
margin-left: 41.66%
}
.grid-6of12 {
width: 50%
}
.push-6of12 {
margin-left: 50%
}
.grid-7of12 {
width: 58.33%
}
.push-7of12 {
margin-left: 58.33%
}
.grid-8of12 {
width: 66.66%
}
.push-8of12 {
margin-left: 66.66%
}
.grid-9of12 {
width: 75%
}
.push-9of12 {
margin-left: 75%
}
.grid-10of12 {
width: 83.33%
}
.push-10of12 {
margin-left: 83.33%
}
.grid-11of12 {
width: 91.66%
}
.push-11of12 {
margin-left: 91.66%
}
.grid-12of12 {
width: 100%
}
.push-12of12 {
margin-left: 100%
}
16 列网格:
.grid-1of16 {
width: 6.25%
}
.push-1of16 {
margin-left: 6.25%
}
.grid-2of16 {
width: 12.5%
}
.push-2of16 {
margin-left: 12.5%
}
.grid-3of16 {
width: 18.75%
}
.push-3of16 {
margin-left: 18.75%
}
.grid-4of16 {
width: 25%
}
.push-4of16 {
margin-left: 25%
}
.grid-5of16 {
width: 31.25%
}
.push-5of16 {
margin-left: 31.25%
}
.grid-6of16 {
width: 37.5%
}
.push-6of16 {
margin-left: 37.5%
}
.grid-7of16 {
width: 43.75%
}
.push-7of16 {
margin-left: 43.75%
}
.grid-8of16 {
width: 50%
}
.push-8of16 {
margin-left: 50%
}
.grid-9of16 {
width: 56.25%
}
.push-9of16 {
margin-left: 56.25%
}
.grid-10of16 {
width: 62.5%
}
.push-10of16 {
margin-left: 62.5%
}
.grid-11of16 {
width: 68.75%
}
.push-11of16 {
margin-left: 68.75%
}
.grid-12of16 {
width: 75%
}
.push-12of16 {
margin-left: 75%
}
.grid-12of16 {
width: 81.25%
}
.push-12of16 {
margin-left: 81.25%
}
.grid-12of16 {
width: 87.5%
}
.push-12of16 {
margin-left: 87.5%
}
.grid-12of16 {
width: 93.75%
}
.push-12of16 {
margin-left: 93.75%
}
.grid-12of16 {
width: 100%
}
.push-12of16 {
margin-left: 100%
}
写了很多东西……
现在,我们需要创建一个可以在媒体查询和响应式网站上使用的代码。在最流行的 CSS 框架(如 Bootstrap 和 Foundation)中,你可以为手机/平板/桌面使用类:
<div class="small-2 medium-4 large-5">
</div>
例如,当分隔符设置为12时,你将在小设备上看到这个框是2列宽,中等设备上是4列宽,大文档上是5列宽。我们可以创建所有这些类,但我建议你创建一个 mixin,我们可以在 CSS 中描述的每个元素中调用它。
SASS 代码将如下所示:
=grid($columns, $divider)
width: percentage($columns/$divider)
=push($columns, $divider)
margin-left: percentage($columns/$divider)
我们如何在 SASS 代码中使用它?假设我们有一个基于网格16的块,并且我们想要给它宽度为12的16,并用2的16推动它:
.gridElement
+grid(12, 16)
+push(2, 16)
这是编译后的 CSS:
.gridElement {
width: 75%;
margin-left: 12.5%;
}
标准可重用结构
作为前端开发人员,你总是在努力处理可重复的元素。在几乎所有情况下,你会觉得自己在试图重复造轮子,那么你可以做些什么来避免重复呢?让我们创建一些标准和可重用的结构。
可重用的多级菜单
多级菜单是最可重用的代码。所有更大的网站都有一个你可以描述为可重用代码的菜单。
让我们从 HTML 代码开始:
<ul class="menu-multilevel">
<li>
<a href="#">Level one - item one</a>
<ul>
<li><a href="#">Level two - item one</a></li>
<li><a href="#">Level two - item two</a></li>
<li><a href="#">Level two - item three</a></li>
<li><a href="#">Level two - item four</a></li>
</ul>
</li>
<li>
<a href="#">Level two - item one</a>
<ul>
<li><a href="#">Level two - item one</a></li>
<li><a href="#">Level two - item two</a></li>
<li><a href="#">Level two - item three</a></li>
<li><a href="#">Level two - item four</a></li>
</ul>
</li>
<li>
<a href="#">Level one - item three</a>
<ul>
<li><a href="#">Level three - item one</a></li>
<li><a href="#">Level three - item two</a></li>
<li><a href="#">Level three - item three</a></li>
<li><a href="#">Level three - item four</a></li>
</ul>
</li>
</ul>
SASS 代码:
ul.menu-multilevel
list-style: none
padding: 0
ul.menu-multilevel > li
float: left
display: inline-block
position: relative
margin-right: 10px
&:hover
ul
display: block
width: 200px
ul.menu-multilevel ul
display: none
position: absolute
left: 0
li
display: block
这是编译后的 CSS:
ul.menu-multilevel {
list-style: none;
padding: 0;
}
ul.menu-multilevel > li {
float: left;
display: inline-block;
position: relative;
margin-right: 10px;
}
ul.menu-multilevel > li:hover ul {
display: block;
width: 200px;
}
ul.menu-multilevel ul {
display: none;
position: absolute;
left: 0;
}
ul.menu-multilevel ul li {
display: block;
}
现在,让我们稍微重建这个代码,以在 SASS 中创建一个可重用的 mixin:
=memuMultilevel
list-style: none
padding: 0
& > li
float: left
display: inline-block
position: relative
margin-right: 10px
&:hover
ul
display: block
width: 200px
& ul
display: none
position: absolute
left: 0
li
display: block
要使用它,你需要像这样调用一个 mixin:
ul.menu-multilevel
+memuMultilevel
生成的 CSS:
ul.menu-multilevel {
list-style: none;
padding: 0;
}
ul.menu-multilevel > li {
float: left;
display: inline-block;
position: relative;
margin-right: 10px;
}
ul.menu-multilevel > li:hover ul {
display: block;
width: 200px;
}
ul.menu-multilevel ul {
display: none;
position: absolute;
left: 0;
}
ul.menu-multilevel ul li {
display: block;
}
如何创建可重用的按钮
按钮是下一个你可以看到和重复使用的元素。让我们考虑一下按钮参数。当然,我们需要有机会设置背景和字体颜色。我们需要有机会改变边框颜色和填充。
让我们从一个简单的 CSS 定义开始:
.button {
padding: 5px 10px;
background: #ff0000;
color: #fff;
}
因此,基于此,mixin 在 SASS 中可以如下所示:
=button($bgc, $fc)
display: inline-block
background: $bgc
color: $fc
这里:
-
$bgc:背景颜色 -
$fc:字体颜色
要使用这个 mixin,你只需要执行这个:
.button
padding: 5px 10px
+button(#ff0000, #fff)
这是编译后的 CSS:
.button {
padding: 5px 10px;
display: inline-block;
background: #ff0000;
color: #fff;
}
你如何扩展这个 mixin?让我们考虑一下其他可以参数化的值。当然,边框半径。所以,让我们添加一个新的 mixin:
=roundedButton($bgc, $fc, $bc, $br)
background: $bgc
color: $fc
border-color: $bc
border-radius: $br
这里:
-
$bc:边框颜色 -
$br:边框半径
让我们使用这个 mixin:
.roundedButton
+roundedButton(black, white, red, 5px)
这是编译后的 CSS:
.roundedButton {
background: black;
color: white;
border-color: red;
border-radius: 5px;
}
如果你需要创建一堆有三种尺寸的按钮,你可以这样做:
.button
+button(#ff0000, #fff)
.small
padding: 5px 10px
.medium
padding: 10px 20px
.large
padding: 15px 30px
这是编译后的 CSS:
.button {
display: inline-block;
background: #ff0000;
color: #fff;
}
.button .small {
padding: 5px 10px;
}
.button .medium {
padding: 10px 20px;
}
.button .large {
padding: 15px 30px;
}
收集其他可重用的 mixin
我们需要一堆有用的可重用的 mixin。还有什么可以额外帮助的?让我们想一想:
-
基本元素
-
内联列表
基本元素
正如你可能还记得之前的章节中所提到的,我们一直在使用基元。创建基元的 mixin 列表可以成为我们框架非常有用和有帮助的一部分。我们将为以下内容创建 mixin:
-
矩形(带或不带填充)
-
圆/环
-
三角形
让我们快速回顾一下:
=rectangle($w, $h, $c)
width: $w
height: $h
background: $c
=square($w, $c)
width: $w
height: $w
background: $c
=circle($size, $color)
width: $size
height: $size
border-radius: 50%
background: $color
=ring($size, $color, $width)
width: $size
height: $size
border-radius: 50%
border: $width solid $color
background: none
=triangleRight($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height/2 0 $height/2 $width
border-color: transparent transparent transparent $color
=triangleLeft($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height/2 $width $height/2 0
border-color: transparent $color transparent transparent
=triangleTop($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: 0 $width/2 $height $width/2
border-color: transparent transparent $color transparent
=triangleBottom($width, $height, $color)
width: 0
height: 0
border-style: solid
border-width: $height $width/2 0 $width/2
border-color: $color transparent transparent transparent
让我们测试和使用我们的框架
为了检查我们的框架是如何工作的,以及添加所有内容有多容易,让我们创建一个博客模板。在这个模板中,让我们包括视图:
-
帖子列表
-
单个帖子
-
单页
让我们创建区域:
-
页眉
-
页脚
-
内容
这是我们简化的设计:

让我们从博客页面(主页)的简单结构开始:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<link rel="stylesheet" href="css/master.css" media="screen" title="no title" charset="utf-8">
</head>
<body>
<header>
<h1>FEDojo.com</h1>
<h2>Front End Developers Blog</h2>
</header>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<main>
<article class="main--article">
<a href="#">
<img src="img/error_log.png" alt=""/>
<span class="comments"></span>
</a>
<h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit</h3>
<p>
sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit
in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<a href="#" class="readmore">Read more</a>
</article>
</main>
<footer>
<div class="wrapper">
<div class="column">
Left column
</div>
<div class="column">
Right column
</div>
</div>
</footer>
</body>
</html>
正如你所看到的,我们有一个基于标签的结构:
-
页眉
-
导航
-
主要
-
页脚
这是我们的文件结构:

让我们描述页眉:
header
h1
+tac
margin-bottom: 0
h2
+tac
font-size: 16px
margin-top: 0
margin-bottom: 30px
描述页脚:
footer
width: 100%
background: #d3d3d3
padding: 50px 0
.wrapper
+m0a /* margin 0 auto */
+clearfix
max-width: $wrapper
.column
width: 50%
float: left
描述导航:
nav
background: black
text-align: center
ul
+navigation
a
color: white
+ttu
padding: 10px
在fed目录中,我们存储可重复使用的代码(我们的框架)。在其余的目录中,我们存储与项目相关的代码。在描述结构中,我们存储在所有视图上重复的元素的样式。在视图目录中,我们将保留与特定视图相关的元素的样式。
记住!
当你创建一些可重复使用的代码甚至任何其他代码时,你需要留下评论。出于某种原因,程序员们当前(并且不礼貌地)趋向于不添加评论“他们的代码不需要额外的描述”。另一种思路是,“那是我的代码。我知道我在写什么”。你认为把它留下是公平的吗?当然,答案是否定的!即使你的记忆也不完美。你可能会忘记你在代码中的意思和目的是什么。建议你至少为自己和将来在项目上工作的其他人写一些简短的评论。
在 Github 和 Bitbucket 的黄金时代,你可以在几秒钟内分享你的代码,并与来自世界另一部分的另一位程序员一起工作,他可以 fork 你的代码或为你的项目做出贡献。
摘要
正如你所看到的,有很多可重复使用的结构,每次创建新项目时都可以装饰。最好是写一次东西,然后添加一些新功能,而不是每次都写一些东西并描述可重复的元素。
在下一章中,我们将尝试创建一个简单的 CSS 框架,其中包含准备好使用的组件!
第十一章:邮件客户端基础知识
本章是关于构建邮件客户端和创建正确结构的基本方面。因为为邮件客户端构建正确的结构并不容易,而且仍然与 HTML 结构的老派思维有关,只有少数教程展示了如何从头到尾完成。为什么?让我们开始吧!
在本章中,我们将涵盖:
-
为邮件客户端创建一个简单的结构
-
了解邮件客户端中可能和不可能的事情
-
比较最知名的邮件客户端,包括 Outlook 和 Gmail
-
回到基于表格的 HTML 结构的老派思维
测试您的邮件客户端
由于需要在计算机上安装一堆邮件客户端,测试电子邮件的过程变得复杂。这当然与您需要安装以下操作系统有关:
-
Microsoft Outlook 2007/2010/2013
-
Microsoft Outlook 2003/Express
-
Microsoft Outlook.com
-
iPhone 邮件
-
Apple Mail
-
Gmail
-
雅虎电子邮件
这一大堆邮件客户端相当长,测试所有这些邮件客户端将会有问题。但您可以在工作流程中使用一些电子邮件测试工具。有一些在线工具的列表,例如 Litmus,稍后将在本章中介绍。
回到表格
表格结构是构建防弹电子邮件模板的最流行方法。它看起来像是从过去传来的。所以,让我们带来过去的风味,让我们开始创建正确的结构:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
<meta name="viewport" content="width=device-width"/>
<meta name="format-detection" content="telephone=no">
<title>Untitled Document</title>
</head>
<body>
<style type="text/css">
.class {} /* here will be your code */
</style>
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<!-- HERE your content -->
</table>
</body>
</html>
你可能会问,“但 HTML5 声明在哪里?为什么样式没有包含在rel标签的链接中?”这是因为电子邮件客户端中包含的旧 HTML 解释器以及使用较新的doctype可能会导致兼容性问题。目前,我们有一个骨架。让我们开始编写样式:
那么为什么我们要使用代码的这一部分?
<meta name="format-detection" content="telephone=no">
这段代码与 iOS 特定问题有关。它改变了输入电话号码的行为,该电话号码(在 iOS 上)被检测并更改为一个交互链接,您可以点击并开始拨打电话。
重置样式
在 CSS 代码中,有很多代码应该用于重置所有浏览器上的行为。同样的情况也发生在邮件客户端中。有一堆声明应该附加到您的样式部分,并且将帮助您提供防弹邮件客户端。那么我们可以添加什么作为重置器?
body {
margin: 0;
padding: 0;
min-width: 100% !important;
}
删除边距和填充的第一个声明非常重要。这个声明来自标准的互联网浏览器。正如你所看到的,min-width也出现了。如代码中所述,这是非常重要的一行!在值中,有100% !important。是的!值和!important之间没有空格。以下代码是邮件客户端的重置样式的一部分:
body,
table,
td,
a {
-webkit-text-size-adjust: 100%; // IOS specific
-ms-text-size-adjust: 100%; // Windows mobile
}
.ExternalClass {
width: 100%;
}
.ExternalClass,
.ExternalClass p,
.ExternalClass span,
.ExternalClass font,
.ExternalClass td,
.ExternalClass div {
line-height: 100%;
}
什么是ExternalClass?这个类与将在 Outlook 或 Hotmail 中显示的模板有关。将这一大堆类设置到您的<style>标签中是一个很好的方法。这将最小化可能在特定邮件客户端上出现的问题。以下代码包含 mso-前缀。这意味着它与 Microsoft Office 有关。
table {
mso-table-lspace: 0pt;
mso-table-rspace: 0pt;
}
这段代码与 Microsoft Outlook 有关。它将重置边框中的额外空间:
#outlook a{
padding:0;
}
h1,
h2,
h3,
h4,
h5,
h6 {
color: <your_color>!important;
}
h1 a,
h2 a,
h3 a,
h4 a,
h5 a,
h6 a {
color: <your_color>!important;
}
h1 a:active,
h2 a:active,
h3 a:active,
h4 a:active,
h5 a:active,
h6 a:active {
color: <your_color>!important;
}
h1 a:visited,
h2 a:visited,
h3 a:visited,
h4 a:visited,
h5 a:visited,
h6 a:visited {
color: <your_color>!important;
}
img{
-ms-interpolation-mode:bicubic;
border: 0;
height: auto;
line-height: 100%;
outline: none;
text-decoration: none;
}
通过媒体查询定位特定设备
要构建一个防弹邮件客户端,您将需要为一些特定的邮件客户端和设备使用特定的代码。这更难做,因为调试存在问题(没有很好的调试器/检查器来实时检查行为)。我们需要哪些设备?让我们创建一个列表:
-
带有视网膜和非视网膜显示器的 iPad 或 iPhone
-
Android 设备:
-
低密度(像素比小于 1)
-
中密度(像素比等于 1)
-
高密度(像素比大于 1)
@media only screen and (max-device-width: 480px) {
}
这个集合将匹配平板电脑和小屏幕:
@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) {
}
视网膜显示器是 iOS 设备(如 iPhone、iPod 和 iPad)所知的。可以使用这个媒体查询来定位这些设备:
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
}
针对低密度 Android 布局:
@media only screen and (-webkit-device-pixel-ratio: .75) {
}
针对中密度 Android 布局:
@media only screen and (-webkit-device-pixel-ratio: 1) {
}
针对高密度 Android 布局:
@media only screen and (-webkit-device-pixel-ratio: 1.5) {
}
如果你想要针对 Outlook 2007 和 2010,你需要使用 HTML 条件结构。它看起来像这样:
<!--[if gte mso 9]>
<style>
/* Your code here */
</style>
<![endif]-->
电子邮件模板中的 CSS 属性
重要的是要记住你可以使用哪些属性以及有哪些例外。这些知识将使你免于许多紧张的情况。让我们列举一下:
| 属性 | 特定客户端/设备的问题 |
|---|---|
direction |
- |
font |
- |
font-family |
- |
font-style |
- |
font-variant |
- |
font-size |
- |
font-weight |
- |
letter-spacing |
- |
line-height |
(iOS) 默认字体大小为 13px |
text-align |
(Outlook) 不要将 line-height 附加到TD元素。建议将此属性附加到P元素。 |
text-decoration |
- |
text-indent |
- |
background |
(Outlook) 不支持背景图片 |
background-color |
- |
border |
- |
padding |
(Outlook) 不支持元素的填充:<p>``<div>``<a> |
width |
(Outlook) 不支持元素的宽度:<p>``<div>``<a> |
list-style-type |
- |
border-collapse |
- |
table-layout |
- |
你可以看到,有很多属性在所有电子邮件客户端上的工作方式都不同。这是一个大问题,但是有了基本的知识,你就会知道哪些元素可以用 CSS 描述。邮件发送者中最大的问题是定位,这是不受支持的。所以例如,在大多数情况下,当文本溢出某些图像时,你需要使用包含文本的图像。
响应式电子邮件模板
这本书的这一部分可能会引发一场大讨论,因为在所有电子邮件客户端中都不可能构建响应式电子邮件。这是一个可以用作电子邮件模板基础的工作草案:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html >
<head>
<title>Our responsive template</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<style type="text/css">
@media screen and (max-width: 525px) {
.wrapper {
width: 100% !important;
}
.content {
padding: 10px 5% 10px 5% !important;
text-align: left;
}
}
</style>
</head>
<body style="margin: 0 !important;
padding: 0 !important;">
<table border="0"
cellpadding="0"
cellspacing="0"
width="100%">
<tr>
<td bgcolor="#ffffff"
align="center"
style="padding: 10px;">
<table border="0"
cellpadding="0"
cellspacing="0"
width="500"
class="wrapper">
<tr>
<td>
<table width="100%"
border="0"
cellspacing="0"
cellpadding="0">
<tr>
<td align="left"
style="font-size: 40px;
font-family: Helvetica, Arial, sans-serif;
color: #000000;
padding-top: 10px;"
class="content">Header of our mailer
</td>
</tr>
<tr>
<td align="left"
style="padding: 20px 0 0 0;
font-size: 16px;
line-height: 25px;
font-family: Helvetica, Arial, sans-serif;
color: #000000;
padding-bottom: 30px;"
class="content">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed
varius, leo a ullamcorper feugiat, ante purus sodales justo, a faucibus libero lacus
a est. Aenean at mollis ipsum.
</td>
</tr>
<tr>
<td align="center" class="content">
<table width="100%"
border="0"
cellspacing="0"
cellpadding="0">
<tr>
<td align="left">
<table
border="0"
cellspacing="0"
cellpadding="0">
<tr>
<td align="center"
bgcolor="#000"><a href="#"
target="_blank"
style="font-size: 20px;
font-family: Helvetica, Arial, sans-serif;
color: #ffffff;
text-decoration: none;
color: #ffffff;
text-decoration: none;
padding: 10px 20px;
display: inline-block;">
Lorem ipsum click
</a>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
你可以看到,有很多代码...但是当我们想要将其与普通网站进行比较时,效果并不是很好。以下截图显示了在宽度大于 520px 的桌面浏览器中的外观:

在较小的浏览器(小于 520px)中,你会看到这个:

内联电子邮件模板
在推送项目之前,对电子邮件模板进行内联处理是一个非常重要的过程,当你使用单独的 CSS 文件或者 CSS 代码写在<style>部分时—foundation.zurb.com/e-mails/inliner-v2.html。
电子邮件模板开发提示
与前端开发相关的其他流程一样,这应该从准备好的设计开始。真正的网页设计师知道一个好网站的边界在哪里,也应该知道与邮件发送者相关的边界在哪里。在全局电子邮件创建过程中有很多限制。这就是为什么参与这个过程的设计师应该知道可以在 HTML 电子邮件模板中使用的功能。
ZURB 的电子邮件模板框架 INK
这个开发过程更简单,有一些收集了经过测试的代码片段的框架。ZURB 在创建了伟大的前端框架 Foundation 之后,为电子邮件模板创建了 INK 作为框架。关于这个框架的完整信息,建议访问foundation.zurb.com/e-mails.html。

基于 INK 创建的电子邮件模板非常适合开发人员。该框架收集了许多易于使用的组件,如网格系统、按钮、缩略图,你可以轻松地添加到你的模板中。此外,还有一系列可调参数,如间距、全局填充和边距。为了更深入地了解 ZURB INK2 框架,建议查看官方文档:foundation.zurb.com/emails/docs/。
在 Litmus 上进行测试
当您想要收集所有测试环境时,电子邮件模板的测试就会变得非常复杂。使用 Litmus 会更容易,它会在大多数已知的电子邮件客户端中对您的电子邮件模板进行截图。
使用 Litmus 进行测试
创建模板后,您需要复制 HTML 代码并将其粘贴到系统中。如果您的电子邮件中有一些托管在某个服务器上的图片,您可以发送电子邮件到 Litmus 中的您的账户。Litmus 在应用程序端创建了您专用的电子邮件地址。当您发送电子邮件到此地址时,您可以在 Litmus 中测试此电子邮件。
使用 Litmus 进行测试
如您在上面的屏幕上所见,您可以在大多数已知的电子邮件客户端中检查您的代码。截图是在 Litmus 账户的试用版本上制作的,因此一些视图未被激活。
总结
准备防弹电子邮件模板是一个复杂的过程。为什么?正如您所见,HTML 和 CSS 在您熟悉的标准网络浏览器中表现得非常奇怪,不太符合逻辑。当然,所有这些过程都可以被描述,并且有一个工作流程可以帮助您在不紧张的情况下构建邮件发送程序。电子邮件模板带来的限制清单非常长,但对基础知识的良好掌握和电子邮件模板开发经验可以使您成为这个前端领域的专家。
在下一章中,我们将讨论 CSS 代码的可扩展性和模块化。您将更多地了解方法论和命名约定。让我们开始吧!
第十二章:可扩展性和模块化
在本章中,我们将介绍在创建模块化和可扩展代码的过程中最知名的 CSS 方法论。这是一个非常有趣的主题,因为有很多方法论。每种方法论都有其优缺点。在本章中,我们将对它们有一个基本的了解。
我们将涵盖以下主题:
-
构建可扩展和模块化的代码
-
CSS 方法论
-
SMACSS
-
BEM
-
OOCSS
-
如何选择正确的方法论?
构建可扩展和模块化的代码
构建良好代码的过程对每个开发者来说都是独特的。但是你如何构建易扩展的 CSS 代码?此外,这段代码需要是模块化的。
方法论中最重要的是命名约定。你可以为你的项目使用适当的方法论,但你也可以错误地使用它并附加不良的类名。你是否曾经见过类似这样的项目,其中类名和定义类似于这样的:
.padding-0 {
padding: 10px;
}
正如你所看到的,类名被创建为使用值0进行填充,但最终它的值不等于0。这可以是一个不良的命名约定的例子。还有更多不良使用名称的例子:
.marginTop10 {
padding-top: 50px;
}
方法论中的第二个重要事项是文档中类/元素的结构和嵌套级别。一些来源说,最大嵌套级别不应大于五,而其他人说三。为了可读性,代码应该具有完全平坦的结构(只有一级)。
让我们来看看流行的 CSS 方法论,学习它们的最佳特点。
CSS 方法论
CSS 方法论的目的是使构建代码的过程更可预测和更有组织。最知名的方法论如下:
-
可扩展和模块化的 CSS 架构(SMACSS)
-
面向对象的 CSS(OOCSS)
-
块元素修饰符(BEM)
每种方法论都有不同的特点。让我们看看这些流行的方法论能提供什么。
SMACSS
SMACSS 是由 Jonathan Snook 创建的。它更像是一个框架而不是一个方法论:

有关该项目的官方网站,请访问smacss.com/。
SMACSS 基于以下规则:
-
基本规则
-
布局规则
-
模块规则
-
状态规则
-
主题规则
基本规则
基本规则与相关元素:
-
标题(
h1-h6) -
链接(
a,a:hover,a:active) -
表单(
form,input)
所有这些规则都与 HTML 元素相关,不应该需要!important语句。
布局规则
布局规则与结构中的主要块相关,例如这些:
-
header -
footer -
content -
sidemenu -
article
这些元素的描述如下:
CSS:
#header {
display: inline-block;
}
#footer {
display: inline-block;
padding: 10px;
}
模块规则
模块规则与网站上的组件或块相关。让我们以先前为博客文章创建的结构的一个示例片段为例。在这里,我们将更好地了解如何在这种特定情况下使用 SMACSS 模块:

要在 CSS 中描述它,我们需要使用基于以下内容的选择器:
.module > element / class
让我们为其构建一个 HTML:
<article class="article">
<img src="img/#">
<h1>Lorem ipsum dolor sit amet, consecteur adisiciping elit</h1>
<p> Lorem ipsum … </p>
<a href="#">Read more</a>
</article>
让我们基于模块规则创建选择器:
.article >img {
/* Image in top */
}
.article > h1 {
/* Post header */
}
.article > p {
/* Post excerpt */
}
.article > a {
/* Read more button */
}
创建所有这些是相当容易和明显的。
状态规则
状态规则与元素的状态相关。有许多可能的状态规则类。以下是可能的规则列表:
-
is-collapsed -
is-error -
is-active -
is-tab-active
描述状态规则最简单的方法是通过一个简单的导航示例:
<nav>
<ul>
<li class="is-active"><a href="#">Home</a>
<ul>
<li><a href="#">Home 1.1</a></li>
<li><a href="#">Home 1.2</a></li>
</ul>
</li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
<ul>
</nav>
要描述当前活动的菜单中的元素,可以使用类is-active。这种约定易于阅读,并为你提供了正确的类名的机会。
主题规则
主题规则与特定视图相关。例如,你创建了一个带有元素的页面:
HTML 如下:
<body>
<div class="alert">
Alert
</div>
</body>
我们最初所知道的是.alert是一个窗口,需要粘在浏览器上,就像一个灯箱窗口一样。
CSS(在alert.css中)如下:
.alert {
width: 300px;
height: 300px;
position: fixed;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
现在我们需要为这个.alert(在theme.css中)添加一个特定的主题:
.alert {
background: red;
color: black;
}
正如我们在alert.css中看到的,我们将静态元素的定义保留在theme.css中不会改变。保留在theme.css中的主题规则是为我们的组件进行主题设置;在这种情况下,它是一个alert窗口。
SMACSS 摘要
由于以下原因,SMACSS 是一个非常好的方法:
-
它有收集主要元素定义的基本规则
-
它有描述元素状态的状态规则,使用
is-约定 -
它在 CSS 中使用主要元素的 ID
OOCSS
OOCSS 是由 Nicole Sullivan 发起的一个项目或方法:

访问项目的官方网站oocss.org/获取更多信息。
OOCSS 的主要原则如下:
-
分离结构和皮肤
-
分离容器和内容
这是什么意思?让我们试着深入挖掘一下。
这意味着最好描述嵌套在另一个元素中的元素时,使用一个单独的类,而不是嵌套在容器中。当你创建这样的代码时:
<div class="product">
<h1>Name of product</h1>
<p>Description</p>
</div>
你不应该基于选择器来编写你的 CSS:
.product h1 {}
.product p {}
而不是在标记中进行小改变:
<div class="product">
<h1 class="product-name">Name of product</h1>
<p class="product-desc">Description</p>
</div>
然后用选择器在 CSS 中描述它:
.product-name {}
.product-desc {}
它让你有可能将类.product-name移动到 HTML 结构中的任何元素,视觉特性也会随之改变,如描述的那样。这给了你更多的灵活性和可重用的代码。
在我们的示例中使用 OOCSS
让我们尝试在我们的示例代码中使用 OOCSS 来描述博客文章:
<article class="article">
<img src="img/#" class="article-image">
<h1 class="article-h1">Lorem ipsum dolor sit amet, consecteur adisiciping elit</h1>
<p class="article-p"> Lorem ipsum … </p>
<a href="#" class="article-btn">Read more</a>
</article>
在你的 CSS 中,它会是这样的:
.article { /**/}
.article-image { /**/ }
.article-h1 { /**/ }
.article-p { /**/ }
.article-btn { /**/ }
OOCSS 摘要
让我们总结一下 OOCSS:
-
你可以在 HTML 中任何地方重用类,而不需要考虑它是在哪个模块中描述的
-
这种方法非常成熟
块元素修饰符(BEM)
下一个方法是由 Yandex 构建的。在 BEM 方法中,每个元素都用一个类来描述。由于平面 CSS 结构,不需要嵌套。命名约定基于:

访问项目的官方网站en.bem.info/获取更多信息。
在我们的示例中使用 BEM
让我们尝试在我们的示例代码中使用 BEM 来描述博客文章:
<article class="article">
<img src="img/#" class="article__image">
<h1 class="article__h1">Lorem ipsum dolor sit amet, consecteur adisiciping elit</h1>
<p class="article__p"> Lorem ipsum … </p>
<a href="#" class="article__btn">Read more</a>
</article>
现在在你的 CSS 中,它会是这样的:
.article { /**/}
.article__image { /**/ }
.article__h1 { /**/ }
.article__p { /**/ }
.article__btn { /**/ }
在 SASS 中使用 BEM
在 SASS 中构建 BEM 代码不应该很难。让我们尝试描述前面代码中的代码:
.article
&__image
/* Image in top */
&__h1
/* Post header */
&__p
/* Post paragraph */
&__btn
/* Post button */
如何使用修饰符?
前面的代码示例是基于 BEM 方法中的块和元素。我们如何添加M及其修饰符?我们什么时候可以使用它?让我们想象一下,我们有两篇文章:一篇文章左侧有一张图片,第二篇文章右侧有一张图片。使用 BEM 方法,我们可以使用一个修饰符。让我们拿上一个 CSS 代码并附加修饰符:
.article { /**/}
.article__image { /**/ }
.article__h1 { /**/ }
.article__p { /**/ }
.article__btn { /**/ }
.article--imgleft { /**/}
.article--imgleft__image { /**/ }
.article--imgleft__h1 { /**/ }
.article--imgleft__p { /**/ }
.article--imgleft__btn { /**/ }
正如我们所看到的,修饰符被定义为imgleft,并使用两个破折号添加到块中。修饰符可以帮助你避免为新块创建新代码。它可以像在 CSS 中实现的装饰器一样工作。
你应该使用哪种方法?
这是一个非常好的问题。毫无疑问,你需要使用适合你的方法。但哪一种适合?最好的 CSS 方法是可以轻松调试的方法。什么时候呢?毫无疑问,当你不需要深入挖掘时,比如,一个元素有 10 条规则。在 CSS 中最好的可读性是当规则严格与页面上的元素相关联时。
也许是你自己的方法?
是的!如果你想为你的项目创建一些新的东西,创建你自己的方法。但是,不要重复造轮子,也不要试图重命名已知的方法来构建你自己的方法。对这三种方法的深入理解可能是你创建一个符合你要求的小型未命名混搭的关键。
摘要
现在应该更容易选择适合您的代码/项目的正确方法论了。在本章中,我们熟悉了 CSS 方法论,并试图定义它们的方法。最重要的是要理解它们,并知道如何将它们应用到您的代码中。这在调试其他代码的过程中可能会有用。
在下一章中,我们将专注于 CSS 代码优化。我们将使用Gulp.js来准备您的代码进行测试和最终优化项目。
第十三章:代码优化
本章是关于一般创建代码过程和与每个步骤相关的过程。这个过程有几个一般阶段,我们将研究如何在每个阶段优化代码。
在本章中,我们将涵盖以下主题:
-
在创建的每个步骤中进行代码优化
-
如何在你的代码库中保持代码
-
如何优化 SASS 代码
-
如何在 CSS/SASS 代码中使用简写形式
-
如何准备代码以用于生产
自我优化
优化过程是在你开始编写代码时开始的。在编写代码时意识到可以优化的内容以及它在编写代码时应该如何出现是至关重要的。在编写过程之后,当你开始优化时,重构和重组代码可能会非常困难。但是构建代码并自动附加优化过程是很容易的。在编写代码时可以执行哪些过程?
-
使用简写形式
-
省略使用
!important -
省略使用 ID
在将代码发布之前的几个步骤
在代码创建过程中,有一些可重复的步骤:
-
编写代码
-
测试代码
-
将代码发布
这些过程有时是可重复的,特别是当它们与 Eric Ries 的《精益创业》方法论和多阶段项目相关时。在将代码发布之前,你需要记住这几个步骤:
-
检查是否使用了简写形式
-
检查元素/声明是否重复
-
检查元素/声明是否在 HTML 中使用(僵尸选择器)
-
检查
!important的出现(如果可能的话,尝试省略它们) -
检查代码是否被压缩
这个列表非常基础。在接下来的章节中,我们将运行优化过程和用法,检查所有可能性。
使用简写形式
在编写和构建过程中,简写形式有助于压缩代码。在 CSS 中使用简写形式,你可以节省很多字符,使代码更加精简。让我们来看一下简写形式的概述。
填充/边距的简写形式
你写填充和边距时有多少次使用了完整形式?你有多少次看到别人的代码没有使用填充和边距的简写形式而感到紧张?是的!它可能会让你紧张,因为这是对 CSS 的浪费!让我们从 SASS 中对元素填充的简单描述开始:
.element
padding:
top: 10px
right: 20px
bottom: 30px
left: 40px
它会给你类似这样的 CSS 代码:
.element {
padding-top: 10px;
padding-right: 20px;
padding-bottom: 30px;
padding-left: 40px;
}
以下是用 CSS 简要描述它的方法:
.element
padding: 10px 20px 30px 40px
一般来说,填充可以描述如下:
padding: top right bottom left
你也可以用同样的方法处理边距:
.element
margin:
top: 10px
right: 20px
bottom: 30px
left: 40px
它会给你类似这样的 CSS 代码:
.element {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 30px;
margin-left: 40px;
}
以下是用 CSS 简要描述它的方法:
.element
margin: 10px 20px 30px 40px
一般来说,边距可以描述如下:
margin: top right bottom left
让我们用另一个例子:
.element
margin:
top: 10px
right: 20px
bottom: 10px
left: 20px
编译为 CSS:
.element {
margin-top: 10px;
margin-right: 20px;
margin-bottom: 10px;
margin-left: 20px;
}
正如你所看到的,有两对值。当上边距/填充的值在底部值中重复,并且左值等于右值时,你可以使用简写版本:
.element
margin: 10px 20px
当编译为 CSS 时,它看起来像这样:
.element {
margin: 10px 20px;
}
如你所见,这个版本是被压缩的,最终基于这个模式:
margin: top_bottom_value left_right_value
边框的简写形式
让我们从边框的基本描述开始,然后我们可以扩展它:
.element
border:
style: solid
color: #000
width: 10px
这是编译后的 CSS:
.element {
border-style: solid;
border-color: #000;
border-width: 10px;
}
这个类将在框周围创建一个边框,它将是实心的,宽度为10px,颜色为黑色。因此,让我们创建一个包括所有边框(上、右、下和左)的类,定义样式颜色和宽度:
.element
border:
top:
style: solid
color: #000
width: 1px
right:
style: solid
color: #f00
width: 2px
bottom:
style: solid
color: #0f0
width: 3px
left:
style: solid
color: #00f
width: 4px
CSS:
.element {
border-top-style: solid;
border-top-color: #000;
border-top-width: 1px;
border-right-style: solid;
border-right-color: #f00;
border-right-width: 2px;
border-bottom-style: solid;
border-bottom-color: #0f0;
border-bottom-width: 3px;
border-left-style: solid;
border-left-color: #00f;
border-left-width: 4px;
}
因此,如果你想让这个代码变得更短一点,你可以使用全局定义的边框简写。代码如下:
.element
border: 1px solid #000
CSS:
.element {
border: 1px solid #000;
}
和方向。代码将看起来像这样:
.element
border:
top: 1px dotted #000
right: 2px solid #f00
bottom: 3px dashed #0f0
left: 4px double #00f
编译:
.element {
border-top: 1px dotted #000;
border-right: 2px solid #f00;
border-bottom: 3px dashed #0f0;
border-left: 4px double #00f;
}
有一种方法可以以与我们定义填充和边框相同的方式来描述样式/宽度/颜色:
.element
border:
style: dotted solid dashed double
width: 1px 2px 3px 4px
color: #000 #f00 #0f0 #00f
编译:
.element {
border-style: dotted solid dashed double;
border-width: 1px 2px 3px 4px;
border-color: #000 #f00 #0f0 #00f;
}
现在,让我们收集关于border-radius的信息。边框半径的全局定义如下:
SASS:
.element
border-radius: 5px
CSS:
.element {
border-radius: 5px;
}
在另一行和另一个值中描述每个角:
.element
border:
top:
left-radius: 5px
right-radius: 6px
bottom:
left-radius: 7px
right-radius: 8px
CSS:
.element {
border-top-left-radius: 5px;
border-top-right-radius: 6px;
border-bottom-left-radius: 7px;
border-bottom-right-radius: 8px;
}
现在,前面的代码可以用以下方式描述得更短:
.element
border-radius: 5px 6px 7px 8px
CSS:
.element {
border-radius: 5px 6px 7px 8px;
}
字体样式中的简短形式
字体在每个段落标题链接中都有描述。如您所见,在代码中这么多重复出现的情况下使用简写是很好的。在这里,我们对一个示例元素的字体和行高进行了简单描述:
.element
font:
size: 12px
family: Arial
weight: bold
line-height: 1.5
CSS:
.element {
font-size: 12px;
font-family: Arial;
font-weight: bold;
line-height: 1.5;
}
让我们基于模式使用简短形式:
font: font_family font_size/line_height font_weight
通过这种简短的形式,我们在 SASS 中的五行(在 CSS 中的四行)被改为了一行:
.element
font: Arial 12px/1.5 bold
编译后,代码如下:
.element {
font: Arial 12px/1.5 bold;
}
背景的简短形式
背景是最常用的 CSS 特性之一。背景的主要用途是:
.element
background:
color: #000
image: url(path_to_image.extension)
repeat: no-repeat
attachment: fixed
position: top left
这段代码将给我们以下输出:
.element {
background-image: url(path_to_image.extension);
background-repeat: no-repeat;
background-attachment: fixed;
background-position: top left;
}
这是很多代码!简短形式按照这个顺序描述:
background-color
background-image
background-repeat
background-attachment
background-position
例子:
background: url color repeating attachment position-x position-y;
如果我们想用这种简短形式描述我们的元素,我们只需要这样做:
.element
background: #000 url(path_to_image.extension) no-repeat fixed top left
在 SASS 编译成 CSS 后,我们将得到以下结果:
.element {
background: #000 url(path_to_image.extension) no-repeat fixed top left;
}
检查重复
在创建 CSS 代码时,您需要注意代码的重复。对于专业开发人员来说,代码可能看起来有点奇怪,但我们可以把它当作代码审查过程的一个很好的样本。让我们来分析一下。
HTML:
<section>
<a class="button">click it</a>
<a class="buttonBlue">click it</a>
<a class="buttonGreen">click it</a>
</section>
CSS:
section .button {
padding: 5px 10px; /* Repeated padding */
font-size: 12px; /* Repeated font size */
color: white; /* Repeated color */
background: black;
}
section .buttonBlue {
padding: 5px 10px; /* Repeated padding */
font-size: 12px; /* Repeated font size */
color: white; /* Repeated color */
background: blue;
}
section .buttonGreen {
padding: 5px 10px; /* Repeated padding */
font-size: 12px; /* Repeated font size */
color: white; /* Repeated color */
background: green;
}
如您所见,重复部分已经被注释,现在我们将创建一个通用类:
section .button {
padding: 5px 10px;
font-size: 12px;
color: white;
background: black;
}
section button.button_blue {
background: blue;
}
section button.button_green {
background: green;
}
我们需要在 HTML 代码中追加一些小的改变:
<section>
<a class="button">click it</a>
<a class="button button_blue">click it</a>
<a class="button button_green">click it</a>
</section>
在 SASS 中将其最小化:
section
.button
padding: 5px 10px
font-size: 12px
color: white
background: black
&.button_blue
background: blue
&.button_green
background: green
这是另一种处理重复的方法,而不改变标记:
article .h1 {
font-family: Arial; /* Repeated font family */
padding: 10px 0 15px 0; /* Repeated padding */
font-size: 36px;
line-height: 1.5; /* Repeated line height */
color: black; /* Repeated color */
}
article .h2 {
font-family: Arial; /* Repeated font family */
padding: 10px 0 15px 0; /* Repeated padding */
font-size: 30px;
line-height: 1.5; /* Repeated line height */
color: black; /* Repeated color */
}
article .h3 {
font-family: Tahoma; /* Oryginal font family */
padding: 10px 0 15px 0; /* Repeated padding */
font-size: 24px;
line-height: 1.5; /* Repeated line height */
color: black; /* Repeated color */
}
让我们收集重复的部分:
font-family: Arial;
padding: 10px 0 15px 0;
line-height: 1.5;
color: black;
让我们添加一个将在自定义元素.h3中被覆盖的值:
font-family: Tahoma;
现在,让我们描述选择器并在单独的选择器中覆盖值:
article .h1,
article .h2,
article .h3 {
padding: 10px 0 15px 0;
line-height: 1.5;
color: black;
font-family: Arial;
}
article .h1 {
font-size: 36px;
}
article .h2 {
font-size: 30px;
}
article .h3 {
font-size: 24px;
font-family: Tahoma;
}
让我们将其改为 SASS 代码:
article
.h1,
.h2,
.h3
padding: 10px 0 15px 0
line-height: 1.5
color: black
font:
family: Arial
.h1
font:
size: 36px
.h2
font:
size: 30px
.h3
font:
size: 24px
family: Tahoma
让我们用@extend做同样的事情:
article
.h1
padding: 10px 0 15px 0
line-height: 1.5
color: black
font:
family: Arial
size: 36px
.h2
@extend .h1
font:
size: 30px
.h3
@extend .h1
font:
size: 24px
family: Tahoma
当您自己创建代码时,检查重复的过程很容易,但当您与其他开发人员一起工作或者在一个由其他人开始的项目上工作时,这可能会更难。这个过程使代码变得更短,因此它可以被视为代码优化的过程。通过这些技术,您可以对代码进行追加更改。
总结
在本章中,我们讨论了 CSS 代码优化的过程。有了这些知识,您可以最小化您的代码,并且在创建代码时考虑优化过程。这些知识将使您成为一个更加明智的前端开发人员,了解代码如何可以在瞬间被最小化。
在下一章中,我们将讨论您可以在 CSS 和前端项目中使用的最终自动化!
第十四章:最终自动化和流程优化
在这最后一章中,我们将讨论在创建 CSS 代码过程中重复流程的最终自动化。有很多流程可以自动化,但是意识到它是否可以做到以及使用的工具的知识是必不可少的。在本章中,我们将专注于工具以及如何在 Gulp 任务运行器中实现自动化。
在本章中,我们将涵盖以下主题:
-
视网膜和移动设备上的图像
-
如何识别未使用的 CSS
-
如何压缩代码
-
如何从页面列表中制作截图以便快速概览
-
如何使用 Jade 模板的基础知识并将其编译到 Gulp 中
Gulp
在本书的开头,我介绍了 Gulp 作为 SASS 的入门。但是仅仅使用 Gulp 来编译 SASS 可能是浪费时间的。在本章中,我们将向 Gulp 添加更多任务,这些任务可以作为前端开发人员使用,并将帮助你优化你的代码。
Jade 作为你的模板引擎
在大型项目的情况下编写 HTML 文件可能会有问题。页面的可重复元素的维护,比如主导航页脚边栏,在需要处理 10 个文件时可能会成为一个问题。每次你想要更改页脚中的内容,你都需要更新 10 个文件。当一个项目有 50 个模板时,情况会变得更加复杂。你可以开始使用 PHP 或任何包含重复代码部分的文件的语言,或者使用其中一个模板语言。有多种模板系统。以下是一些知名和时髦的模板系统:
-
手柄
-
HAML
-
Jade
-
Slim
让我们专注于 Jade。为什么?因为有以下功能:
-
混合支持
-
主模板
-
文件的部分化
-
缩进的语法(类似于 SASS)
安装和使用 Jade
Jade 是通过 node 包管理器安装的。你可以用以下命令安装它:
npm install jade --global
如果你想编译一些文件,只需要调用 HTML 文件如下:
jade filename.html
更多信息,我建议你查看 Jade 模板系统的官方文档jade-lang.com/。
Jade 的基础知识
理论介绍很重要,但让我们试着将代码的这部分描述成 Jade:
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
在 Jade 中,它会是这样的:
nav
ul
li
a(href="#") Home
li
a(href="#") About
li
a(href="#") Contact
你可以看到,你不需要考虑标准的 HTML 问题“我的标签关闭了吗?”缩进会跟踪标签的开启和关闭。你想要附加到标签中的每个文本都会出现在标签描述(名称和属性)后的空格后。让我们看一下代码的这部分:
a(href="#") Home
这部分代码将被编译成:
<a href="#">Home</a>
如你所见,在 Jade 中,属性(href)出现在元素名称(a)之后,用括号括起来。让我们看一下我们将要翻译成 Jade 的 HTML 代码的下一部分:
<head>
<meta charset="utf-8">
<title>Page title</title>
<link rel="stylesheet" href="css/main.css" media="screen" title="no title" charset="utf-8">
</head>
这部分代码将在所有页面上重复出现,因为它包含了我们 HTML 的head标签。在 Jade 中,它会是这样的:
head
meta(charset="utf-8")
title Page title
link(rel="stylesheet", href="css/main.css", media="screen", title="no title", charset="utf-8")
在这里你可以看到如何向 HTML 元素添加更多属性。在link元素中,括号中的每个属性都用逗号分隔。
代码的下一部分与带有类和 ID 的 DOM 元素有关:
<main id="main">
<article class="main--article">
<a href="#">
<img src="img/error_log.png" alt=""/>
<span class="comments"></span>
</a>
<h3>Lorem ipsum dolor sit amet, consectetur adipisicing elit</h3>
<p>
sed do eiusmod tempor incididunt ut labore et dolore
</p>
<a href="#" class="readmore">Read more</a>
</article>
</main>
在 Jade 中,代码看起来是这样的:
main#main
article.main--article
a(href="#")
img(src="img/error_log.png", alt="Error log")
.comments
h3 Lorem ipsum dolor sit amet
p sed do eiusmod tempor incididunt ut labore et dolore
a(href="#").readmore Read more
你可以看到,你不需要描述这部分:
<main id="main">
这是写成这样的:
main(id="main")
在 Jade 中有一个简短的形式:
main#main
类似的情况也适用于类:
<article class="main--article">
你也可以使用一个简短的形式:
article.main--article
这种简短的方法使 Jade 易于理解,因为它基于 CSS 中使用的选择器。
Jade 中的混合
Jade 中的混合很有用,特别是当网页上有一些可重复的元素时。例如,可能是一些带有href的小元素a:
mixin link(href, name)
a(href= href)=name
现在我们需要做的就是将它添加到你的模板中:
+link("url", "Your link")
在你编译的文件中,你会看到:
<a href="url">Your link</a>
在 Jade 中包含和扩展功能
如前所述,我们可以将代码的部分保存在单独的文件中。这样做的最简单方法是使用include方法。假设我们已经在文件navigation.jade中定义了主要的nav,并且我们希望在我们的模板中添加其内容。代码如下:
文件名是:navigation.jade
nav
ul
li
a(href="#") Home
li
a(href="#") About
li
a(href="#") Contact
文件名是:template.jade
doctype html
html
head
meta(charset="utf-8")
title Page title
link(rel="stylesheet", href="css/main.css", media="screen", title="no title", charset="utf-8")
body
include _navigation.jade
当您编译template.jade时,您将得到:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Page title</title>
<link rel="stylesheet" href="css/main.css" media="screen" title="no title" charset="utf-8">
</head>
<body>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
</body>
</html>
这是一个很好的时机来使用可以扩展的主布局。这可以通过代码操作来完成。第一次操作必须在主模板中进行 - 定义一个将在我们的 HTML 文件中交换的块。第二次需要在将代表最终 HTML 文件的文件中完成 - 指定将扩展的主模板。代码如下:
文件名是:master.jade
doctype html
html
head
meta(charset="utf-8")
title Page title
link(rel="stylesheet", href="css/main.css", media="screen", title="no title", charset="utf-8")
body
include _navigation.jade
block content
文件名是:index.jade
extends master
block content
h1 Content
编译后的文档:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Page title</title>
<link rel="stylesheet" href="css/main.css" media="screen" title="no title" charset="utf-8">
</head>
<body>
<nav>
<ul>
<li><a href="#">Home</a></li>
<li><a href="#">About</a></li>
<li><a href="#">Contact</a></li>
</ul>
</nav>
<h1>Content</h1>
</body>
</html>
在 gulp.js 中使用 Jade
要在gulpfile.js中创建或添加 Jade 任务,您需要使用npm安装特定的包:gulp-jade。要这样做,请使用以下命令:
npm install --save gulp-jade
然后,您需要在gulpfile.js中定义一个新任务,并为模板添加一个监视器,该模板将存储在src/jade目录中。以下是来自本书第一章的扩展gulpfile.js的清单:
var gulp = require('gulp'),
sass = require('gulp-sass'),
jade = require('gulp-jade');
gulp.task('sass', function () {
return gulp.src('src/css/main.sass')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('dist/css/main.css'));
});
gulp.task('jade', function() {
gulp.src('src/jade/*.jade')
.pipe(jade())
.pipe(gulp.dest('dist/'));
});
gulp.task('default', function () {
gulp.watch('src/sass/*.sass', ['sass']);
gulp.watch('src/jade/*.jade', ['jade']);
});
它会表现如何?每当您更改src/jade文件夹中的任何文件时,编译后的文件将会出现在dist文件夹中。当然,如果您愿意,这种结构可以更改;这只是使用示例。随意更改它!
UnCSS
有多少次你面对过这样的情况:HTML 中没有使用某些类/选择器,但在 CSS 代码中有描述?每当您的项目更改或重新设计时,这种情况都会发生。例如,您的任务是删除某些部分并在 HTML 代码中添加几行。因此,您将添加一些 CSS 代码,然后删除其中的一些。但您确定 CSS 代码不包含未使用的 CSS 代码部分吗?UnCSS 将帮助您完成此任务。要安装它,您需要执行此命令:
npm install -g uncss
让我们来看看在npm命令中使用的标志:
| 标志 | 描述 |
|---|---|
-g |
全局安装 |
--save |
本地安装这些包将出现在package.json的dependencies部分。这些包是在生产中运行应用程序所需的。 |
--save-dev |
本地安装这些包将出现在package.json的devDependencies部分。这些包是用于开发和测试过程的。 |
在 Gulp 中集成 UnCSS
首先,我们需要通过npm安装gulp-uncss:
npm install --save gulp-uncss
现在,我们需要在gulpfile.js中添加新的任务。我们需要在项目中创建一个测试阶段,该阶段将存储在test目录中。您需要这些新任务来基于uncss进行处理:
gulp.task('clean-css-test', function () {
return gulp.src('test/css/main.css', {read: false})
.pipe(rimraf({force: true}));
});
gulp.task('jade-test', function() {
return gulp.src('src/jade/templates/*.jade')
.pipe(jade())
.on('error', gutil.log)
.pipe(gulp.dest('test/'));
});
gulp.task('sass-test',['clean-css-test'], function () {
return gulp.src('src/sass/main.sass')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('test/css/'));
});
gulp.task('uncss',['jade-test', 'sass-test'], function () {
return gulp.src('test/css/main.css')
.pipe(uncss({
html: ['test/**/*.html']
}))
.pipe(gulp.dest('./test/uncss'));
});
要运行uncss任务,您需要使用以下命令:
gulp uncss
此命令将执行以下任务:
-
将 Jade 文件编译到
test文件夹中 -
从
test文件夹中删除旧的 CSS 文件 -
将 SASS 文件编译到
test文件夹中 -
运行
uncss任务,并将文档保存为test/uncss文件夹中仅使用的 CSS 部分
现在我们需要实时测试。我们将准备一个简短的测试环境。
以下是文件的结构:
├── jade
│ ├── master_templates
│ │ └── main.jade
│ ├── partials
│ │ ├── footer.jade
│ │ └── navigation.jade
│ └── templates
│ ├── about.jade
│ ├── contact.jade
│ └── index.jade
└── sass
└── main.sass
代码如下:
文件名是:main.jade
doctype html
html
head
meta(charset="utf-8")
title Page title
link(rel="stylesheet", href="css/main.css", media="screen", title="no title", charset="utf-8")
body
include ../partials/navigation
block content
include ../partials/footer
文件名是:navigation.jade
nav
ul
li
a(href="#") Home
li
a(href="#") About
li
a(href="#") Contact
文件名是:footer.jade
footer
p Copyright fedojo.com
文件名是:index.jade
extends ../master_templates/main
block content
.main
p Test of INDEX page
文件名是:about.jade
extends ../master_templates/main
block content
.main
h1 Test of ABOUT page
文件名是:contact.jade
extends ../master_templates/main
block content
.main
h1 Test of CONTACT page
文件名是:main.sass
body
background: #fff
p
color: #000
.header
background: #000
color: #fff
.footer
background: #000
color: #fff
header
background: #000
color: #fff
footer
background: #000
color: #fff
现在,让我们检查这个过程对我们是否有利。这是从 SASS 编译的文件:
body {
background: #fff;
}
p {
color: #000;
}
.header {
background: #000;
color: #fff;
}
.footer {
background: #000;
color: #fff;
}
header {
background: #000;
color: #fff;
}
footer {
background: #000;
color: #fff;
}
此文件由uncss检查,它查看了所有模板(index.html,about.html和contact.html):
body {
background: #fff;
}
p {
color: #000;
}
footer {
background: #000;
color: #fff;
}
我们的新命令是用 Gulp 构建的,删除了所有不必要的 CSS 声明。
压缩 CSS
缩小文件的过程主要应该用于生产代码。在开发过程中,对缩小的文件进行操作会很困难,因此我们只需要为生产代码进行缩小。可以通过添加适当的标志(--compressed)来启用 SASS 或 Compass 编译中的缩小。我们还将使用一个外部工具,在 uncss 过程之后对代码进行缩小。现在我们需要安装 gulp-clean-css:
npm install --save gulp-clean-css
现在,缩小 uncss 过程的结果。我们将创建一个 prod 目录,其中存储项目的最终版本。现在让我们导入 gulp-clean-css:
cleanCSS = require('gulp-clean-css')
让我们在 gulpfile.js 中创建所需的部分:
gulp.task('clean-css-production', function () {
return gulp.src('prod/css/main.css', {read: false})
.pipe(rimraf({force: true}));
});
gulp.task('sass-production',['clean-css-production'], function () {
return gulp.src('src/sass/main.sass')
.pipe(sass().on('error', sass.logError))
.pipe(uncss({
html: ['prod/**/*.html']
}))
.pipe(cleanCSS())
.pipe(gulp.dest('prod/css/'));
});
gulp.task('jade-production', function() {
return gulp.src('src/jade/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('prod/'));
});
gulp.task('production',['jade-production', 'sass-production']);
最终的自动化工具
现在我们需要将之前创建的所有任务汇总到一个文件中。gulp 项目的核心是两个文件:package.json,它汇总了所有项目依赖,以及 gulpfile,你可以在其中存储所有任务。以下是任务:
文件名是:package.json
{
"name": "automatizer",
"version": "1.0.0",
"description": "CSS automatizer",
"main": "gulpfile.js",
"author": "Piotr Sikora",
"license": "ISC",
"dependencies": {
"gulp": "latest",
"gulp-clean-css": "latest",
"gulp-jade": "latest",
"gulp-rimraf": "latest",
"gulp-sass": "latest",
"gulp-uncss": "latest",
"gulp-util": "latest",
"rimraf": "latest"
}
}
文件名是:gulpfile.json
var gulp = require('gulp'),
sass = require('gulp-sass'),
jade = require('gulp-jade'),
gutil = require('gulp-util'),
uncss = require('gulp-uncss'),
rimraf = require('gulp-rimraf'),
cleanCSS = require('gulp-clean-css');
gulp.task('clean-css-dist', function () {
return gulp.src('dist/css/main.css', {read: false})
.pipe(rimraf({force: true}));
});
gulp.task('clean-css-test', function () {
return gulp.src('test/css/main.css', {read: false})
.pipe(rimraf({force: true}));
});
gulp.task('sass',['clean-css-dist'], function () {
return gulp.src('src/sass/main.sass')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('dist/css/'));
});
gulp.task('jade', function() {
return gulp.src('src/jade/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('dist/'));
});
gulp.task('jade-test', function() {
return gulp.src('src/jade/templates/*.jade')
.pipe(jade())
.on('error', gutil.log)
.pipe(gulp.dest('test/'));
});
gulp.task('sass-test',['clean-css-test'], function () {
return gulp.src('src/sass/main.sass')
.pipe(sass().on('error', sass.logError))
.pipe(gulp.dest('test/css/'));
});
gulp.task('uncss',['jade-test', 'sass-test'], function () {
return gulp.src('test/css/main.css')
.pipe(uncss({
html: ['test/**/*.html']
}))
.pipe(gulp.dest('test/uncss'));
});
gulp.task('clean-css-production', function () {
return gulp.src('prod/css/main.css', {read: false})
.pipe(rimraf({force: true}));
});
gulp.task('sass-production',['clean-css-production'], function () {
return gulp.src('src/sass/main.sass')
.pipe(sass().on('error', sass.logError))
.pipe(uncss({
html: ['prod/**/*.html']
}))
.pipe(cleanCSS())
.pipe(gulp.dest('prod/css/'));
});
gulp.task('jade-production', function() {
return gulp.src('src/jade/templates/*.jade')
.pipe(jade())
.pipe(gulp.dest('prod/'));
});
gulp.task('production',['jade-production', 'sass-production']);
gulp.task('default', function () {
gulp.watch('src/sass/*.sass', ['sass']);
gulp.watch('src/jade/*.jade', ['jade']);
});
总结
在本章中,我们讨论了 Jade 模板系统的基础知识。我们看到了如何将其添加到前端开发人员的工作流程中。基于模板系统,你现在可以将 UnCSS 包含到你的流程中,并从 CSS 文件中删除不必要的代码。然后我们对最终结果进行了缩小,并创建了生产代码。
你可以将这个自动化工具视为项目的起点,并根据自己的项目进行调整。你也可以添加新功能并不断完善它。










浙公网安备 33010602011771号