HtmlandCss基础4-第二部分余下

HtmlandCss基础4

Forms

Introduction

  • Build forms
  • Style forms
  • Text fields
  • Data lists
  • Drop-down lists
  • Check boxes
  • Radio buttons
  • Sliders
  • File inputs
  • Hidden fields

Creating a Basic Form

现在我们来创建一个基本的表单。

首先表单的标签是<form> ,在一个表单里面还可以有多个 <input>

1
2
3
4
<form>
<label for="name">Name</label>
<input id="name" type="text" name="name"/>
</form>

我们这里之所以使用label是因为lable是行内块,而用<p>元素是段落块,导致Name会出现在文本框上面,不美观。

此外,这里将label与input联系起来了,for='name',id='name' 匹配之后,直接点击label就可以将光标锁定到文本框,如下所示

此外还有email类型的,这样,当提交表单的时候如果输入的不是email,就会报错,能提供一定程度上的数值验证。

最后我们写两个button,很简单:

1
2
<button type="submit" >Register</button>
<button type="reset" >Clear</button>

Styling Forms

我们发现这个表单太丑了,怎么美化一下呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
body{
// 首先改一下字体,设置一下例页边距
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
line-height: 1.5;
padding: 1rem;
}


form {
// 修改表单的页边距
padding: 10px 20px
}

label{
// 将label设置为块呈现
display: block;
}
// 可以用这种语法来选择input类型
input[type='text'],
input[type='email']{
border: 1px solid #ccc;
border-radius: 5px;
padding: 0.5rem 0.7rem;
//设置一下小动画,让点击效果更圆润
transition: border-color 0.15s,box-shadow 0.15s;
}

input[type='text']:focus,
input[type='email']:focus{
border-color: #7db0fb;
// 去掉外轮廓
outline: 0;
// 添加一些阴影
box-shadow: 0 0 0 4px rgba(24,117,255,0.25)

}

button{
// 对按钮设置背景、字体颜色、边框等
background: #0d6efd;
color: #fff;
padding: 0.5rem 0.7rem;
border: 0;
border-radius: 5px;
}

.form-group {
//设置底部间隙
margin-bottom: 1rem;
}

但是如果所有css都我们自己写,这未免也太过繁琐了。因此接下来我们来学CSS Framework

CSS Frameworks

CSS 框架其实就是一个已经写好了的CSS代码库。我们常用的CSS库如下:

  • Bootstrap
  • Foundation
  • UI Kit
  • Semantic UI
  • Materialize
  • Miligram

这里我们要使用Bootstrap来美化表单。要下载Bootstrap,访问:https://getbootstrap.com/docs/5.1/getting-started/download/即可。我们采用CDN这种下载方式,只要在html文件中引入一个连接即可:

1
2
3
4
5
6
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css"
rel="stylesheet"
integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We"
crossorigin="anonymous"
/>

然后我们就可以使用Bootstrap了。

比如说我要用Bootstrap中的 Email 文本框,就可以模仿bootstrap的写法来修改我们的html页面。因为Bootstrap中对于email有其特殊的class名字,Bootstrap内置的CSS文件就会渲染这些类。

1
2
3
4
5
6
7
8
<div class="form-group">
<label class="form-label" for="name">Name</label>
<input class="form-control" id="name" type="text" />
</div>
<div class="form-group">
<label class="form-label" for="email">Email</label>
<input class="form-control" id="email" type="email" />
</div>

对于按钮,Bootstrap也有自己的一套代码库:

我们发现文本框太长了,而且间距也不是很好,我们可以这样来调整

1
2
<form class="w-50">
<div class="mb-3">

w-50就是说,这个表单占据页面宽度的一半

mb-3 就是说 margin bottom,第三档次的间隙(一共5档,越大越宽)

此外bootstrap还有很多组件,我们可以自行调用。

然而当我们使用CDN方法时,可能会导致下载css文件的时间过长从而对用户体验造成影响。因此我们再介绍一个CSS框架:Milligram

milligram不需要我们记下很多class(像bootstrap一样),只要引入一个链接,其他照常写html即可,如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/normalize.css" />
<link rel="stylesheet" href="./css/form.css" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/milligram/1.4.1/milligram.css">

<title>Document</title>
</head>
<body>
<form>
<div>
<label for="name">Name</label>
<input id="name" type="text" />
</div>
<div>
<label for="email">Email</label>
<input id="email" type="email" />
</div>
<button type="submit">Register</button>
<button type="reset">Clear</button>
</form>
</body>
</html>

而且这个css是很轻量级的,下载只需要2.5KB. 只是文本框长度啥的还需要自己调一下

Text Fields

现在我们来研究文本框。文本框有很多类型,比如说最简单的就是

<input type ="text" />

如果我们想限制填入文本的类型,比如我们只想输入的是数字,可以这么写:

<input type = "number" />

比如我希望输入的是密码,需要隐藏,可以这么写:

<input type = "password" />

如果需要填写日期,可以这么写:

<input type="date"/>

以及之前我们介绍过的: <input type = "email" />

如果我们不想要文本框,而是一个文本块。可以这么写:

<textarea cols="30" row="10"></textarea> 说明这个文本块可以容纳十行三十列的文本:

我们还可以为每一个文本框(块)设置占位符。设置placeholder属性即可

此外我们可以设置文本框只读,只要设置readonly或者disable即可。readonly是可以选中文本框,但是disable连选中都不可以。<input type="email" readonly value="111">

如果我们要设置文本框的最大输入个数,可以设置maxlength属性。比如<input type="email" maxvalue="5">

如果我们要设置自动选中,可以设置autofocus属性。<input type="email" autofocus> 这样当刷新页面时会自动选中该文本框。

需要注意的是,textarea并没有value这个属性,若要设置占位符,可以直接在标签内写 <textarea cols="30" row="10">Comment...</textarea>

这节课我们主要学了这几种属性:

type : text | email | password | date | number

cols, rows

placeholder

maxlength

布尔属性,不需要为其设置值: readonly | disable | autofoucus

Data Lists

现在我们来学习如何做一个下拉式选择表单:

1
2
3
4
5
6
7
8
9
<form>
<input type="text" list = "countries" autocomplete="off">
<datalist id = "countries">
<option>Austria</option>
<option>Canada</option>
<option>America</option>
<option>China</option>
</datalist>
</form>

首先我们要放一个文本框,让其list属性等于datalist的id属性。然后再在datalist下设置<option>

<option data-value="1">Austria</option> 此外我们最好设置一下data-value属性以便后台知道我们提交时到底选中的是几号选项。

需要注意的是,这个下拉列表的样式并不是我们说了算的,而是chrome的默认样式,我们可以通过自己写css来修改这个样式。

https://developer.mozilla.org/en-US/docs/Web/HTML/Element/datalist

访问上面的网站我们可以找到一些样式。

因为虽然我们有选择列表,但是用户还是可以填入它们想写的任何文本。因此我们还需要对其做一定的限制。这就要用到 Drop-down List了

1
2
3
4
5
6
7
8
<form>
<select>
<option value="">Select a Course</option>
<option value="1" selected >HTML</option>
<option value="2">CSS</option>
<option value="3">JAVASCRIPT</option>
</select>
</form>

Drop-down List 是不能自行填写其他内容的。和Data List 的区别在于将<datalist>替换成<select> 即可。

此外我们还可以设置布尔属性:selected 即自动选中。


1
2
3
4
5
6
7
<form>
<select multiple>
<option value="1" selected >HTML</option>
<option value="2">CSS</option>
<option value="3">JAVASCRIPT</option>
</select>
</form>

只要我们给select标签设置multiple属性,那么就没有弹出式表单了。直接可以在文本框里选,就是比较丑。


最后,select标签里面还可以以组为单位设置选项。组标签为<optgroup>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<form>
<select>
<optgroup label = "Front-end Courses">
<option value="1">HTML</option>
<option value="2">CSS</option>
<option value="3">JAVASCRIPT</option>
</optgroup>
<optgroup label = "Back-end Courses">
<option value="1" >Node.js</option>
<option value="2">ASP.Net</option>
<option value="3">Django</option>
</optgroup>
</select>
</form>

Check Boxes

1
2
3
4
5
6
7
8
9
10
<form>
<div>
<input type="checkbox" id="">
<label class="label-inline" for="front-end">Front-end</label>
</div>
<div>
<input type="checkbox" id="">
<label class="label-inline" for="back-end">Back-end</label>
</div>
</form>

这个类型的表单叫做复选框。类型为 checkbox

但是单独的<input type="checkbox" id="">仅仅是一个可以打钩的框框。如果我们想在旁边加上文字,需要写一个label元素。且class属性需要填写label-inline 。这样milligram就会将这个label渲染成行内呈现而不是块呈现。

此外,checkbox也有disablechecked 这类布尔属性

Radio Buttons

说完了复选框,现在我们来说单选按钮。

1
2
3
4
5
6
7
8
9
10
<form>
<div>
<input type="radio" name="membership" id="silver" />
<label for="silver" class = "label-inline" >silver</label>
</div>
<div>
<input type="radio" name="membership" id="gold" />
<label for="gold" class = "label-inline" >gold</label>
</div>
</form>

和checkbox 大差不差。

当然,Radio Buttons也有disablechecked 这类布尔属性

Sliders

现在我们来创建滑动条- 类型是range

1
2
3
<form>
<input type="range" min="0" max = "100" value = "90">
</form>

但是现在无法将滑动条的数值显示出来,这是JavaScript需要做的事情。

File Inputs

现在我们来看文件选择按钮。

最基础的是这样的:<input type = "file" />

此外还可以加上 multiple这个布尔属性,允许选择多个文件

也可以设置accept=""属性,用来指定选择文件的类型。

  • .jpg 只能选择jpg
  • .jpg, .png 可以选择jpg或者png
  • image/* 可以选择所有类型的图片,还有audio/*video/*

fieldset 元素可将表单内的相关元素分组。

<fieldset>标签将表单内容的一部分打包,生成一组相关表单的字段。当一组表单元素放到 <fieldset> 标签内时,浏览器会以特殊方式来显示它们,它们可能有特殊的边界、3D 效果,或者甚至可创建一个子表单来处理这些元素。

比如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<form>
<fieldset>
<legend>Billing Address</legend>
<input type="text" />
<input type="text" />
<input type="text" />
</fieldset>
<fieldset>
<legend>Payment</legend>
<input type="text" />
<input type="text" />
<input type="text" />
</fieldset>
</form>

Hidden Fields

HiddenField控件顾名思义就是隐藏输入框的服务器控件,它能让你保存那些不需要显示在页面上的且对安全性要求不高的数据。

1
2
3
<form>
<input type="hidden" name = "course-id" value = "1234" />
</form>

Data Validation

数据验证其实是一项很重要的功能,否则会带来千奇百怪的bug。那么怎么保证客户输入的数据符合规范呢?

数据验证既可以在后端做(Mongo - Data Validation) 也可在前端用 html完成一些简单的数据验证。

最基本的,就是规定某个文本框一定要填写:

1
2
3
4
<form>
<input type="text" required >
<button type="submit">SUBMIT</button>
</form>

<input type="text" required minlength="3" maxlength="10" /> 还可以设置最少填入字数以及最大填入字数

Submitting the Form

1
2
3
4
5
<form>
<input type="text" placeholder="Name"/>
<input type="text" placeholder="Email"/>
<button type="submit">Submit</button>
</form>

这是最简单的一张表单。对于提交按钮有两种写法:

1
2
<button type="submit">Submit</button>
<input type="submit">Submit</input>

但是第二种不能给其另外添加icon了

设计完表单之后我们就要提交了。一般来说提交到我们自己写的后台,如Node、Django之类的。但是这里为了方便起见,我们用一个网站来实现后台功能:https://formspree.io/forms

注册以后,我们创建一个新的 Form,与此同时该网站会自动生成一个后台。我们只需要复制一个连接到我们的HTML文件中即可:

1
2
3
4
5
<form action="https://formspree.io/f/xzbykqky" method = "POST">
<input type="text" placeholder="Name" name="name"/>
<input type="text" placeholder="Email" name="email"/>
<button type="submit">Submit</button>
</form>

注意,这边要成功提交,需要设置 name属性以及method属性

现在我们来解释一下 GET和POST有什么区别:

当我们设置Method为POST的时候,数据是放在请求体里的。

而当我们设置Method为GET的时候,数据是放在URL中的

Google搜索都是用GET方式的。

Transformations,Transitions,and Animation

这一章我们要学习一些关于变形、过渡动画的内容。

Transformations

CSS中有一个专门的属性叫 transform 里面有很多方法,最基本的有:

  1. rotate(angle) : 定义 2D 旋转,在参数中规定角度。
  2. skew(x-angle,y-angle) : 定义沿着 X 和 Y 轴的 2D 倾斜转换。
  3. scale(x[,y]?) 定义 2D 缩放转换。
  4. translate(x,y) 定义 2D 转换。

比如说我设置了一个Box,然后设置了CSS格式:

1
2
3
.box:hover{
transform: rotate(60deg);
}

这样当我的鼠标移动到box上去,box就会正向旋转60°。当这个变化是瞬时的,并不是一个动画。如果是-60deg ,那么就是反向旋转60°

scale是放缩,可大可小,括号内写的是放大或缩小的倍数

1
2
3
.box:hover{
transform: scale(1.5);
}

如果是skew那么就是斜线变换, 若是负数就是反向变换:

1
2
3
.box:hover{
transform : skew(15deg)
}

如果是translate(10px)那么就会让box沿着水平线正向移动10px,如果是translate(10px,10px),那么就会在水平移动的时候同时在垂直方向移动。

1
2
3
.box:hover{
transform: translate(10px,10px);
}

此外,还可以安排多个转变。比如先移动,然后旋转:

1
2
3
.box:hover{
transform: translate(50px) rotate(45deg);
}

需要注意的是,变形的顺序不同对最终的结果影响也是很大的,比如我把 rotate 和 translate 交换位置:

1
2
3
.box:hover{
transform: rotate(45deg) translate(50px) ;
}

3D Transformations

上面我们说的都是关于x、y轴的变换,其实每一种变换都是可以在3维空间中进行的

translateX(x) 定义 3D 转化,仅使用用于 X 轴的值。
translateY(y) 定义 3D 转化,仅使用用于 Y 轴的值。
translateZ(z) 定义 3D 转化,仅使用用于 Z 轴的值。
scale3d(x,y,z) 定义 3D 缩放转换。
scaleX(x) 定义 3D 缩放转换,通过给定一个 X 轴的值。
scaleY(y) 定义 3D 缩放转换,通过给定一个 Y 轴的值。
scaleZ(z) 定义 3D 缩放转换,通过给定一个 Z 轴的值。
rotate3d(x,y,z,angle) 定义 3D 旋转。
rotateX(angle) 定义沿 X 轴的 3D 旋转。
rotateY(angle) 定义沿 Y 轴的 3D 旋转。
rotateZ(angle) 定义沿 Z 轴的 3D 旋转。
perspective(n) 定义 3D 转换元素的透视视图。
  • translate
1
2
3
.box :hover {
transform: perspective(200px) translateZ(-50px)
}

perspective() 规定 3D 元素的透视效果。

  • rotate
1
2
3
4
.box :hover {
transform: perspective(200px) rotateY(45deg)
transform-origin: 0 50%
}

其中transform-Origin属性允许我更改转换元素的位置。其中两参数分别代表视图被放在x轴、y轴的何处。

Transitions

上面我们展示的都是“突变”,那么是时候在它们之间加点过渡了。

transition 属性设置元素当过渡效果,四个简写属性为:

  • transition-property
  • transition-duration
  • transition-timing-function
  • transition-delay

语法:transition: property duration timing-function delay;

描述
transition-property 指定CSS属性的name,transition效果
transition-duration transition效果需要指定多少秒或毫秒才能完成
transition-timing-function 指定transition效果的转速曲线
transition-delay 定义transition效果开始的时候

比如我要对一个旋转做过渡效果:

1
2
3
4
5
6
7
8
9
10
11
.box {
width: 100px;
height: 100px;
background: gold;
transition: transform 0.5s;
}


.box:hover {
transform: rotate(45deg);
}

此外我们可以设置运动的快慢:

1
2
transition: transform 0.5s ease-in; //先快后慢
transition: transform 0.5s ease-out;//先慢后快

还可以设置cubic-bezier()函数,来自定义变换速度:到这里去定制

我设置 transition-delay 为1s,那么就说嘛我鼠标移动到box后一秒才出发过渡。

此外我们还可以设置颜色渐变:

Animation

  • 语法
1
2
animation: name duration timing-function delay iteration-count direction fill-mode play-state;
或者一个一个标签定义。
说明
animation-name 指定要绑定到选择器的关键帧的名称
animation-duration 动画指定需要多少秒或毫秒完成
animation-timing-function 设置动画将如何完成一个周期
animation-delay 设置动画在启动前的延迟间隔。
animation-iteration-count 定义动画的播放次数。
animation-direction 指定是否应该轮流反向播放动画。
animation-fill-mode 规定当动画不播放时(当动画完成时,或当动画有一个延迟未开始播放时),要应用到元素的样式。
animation-play-state 指定动画是否正在运行或已暂停。
initial 设置属性为其默认值。 阅读关于 initial的介绍。
inherit 从父元素继承属性。 阅读关于 initinherital的介绍。

首先,我们创建了一个animation,叫做pop。在pop中我们要定义一些关键帧,比如这里我设置了在一开始是不懂得,到了四分之一的时候会变大,到了一半的时候会旋转,到了最后会变回原样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

@keyframes pop {
0% {
transform: scale(1);
}

25% {
transform:scale(1.3);
}

50% {
transform: rotate(45deg);
background: tomato;
}

100%{
transform: rotate(0);
}
}

.box {
width: 100px;
height: 100px;
background: gold;
animation-name: pop;
animation-duration: 4s;
animation-delay: 1s;
animation-iteration-count: 1;
animation-timing-function: ease-out;
animation-direction: alternate;

}

Reusable Animations

如果我写了一个很好地动画,想给很多的元素用,但是又不想写这么多的重复代码,怎么办?

我们可以直接对一个类进行渲染,比如:

1
2
3
4
5
6
7
8
.animation-pop {
animation-name: pop;
animation-duration: 4s;
animation-delay: 1s;
animation-iteration-count: 1;
animation-timing-function: ease-out;
animation-direction: alternate;
}

这样,当某个元素要用这套动画的时候,只要在class中加上animation-pop即可。

最后来介绍一下Animate网站,它有很多现成的动画供我们使用。只要在HTTP文件中引入一个链接即可

然后,只要给想要动画的元素加一个类,就可以获得该动画了

Writing Clean,Maintainable CSS

CSS Best Practices

接下来我们来介绍几个能让CSS简洁、可维护的好习惯

  1. Follw a naming convention 命名要符合规范

    通常有这样几种CSS命名规范:

    • .nav-bar {} Kebab case 词与词之间用- 隔开
    • .navBar {} Camel case
    • .NavBar {} Pascal case
    • .nav_bar{} Snake case
  1. Create logical section in your stylesheet

写一个CSS文件需要组织得富有逻辑。比如说:

1
2
3
4
5
6
7
/* Basic styles */
...
/* Typography */
...
/* Forms */
...
/* Navigation Bar */
  1. Avoid over-specific selectors : 不要写特别具体的选择器

比如说有一个列表:

1
2
3
4
5
6
7
<div class="nav">
<ul class="item">
<li class = "item">Link 1</li>
<li class = "item">Link 2</li>
<li class = "item">Link 3</li>
</ul>
</div>

理想的选择器是这样的:.nav .item

我们不要搞得很复杂比如:div.nav > ul.items > li ,这样耦合度太高了

  1. 合理的类命名。

我们同样举这个例子,如果有一个针对 .item的一般性的css样式,那么很可能其样式会覆盖我们上面指定的.nav .item.因此,我们可以将 <li class = "item">Link 1</li> 改为<li class = "nav-item">Link 1</li>。用来表明该item是在nav中的。

  1. 不要使用!important

  2. Sort CSS properties : 对于乱糟糟的CSS属性,我们最好按照一定顺序排列一下(可以使字母表顺序)

比如:

1
2
3
4
5
6
.nav-item {
color: tomato;
width: 100%;
background: #fff;
font-weight:bold;
}

可以shift+command+p 呼唤出控制面板,搜索sort后排序。

  1. Take advantage of style inheritance

对于字体这类的作用范围比较广的样式,我们可以对总体设置,这样细枝末节的字体就会自动继承其父元素的字体,就不需要我们再去设置了。

  1. Extract repetitive patterns
  2. Keep code DRY(Don’t repeat your code)

Variables

对于一些常用的样式,比如说常见的颜色,我们不需要一遍一遍得打rbg,而是可以用变量将它们存储起来:

1
2
3
4
5
6
7
8
9
10
11
12
13
:root{
--primary-color : #ffdd36;
--border-size: 2px;
--border-radius: 10px;

}

.one {
background: var(--primary-color);
}
.two {
background: var(--primary-color);
}

注意变量书写和引用的格式

Object-oriented CSS

BEM

BEM的全称是:Block Element Modifier

BEM是一个非常有用,强大,简单的命名约定,可以让你的前端代码更容易阅读和理解,更容易协作,更容易控制。

当然,通常人们会认为BEM写法难看,但是他的好处远远超过它外观上的那点瑕疵。

  1. BEM命名约定

BEM:块(block)、元素(element)、修饰符(modifier)下面是命名约定的模式

1
2
3
.block{}
.block__element{}
.block--modifier{}

其中块可以用单个连字符来界定:如

1
2
3
.site-search{} //块
.site-search__field{} //元素
.site-search--full{} //修饰符
  1. 如何使用BEM

Block:一个独立的,可以复用而不依赖其他组件的部分,可作为一个块
Element:属于块的某部分,可作为一个元素
Modifier:用于修饰块或元素,体现出外形行为状态等特征的,可作为一个修饰器

规范:

1)保证各个部分只有一级B__E–M,修饰器需要和对应的块或元素一起使用,避免单独使用。
2)仅以类名作为选择器,不使用ID或标签名来约束选择器,且css中的选择器嵌套不超过2层
3)避免 .block__el1__el2 的格式

-------------本文结束,感谢您的阅读-------------