豪翔天下

Change My World by Program

0%

其实很早就想写这么一篇文章了,但一直不知道该怎么措辞,借于大学里第三次逃课之际,很多的想法便喷涌而出。

都他妈大三了,才逃过三次课?没错,这就是我。

人家都说,学霸逃课是为了学习,学渣上课是为了玩手机。我就是后者,一个不大标准的学渣,上课戳手机、玩平板、看课外书,睡觉倒是很少,但肯定是不会听老师讲课的。还记得刚上大学的时候很多人都说,大学呀,一定要好好利用时间,选修课必逃,必修课选逃。我是一直都很不同意这句话的,这句话只教育了我们要逃课,却没教育我们逃课应该去做些其他的什么事情,至少,身边很多的同学,逃课无非这几个目的:玩儿、睡觉、游戏。据我观察,凡是为了写代码而逃课的现在都已经成为高手了,但很遗憾,我可不是这种人。我也很多次想逃课,但苦于找不到逃课的理由最终逃课未遂。

纵观我大学这2.5年里逃的三次课,一次因为班级聚餐,就我有课,确实不好叫他们改时间;一次是回家,要是错过了那天下午的车,第二天整个车站都是人啊,反正我曾经见过一次那个场面的;第三次就是今天,全校都在考试,我一直觉得那个课应该已经结束了,为什么还有,而且都上课了才通知我,裤子都还没穿呢(其实七点过就醒了,在床上看书而已)。

我不逃课,首先是因为尊敬老师。其实,大学的老师和以前的老师不一样,你做什么几乎都不关他们的事,很多老师都只是把教书作为一个工作而已。所以不用太崇拜大学的老师,因为他们也是在为生活打拼,也不要瞧不起大学老师,因为他们也是普通人。简单地说,大学的老师,只要你给他面子,他也会给你面子。你只要不天天去招惹他,逃一两次课也没什么(当然要排除极少数奇葩的老师),多挂一个人对他毫无影响,但老师才懒得多此一举呢,省得你背地里骂他。

不逃课还有一个重要的原因就是确实老师交不了我们什么。额,首先,这绝不仅仅是老师的问题,更重要的还是课程上的问题。大学有很多课程类型,必修课、限选课、任选课,表面上是给了学生很大的自主选择权,但仔细看看就知道了,限选课除了考试比较水以外,课程量和不可选择性上和必修课没什么两样,剩下的任选课要求四年里修满6个学分,也就三门。。。作为一个正在经历这个年龄的人来说,我就感觉越是强制要求的越是我不想学的,这或许也算有点儿叛逆吧。课程设置已经如此让人讨厌了,大学里随处可见的照着PPT和教材读的老师我更是无力吐槽。

至于挂科嘛,我大学读到现在,都没挂过科,绩点也还可以,3.224,额,没算这学期的,目测我决定不考研后,绩点在这学期会一下降到2.X。原因很简单,大学读得越久,越觉得毕业证没有那么重要了。我很庆幸,我读到了计算机这个专业,或者说,进入了互联网行业。这是一个真正拼实力的行业,对我们年轻人,这个行业有极大的包容心,很多互联网企业看重的是学力,而不是学历。还记得元旦节第一次坚决地跟父亲说我不考研的时候,也顺便把这个观点说给他听了,他听后没说什么,只说不能理解我们这个行业,但是同意让我自己选择。所以挂科这种东西早就看淡了,唯一不想的是挂科后得提前几天来学校补考,本来这假期安排的就过不了大年了,还提前。

唉,无病呻吟……

长度单位

1
2
3
4
em: 如果是font-size,那么就是相对父元素的字体大小
rem: 跟元素的字体大小,r是root的意思
vw: 视窗宽度
vh: 视窗高度

浏览器兼容

  • 首行的<!DOCTYPE html>很关键

  • 谷歌浏览器或者新的浏览器支持在十六进制颜色后面加两位数来表示透明度,但是其他浏览器不支持,会直接不显示颜色

  • IE9以下需要专门调用这几个js

    1
    2
    3
    4
    5
    <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
    <!--[if lt IE 9]>
    <script src="http://apps.bdimg.com/libs/html5shiv/3.7/html5shiv.min.js"></script>
    <script src="http://apps.bdimg.com/libs/respond.js/1.4.2/respond.min.js"></script>
    <![endif]-->
  • IE浏览器兼容模式,并且针对IE浏览器首先使用edge内核,对于多核浏览器,首先使用Chrome内核

    1
    <meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1" />

特殊函数

Calc
  • 非常棒的函数,能够借助css直接对属性进行计算,例如width: cacl(50% - 4px),表示宽度为父组件宽度的一半减4px,需要注意的时候中间计算符号的两边必须有空格,否则会被浏览器认为是一个错误的属性而被忽略
  • 可以用于控制字体的缩放,例如font-size: calc(1.5rem + 3vw),这样字体能跟随页面一同缩放
  • 可以通过它实现简单的固定顶部和底部,而中间刚好撑满浏览器的布局:

各种属性

a链接

a:link:表示一个正常的未被点击过的a标签的属性

a:visited: 表示一个已经被点击过的a标签的属性

a:hover: 鼠标移动到a标签上面

a:active: a标签被点击的时候

  • 如果href="javascript:void(0)"会不跳转并且保留鼠标的手势按钮
align-items
  • 居中对齐弹性盒子的各项
    元素,默认值是stretch(拉伸元素以适应容器)
background
  • 可以同时设置背景图像的color、image、repeat、attachment、position属性,如.style1{background:beige url(mypic.png) no-repeat top center}

  • 设置背景颜色渐变

    1
    2
    3
    4
    5
    6
    7
    .simple-linear {
    background: linear-gradient(blue, pink); # 至少需要指定两种颜色,也可以多个颜色
    background: linear-gradient(to right, blue, pink); # 可以改变渐变方向,默认是从上到下
    background: linear-gradient(to bottom right, blue, pink); # 对角线渐变色
    background: linear-gradient(70deg, blue, pink); # 自定义渐变角度,to right=90deg
    background: linear-gradient(to left, blue 30px; pink 50%); # 声明颜色渐变到哪个位置结束
    }
background-color
  • 设置透明
  • transparent: 直接设置
  • rgba(255, 255, 255, 0.5): 前三个是颜色,最后一个是透明度
background-image
background-position
  • 可以分成background-position-xbackground-position-y
  • 可以直接center表示居中
background-repeat
  • 设置是否及如何重复背景图像
  • repeat(默认值,背景图像在摧之方向和水平方向重复)、repeate-x(水平方向重复)、repeat-y(垂直方向重复)、no-repeat(不重复)、inherit(继承父元素)
background-size
  • 设置背景图片的大小
  • 可选值:auto(以背景图片的比例缩放背景图片)、cover(缩放背景图片以完全覆盖背景区,可能背景图片部分看不见,宽高比例不变)、contain(缩放背景图片以完全转入背景区,可能背景区部分空白,宽高比例不变)、直接指定宽度(如50%、3em、12px、auto等)、指定宽度和高度(如50% auto、100% 100%等)
  • background-size: 0 0;可以实现隐藏背景图片
border边框
  • border-color: 设置4个边框的颜色
  • border-radius: 设置边框圆角大小
  • border-style: 设置4个边框的样式。可能的值有none(无边框)、hidden(对于表,用于解决边框冲突,和none一样)、dotted(点状边框)、dashed(虚线)、solid(实线)、double(双线)、groove(3D凹槽边框)、ridge(3D垄状边框)、inset(3D inset边框)、outset(3D outset边框)、inherit(从父元素继承)
  • border-width: 边框宽度
  • 可以将三个属性一起定义:border: width style color,例如border-right: 10px solid black
box-shadow
  • 给框添加阴影

  • box-shadow: h-shadow v-shadow blur spread color inset;,例如box-shadow: 10px 10px 5px #888888;

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    /* x偏移量 | y偏移量 | 阴影颜色 */
    box-shadow: 60px -16px teal;

    /* x偏移量 | y偏移量 | 阴影模糊半径 | 阴影颜色 */
    box-shadow: 10px 5px 5px black;

    /* x偏移量 | y偏移量 | 阴影模糊半径 | 阴影扩散半径 | 阴影颜色 */
    box-shadow: 2px 2px 2px 1px rgba(0, 0, 0, 0.2);

    /* 插页(阴影向内) | x偏移量 | y偏移量 | 阴影颜色 */
    box-shadow: inset 5em 1em gold;

    /* 任意数量的阴影,以逗号分隔 */
    box-shadow: 3px 3px red, -1em 0 0.4em olive;
cursor
  • 设置鼠标悬停效果
  • default(默认光标,一个箭头)、auto(默认值,浏览器自己设置)、crosshair(十字光标)、pointer(一只手、拖拽光标)、move(可被移动的光标)、e-resize/ne-resize/nw-resize/n-resize/se-resize/sw-resize/s-resize/w-resize(光标指示矩形框的边缘可往哪个方向移动,常用于往8个方向改变窗口大小)、text(文本)、wait(在忙,一只表或沙漏)、help(帮助,问号或气球)、no-drop/not-allowed(禁止,红色的圈加一个斜杠)
  • cursor:pointerinput type="file"的情况下可能会不生效,可以给input标签添加font-size: 0,这样就能实现鼠标移到input元素上变成手形了
display
  • 规定元素应该生成的显示框的类型
  • none(不显示)、block(块级元素,前后会带有换行符)、inline(默认,内联元素,前后没有换行符)、inline-block(行内块元素)、list-item(会作为列表显示)、inherit(继承父元素display属性)
  • 值为flex表示弹性布局
font-family
  • 如果是内联样式inline-style,可以用单引号代替双引号,否则可能不会生效
font-weight
  • 设置字体粗细

  • 如果值为bold,表示直接加粗,相当于值为700

  • 如果想要字体超过900,可以尝试这些方法

    • 更换字体

    • 尝试给字加阴影,加少一点也有一定的加粗字体的效果

      1
      2
      3
      4
      5
      6
      7
      text-shadow: 0px 1px, 1px 0px, 1px 0px;

      // 或者几个属性配合
      text-shadow: 1px 0;
      letter-spacing:1px;
      font-weight:bold;
      letter-spacing: 0.5px;
input
  • text-align: 内容显示方式,center表示居中显示

  • 如果direction属性是ltr,则默认值是left;如果direction是rtl,则为right

  • autocomplete="off": 关闭google浏览器等的自动填充功能

  • 如果是number类型的input想要隐藏选择箭头可以这样做:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    /* Chrome, Safari, Edge, Opera */
    input::-webkit-outer-spin-button,
    input::-webkit-inner-spin-button {
    -webkit-appearance: none;
    margin: 0;
    }

    /* Firefox */
    input[type=number] {
    -moz-appearance: textfield;
    }
justify-content
  • 用于设置弹性盒子元素在主轴(横轴)方向上的对齐方式,align-content用于设置垂直轴
  • flex-start: 默认值,项目位于容器的开头
  • flex-end: 项目位于容器的结尾
  • center: 项目位于容器的中心
  • Space-between: 项目位于各行之间留有空白的容器内
  • space-around: 项目位于各行之前、之间、之后都留有空白的容器内
  • initial: 设置该属性为它的默认值
  • Inherit: 从父元素继承该属性
line-height
  • 设置行间距
list-style
  • 把图像设置为列表中的列表项目标记(就是每一行的头那个地方设置为圆点显示还是数字显示)
  • 包括三个属性: list-style-type list-style-position list-style-image,默认值为disc outside none
  • list-style-type就是左边的样式,可选值有none(无标记)、disc(实心圆,默认)、circle(空心圆)、square(实心方块)、decimal(数字)、decimal-leading-zero(0开头的数字)等
margin
1
margin: 10px 5px 15px 20px;	/*上 右 下 左*/
object-fit
  • object-fit: fill可以让video在像素长款不够的情况依然拉大到整个组件那么大
opacity
  • 透明效果,蒙板效果
outline
  • 如果想要Button/Input等点击后(获取焦点时)不出现蓝色的边框,可以把该属性设置为none
overflow
  • 当水平或垂直方向溢出时添加滚动条

  • visible: 内容不会被截断,且可以显示在内容盒之外

  • hidden: 内容会被截断,且不会显示滚动条

  • scroll: 总是显示滚动条,无论内容是否发生溢出

  • auto: 取决于浏览器本身

  • 既要有滚动效果,又要隐藏滚动条,可以使用这种方法:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .hide-scrollbar{
    -ms-overflow-style: none;
    overflow: -moz-scrollbars-none;
    scrollbar-width: none; // 火狐需要添加这个

    &::-webkit-scrollbar {
    width: 0 !important
    }
    }
overflow-x
  • 当水平方向溢出时添加滚动条
overflow-y
  • 当垂直方向溢出时添加滚动条
  • scroll: 可以用这个属性给单独的两列创建单独的滚动条
padding
  • 如果仅提供两个参数,第一个表示垂直方向,第二个表示水平方向,例如padding: 20px 0等同于padding-top: 20px; padding-right: 0px; padding-bottom: 20px; padding-left:0px;
pointer-events
  • 指定在什么情况下某个特定的元素可以成为鼠标事件的target

  • none: 可以实现某个元素仅仅能看,但是无法触发其事件。屏蔽掉某个元素上的所有的事件。屏蔽点击事件,不可点击/禁止鼠标点击/禁止点击,hove的时候也不会有任何的改变

  • 这个属性的其他值都只适用于SVG

position
  • absolute: 绝对定位,相对于static定位以外的第一个父元素进行定位
  • fixed: 绝对定位,相对于浏览器窗口进行定位
  • relative: 相对定位,相对于其正常位置进行定位
  • static: 默认值。没有定位ie,元素出现在正常的流中
  • inherit: 从父元素继承position属性
  • 如果父元素设置了margin auto且overflow-x:none,子元素如果想单独撑开(而不是所有子元素撑开)父元素且横屏占满,可以采取修改position的值为fixed然后width:200%,然后left一点到左边去即可
table
  • overflow:scroll:如果表格超宽,让页面自动出现滚动条
  • word-wrap:break-word,超过宽度自动换行
  • word-break: break-all,超过宽度,无论是不是一个单词都换行
  • 如果table的border不显示可以尝试添加这个样式 border-collapse: collapse;
scroll-behavior
  • smooth: 使滚动变为平滑滚动,如果想要自己通过手动控制滚动,如scrollTo等,一定要加该参数,这样才能使滚动看起来平顺一点
  • auto: 滚动框立即滚动
text
  • text-indent: 段落缩进设置
text-align
  • text-align: center只能让inline元素剧中,而不能让block元素居中,而text-align: -webkit-center可以让其中的block元素也居中
text-decoration
  • text-decoration: underline添加下划线、下横线、删除线(line-through)
text-overflow
  • 设置当文本溢出包含元素时怎么做

  • clip(直接截断文本)、ellipsis(截断文本并显示省略号)

  • 如果text-overflow不能工作,可以尝试下这样:

    1
    2
    3
    4
    5
    {
    width: 80px; // 元素宽度必须是px,不能是百分比%
    overflow: hidden; // 必须设置
    white-space: nowrap;
    }
text-transform
  • 控制文本的大小写,默认为none,可选capitalize(首字母大写)、uppercase(全部大写)、lowercase(全部小写)
top
  • 如果top属性不起作用,可以尝试修改当前元素或者父元素或兄弟元素的position值试试
white-space
  • nowrap: 强制不换行
user-select
  • none(文本不能被选择)、text(可以选择文本)

  • 需要注意的是在input上设置user-select: none可能导致safari的输入框无法输入任何内容,然而这个属性一般又是全局设置的,可以这样做:

    1
    2
    3
    *:not(input) {
    user-select: none;
    }
vertical-align
  • 设置元素的垂直对齐方式,定义行内元素的基线相对于该元素所在行的基线的垂直对齐
  • 参考值:baseline(默认,元素放置在父元素的基线上)、sub(垂直对齐文本的下标)、super(垂直对齐文本的上标)、top(把元素的顶端与行中最高元素的顶端对齐)、text-top(把元素的顶端与父元素字体的顶端对齐)、middle(把此元素放置在父元素的中部)、bottom(把元素的顶端与行中最低的元素的顶端对齐)、text-bottom(把元素的底端与父元素字体的底端对齐)、%(使用line-height属性的百分比值来排列此元素,允许为负)、inherit(继承父元素的值)
-webkit-text-fill-color
  • 检索或设置对象中的文字填充颜色。如果同时设置了text-fill-color和color,text-fill-color定义的颜色将覆盖color属性;通常-webkit-text-fill-color与-webkit-text-stroke一起使用,能实现一些例如渐变文字和镂空文字的效果。

  • 可以使用该参数来解决safari和firefoxinput框在disabled时颜色不一样的问题:

    1
    2
    -webkit-text-fill-color: #880000;
    opacity: 1; /* required on iOS */
white-space
  • nowrap: 强制不换行
width元素宽度
  • max-width设置最大宽度,默认为none,可选max-content(原素内容固有的合适的宽度)、min-content(元素内容固有的最小宽度)、fit-content
word-wrap
  • break-word: 强制换行(a标签太长强制换行)
@media
  • 媒体查询,可以定义当满足某个条件时的css,例如

    1
    2
    3
    4
    5
    6
    7
    8
    @media (max-width: 600px) {	// 当屏幕最大宽度小于600px的时候
    .tag {
    display: none;
    }
    }

    @media (min-width: 700px) and (orientation: landscape) {} // 仅在横屏并且宽度大于700px的时候
    @media tv and (min-width: 700px) and (orientation: landscape){}// 仅在电视上

CSS选择器

.class1.class2
  • 表示既包含class1又包含class2的元素
.class1 .class2
  • 表示class1下的class2的元素
element > element
  • 例如div > p表示选择所有父节点为divp元素
element + element
  • 例如div + p表示选择所有前面是div标签的p标签
element ~ element
  • 例如p ~ ul表示选择所有p标签后的ul标签
[attribute]
  • 例如a[target]表示选择所有含有target属性的a标签
[attribute=value]
  • 例如a[target=_blank]表示选择所有target属性为_blanka标签
  • div[style*=”display:block”]选择有指定inline style的元素
[attribute~=value]
  • 例如[title~=flower]表示选择所有title属性里面包含flower的标签
[attribute|=value]
  • 例如[lang|=en]表示选择所有lang属性以en开头的标签
[attribute^=value]
  • 例如a[href^="https"]表示选择所有href属性以https开头的a标签
[attribute$=value]
  • 例如a[href$=".pdf"]表示所有href属性以.pdf结尾的a标签
[attribute*=value]
  • 例如a[href*="test"]表示所有href包含testa标签
:active
  • 例如a:active表示a标签被激活
::after
  • 例如p::after表示在p标签后插入一些内容
1
2
3
4
// 这样每一个p标签后面都会跟上这个内容了
p::after {
content: " - Remember this";
}
::before
  • 例如p::before表示在p标签前插入一些内容,和::after用法类似
  • ::before/::after可组合实现一些绚丽的效果: 伪类光圈、伪类括号效果、丝带效果、几何图形(三角形、五角星)、水滴、流动边框、Tooltip提示、伪类盒子阴影、Tabs当前激活状态、伪元素模糊背景、蓝湖文字、主要标题、鼠标浮层、遮罩浮层、伪类美化文字、照片堆叠效果
:checked
  • 例如input:checked表示选择所有checked了的input
:default
  • 例如input:default表示选择所有默认状态下的input
:disabled
  • 例如input:disabled表示选择所有禁用了的input
:empty
  • 例如p:empty表示选择没有子元素的p标签
:enabled
  • 例如input:enabled表示选择所有可用的input标签
:first-child
  • 第一个子元素
::first-lettter
  • 第一个字母
::first-line
  • 第一行
:first-of-type
  • 例如p:first-of-type表示全局所有的p标签里面的第一个
:focus
  • 表示获得焦点的时候
:hover
  • 鼠标浮动的时候
:in-range
  • 当值在某个范围内的时候
1
2
3
4
5
6
7
<style>
input:in-range {
border: 2px solid yellow;
}
</style>
// 下面的7input的范围内,当值为7的时候就应用上面的样式
<input type="number" min="5" max="10" value="7">
:indeterminate
  • 元素为不确定状态时
:invalid
  • 当输入为不合法的时候input:invalid
:lang(language)
  • p:lang(it)表示选择所有lang属性为itp标签
:last-child
:last-of-type
  • 全局最后一个指定元素
  • a:link表示所有为访问的a标签
:not(selector)
  • :not(p)表示所有不是p标签的标签
nth-child(n)
  • 前n个子元素
nth-last-child(n)
  • 表示倒数n个子元素
  • 参数除了数字,还可以填入oddeven表示奇偶
1
2
3
4
// 表示该div标签下的最后2个元素的属性
div:nth-last-child(2) {
background: red;
}
:nth-last-of-type(n)
  • 最后n个元素
:nth-of0type(n)
  • 前n个元素
:only-of-type
  • p:only-of-type选择所有的p标签为父元素的p标签
:only-child
  • p:only-child选择p标签为唯一子元素的父元素

  • 例如

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    p:only-child
    {
    background:#ff0000;
    }

    <div> <!--这里选择到的是div元素-->
    <p>这是一个段落。</p>
    </div>

    <div> <!--不唯一,不选择该元素-->
    <p>这是一个 span。</p>
    <p>这是一个段落。</p>
    </div>
:optional
  • input:optional表示输入框为非必选的时候
out-of-range
  • in-range相反
::placeholder
  • input::placeholder
:read-only
  • input:read-only表示只读的input标签
:read-write
  • input:read-write表示可读写的input标签
:required
  • input:required表示必填的input标签
:root
  • 选择文档的跟元素
::selection
  • 用户当前选择的元素
:target
:valid
  • 合法的输入框
:visited
  • 访问过的连接

Flex布局

  • flex布局清单

  • 注意flex是无法给容器设置height的,但是可以通过设置内部元素的height/max-height/min-height来间接控制其高度

  • 如果flex的宽度较长,明明有剩余空间却自动换行了可能需要这样设置(flex布局的内容超出了盒子的宽度):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    .content {
    flex: 1;
    width: 0;
    }
    // 或者
    .content {
    flex: 1;
    overflow: hidden;
    }

参考
Flex 布局教程:语法篇

Flex 布局教程:实例篇: 这里面可以看到居中对齐、右对齐、左对齐、上部居中对齐、下部居中对齐、右下对齐等,以及网格布局、圣杯布局(传统网页的布局方式)、输入框的布局、悬挂式布局、固定的底栏、流式布局

flex容器的属性

属性名 含义 可选值 默认值
flex-direction 决定主轴的方向(即项目的排列方向) row | row-reverse | column | column-reverse row
flex-wrap 定义换行方式 nowrap | wrap(第一行在上方) | wrap-reverse(第一行在下方) nowrap
flex-flow flex-direction和flex-wrap属性的简写形式 row nowrap
justify-content 定义了项目在主轴上的对齐方式 flex-start(左对齐) | flex-end(右对齐) | center(居中) | space-between(两端对齐,项目之间的间隔都相等) | space-around(每个项目两侧的间隔相等)
align-items 定义项目在交叉轴上如何对齐 flex-start(交叉轴的起点对齐,上对齐) | flex-end(交叉轴的终点对齐,下对齐) | center(交叉轴的中点对齐,居中对齐) | baseline(项目的第一行文字的基线对齐) | stretch(如果项目未设置高度或设为auto,将占满整个容器的高度) stretch
align-content 定义了多根轴线的对齐方式.如果项目只有一根轴线,该属性不起作用 flex-start(与交叉轴的起点对齐) | flex-end(与交叉轴的终点对齐) | center(与交叉轴的中点对齐) | space-between(与交叉轴两端对齐,轴线之间的间隔平均分布) | space-around(每根轴线两侧的间隔都相等) | stretch(轴线占满整个交叉轴) stretch

flex容器下项目的属性

属性名 含义 可选值 默认值
order 定义项目的排列顺序,数值越小,排列越靠前,默认为0 0
flex-grow 项目的放大比例 如果所有项目的flex-grow属性都为1,则它们将等分剩余空间(如果有的话)。如果一个项目的flex-grow属性为2,其他项目都为1,则前者占据的剩余空间将比其他项多一倍。这个就类似于element里面的xs了 0(如果存在剩余空间也不放大)
flex-shrink 项目的缩小比例 如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者不缩小。 1(即如果空间不足,该项目将缩小)
flex-basis 在分配多余空间之前,项目占据的主轴空间.浏览器根据这个属性,计算主轴是否有多余空间 可以设为跟widthheight属性一样的值(比如350px),则项目将占据固定空间 Auto
flex flex-grow, flex-shrinkflex-basis的简写 0 1 auto
align-self 允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性 auto | flex-start | flex-end | center | baseline | stretch auto(继承父元素的align-items属性,如果没有父元素,则等同于stretch)

Grid布局

1
2
3
4
5
6
7
8
9
10
11
12
.wrapper {
display: grid; /* 声明一个grid容器 */

grid-template-columns: repeat(4, 25%); /* 声明列的宽度,表示网格宽度为4列,每列25%的宽度,repeat是为了少写几个值,也可以这样写 grid-template-columns: 25% 25% 25% 25% */
grid-template-columns: repeat(4, 1fr); /* 最好使用fr单位,这样可以不用自己去计算百分比,它可以自动减去grid-column-gap的值,但是有个弊端是这样做如果某个列超出宽度后会把整个wrapper的宽度都撑大,就不止25%了 */
grid-template-columns: 250px repeat(12, 1fr); /* fr的好处又可以体现了*/


grid-column-gap: 10px; /* 每两列之间的间隔,*/
grid-column-start: 1; /* 设置当前格占用的起始列,从1开始*/
grid-column-end: 3; /* 设置当前格占用的结束列,左开右闭区间,这个表示占用了1和2两列,相当于两倍宽度*/
}

动画transitions/变化/变换/平滑移动

  • transitions允许我们平滑地改变属性值(而不是立马变更到某个值)

  • ease方法的在线示例: Easing Functions Cheet Sheet

  • 注意值必须是个确定的值,不能是100%这种

    1
    2
    3
    4
    5
    6
    7
    8
    // 最简单的例子,当鼠标移动到div上面的时候div的宽度由100px平滑变更为300px,总共耗时2
    div {
    width: 100px;
    transition: width 2s;
    }
    div:hover {
    width: 300px;
    }
  • transition-property表示绑定的属性名称,transition-duration表示属性变更的时间,transition-timing-function表示属性变更方式,transition-delay表示变更延迟,可以简写为

    1
    2
    3
    div {
    transition: width 2s linear 1s;
    }
  • transition-timing-function变更方式默认为linear表示匀速(cubiz-bezier(0,0,1,1)),ease表示中间快两头慢(cubiz-bezier(0.25,0.1,0.25,1)),ease-in表示先慢后快(0.42, 0, 1, 1),ease-out表示先快后慢(0, 0, 0.58, 1),ease-in-out表示中间慢两头快(0.42, 0, 0.58, 1),cubiz-bezier(n, n, n, n)自定义快慢

内核前缀

  • -ms: ie内核识别码
  • -moz: 火狐内核识别码
  • -webkit: chrome/safari内核识别码
  • -o: opera内核识别码

TroubleShooting

元素居中方法

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
方法一:
<center>...</center>
方法二:
div {margin:0 auto}
方法三:
.Absolute-Center {
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}
# 方法四
.test {
float: none;
display: block;
margin-left: auto;
margin-right: auto;
}
# 方法五,css3里面超级简单
.div {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
# 方法六:让容器内部的元素垂直居中
.parent {
display: flex;
align-items: center;
}
# 方法六:让标签中的文字剧中
div {
text-align: center;
}
# 方法七:绝对定位元素的居中对齐
<div style="position: absolute; left: 50%;">
<div style="position: relative; left: -50%;>
content
</div>
</div>

将某元素置于底层,使用z-index属性,例如:

div {
    z-index; -100;   # 值越小,越底层,默认应该为0
}

文字模糊、阴影效果,使用text-shadow属性,例如:

.menu a:hover{
    text-shadow: 0 0 10px gray;
}

控制元素的隐藏:

# 这样不会占用位置
<div id="div1" style="display:block;">DIV 1</div>

文字环绕图片效果

<div class="wrap">
    文字的前半部分
    <img src="test.png" style="float: left; padding: 0; margin: 3px 5px 0px 0px;">
    文字的后半部分
</div>

固定网站底部信息栏,使得无论内容多少都始终正好显示在底部

html, body {
    height: 100%;
}
.wrapper {
    min-height: 100%;
    height: auto !important;
    height: 100%;
    margin: 0 auto -100px; // 这里负的是footer的高度
}
.footer {
    height: 100px;
}
# 然后,网页主体由以下部分组成:
<html>
    <head></head>
    <body>
        <div class="wrapper"></div>
        <div class="footer"><div>       // 这里也可以用footer代替
    </body>
</html>

以上,我的直觉告诉我会有更方便的方法,但是我居然没找到,谷歌上搜索出来几乎都是这个答案。

判断屏幕宽度

1
2
3
@media (min-width: 400px) {

}

各种情况的颜色渐变实现

http://www.w3cplus.com/content/css3-gradient

让任意的标签可点击

1
<div onclick="location.href='https://haofly.net'" style="cursor:pointer"></div>

底部居中对齐

1
2
3
4
5
6
7
.class {
position:absolute;
bottom: 30px;
margin: auto;
left: 0;
right: 0;
}

在Chrome显示小于12px的字体

  • 需要注意的是这个方法只是单纯地缩小了显示的字,并不是将字体变小了,换行那个地方可能有问题
1
2
3
4
5
.item {
-webkit-transform: scale(.5);
-moz-transform: scale(.5);
transform: scale(.5);
}

让两个Div或其它元素始终并排显示

  • UI中可能会有将两个元素合并成一个元素,并且无论响应式如何改变,两个元素始终按原来的样式在一起
  • 可以先调整两个元素的样式,让他们挨在一起,然后新建一个父类将他们包裹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.parent {
min-width: 150px; // 父组件设置最小宽度,这样即使是响应式也不会影响父组件内部的元素了。剩下的就是让外部无论如何也不能让parent元素的宽度变小了
}
.leftElement {
position: relative;
display: inline-block;
width: 100px;
}
.rightElement {
position: relative;
display: inline-block;
left: -4px; // 微调右边的元素
top: 1px;
border: 1px solid #e1e4e6;
border-left: none;
width: 50px;
}

子元素位于父元素底部

1
2
3
4
5
6
7
8
9
10
11
.parent{
position: relative;
height: 300px;
width: 300px;
margin:0 auto;
}
.child{
position: absolute;
bottom: 0;
height: 80px;
}

多行文字截断/仅显示3行/实现see more/read more功能

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
// 方法一:文本设置固定高度,超过某个高度就隐藏
div {
line-height: 20px;
overflow: hidden;
max-height: 60px; // 3行文本的高度

.read-more { // 当点击read more后最大高度就变大
max-height: 9999px;
transition: max-height 0.2s ease;
}
}

// 方法二:使用-webkit-line-clamps,但是可能存在浏览器兼容问题,例如Firefox和IE浏览器不支持该属性,移动端浏览器一般都基于webkit内核,兼容性还行
div {
display: -webkit-box;
overflow: hidden;
-webkit-line-clamp: 3;
-webkit-box-orient: vertical;
}

// 方法三:通过伪元素绝对定位到行尾并遮住文字
p {
position: relative;
line-height: 20px;
height: 40px;
overflow: hidden;
}
p::after {
content:"...";
font-weight:bold;
position:absolute;
bottom:0;
right:0;
padding:0 20px 1px 45px;

background: -webkit-gradient(linear, left top, right top, from(rgba(255, 255, 255, 0)), to(white), color-stop(50%, white));
background: -moz-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -o-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: -ms-linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
background: linear-gradient(to right, rgba(255, 255, 255, 0), white 50%, white);
}

两个并排inline-block的元素一样的高度却不在同一水平线上,但又不是多余的属性导致的上下空白

  • 这是一个比较奇怪的问题,甚至有时候在不同的浏览器里面会有不同的表现
  • 这涉及到基准线的对齐方式,可以将两个元素都设置vertical-align: top;解决,具体的可以参考上文vertical-align属性的设置

火狐浏览器input的placeholder不再同一水平线上

尝试设置如下伪类,来源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
::-webkit-input-placeholder {
color: brand-blue;
}

:-moz-placeholder { /* Firefox 18- */
color: brand-blue;
line-height 60px;
}

::-moz-placeholder { /* Firefox 19+ */
color: brand-blue;
line-height 60px;
}

:-ms-input-placeholder {
color: brand-blue;
}

设置密码输入框的显示于隐藏

  • 通过修改type属性
1
2
3
4
5
6
7
8
const password = document.querySelector('#password');

$('input#password').on('click', function(e) {
const type = password.getAttribute('type') === 'password' ? 'text' : 'password';
password.setAttribute('type', type);
// 通过修改右边小眼睛的类来切换眼睛的展示
this.classList.toggle('fa-eye-slash');
})

防止元素多次点击出现蓝色边框

1
2
3
4
5
6
7
8
body{
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

// 方法二:用js,需要在点击事件中return false

滚动时隐藏菜单栏

position: absolute不起作用

  • 尝试把当前元素设置为position: absolute,父级元素设置为position: relative

旋转background-image/旋转背景图片

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.div:before {
content: attr(bgImg);
position: absolute;
width: 300%;
height: 200%;
top: -480px;
opacity: 0.3;
left: 70%;
z-index: -1;
background-image: var(--bg-image);
background-position-x: 0;
background-position-y: 0;
background-repeat: no-repeat;
transform: rotate(270deg);
overflow: hidden;
}

Selector “:global .class” is not pure (pure selectors must contain at least one local class or id)

  • :global语法必须在某个类下,不能在顶级使用
1
2
3
4
5
.root {
:global(.myClass) {

}
}

实现图片的等比例自动缩放

1
2
3
4
5
6
img{
width: auto;
height: auto;
max-width: 100%;
max-height: 100%;
}

让video的控制栏一直显示

1
2
3
4
video::-webkit-media-controls-panel {
display: flex !important;
opacity: 1 !important;
}

动态导入的font-family对动态的文字居然不起作用

我的场景就是在canvas中添加文本,但是文本的字体在firefox中却不起作用。首先,如果只是在css中设置了font-face,那么只有在使用的时候才会去获取字体,可以尝试预加载,<link rel="preload" as="font" href="/...ttf" type="font/ttf" crossorigin="anonymous",如果仍然不行,那么可以尝试在页面中添加一个使用该字体的文本,而且必须是显示的,不能隐藏,我不得不把的高度这些设置为0,然后颜色设置为背景色才做到。

扩展阅读

Flex 布局教程

CSS Viewport 视口单位: 一种新的单位vw/vh/vmin/vmax,这篇文章中有很多应用案例,例如: 响应式字体大小、全屏、粘性布局、响应式元素、垂直和水平间距、模态框、页面头部、纵横比、顶部边框、移动端滚动等

最强大的 CSS 布局 —— Grid 布局

CSS灵感:CSS的原生效果大全

animista: 非常多的原生CSSanimation效果大全

作者:叶克飞 摘自:《读者》2014第24期

世间所有的选择,到最后其实都是五个字——你想要什么

在大城市打拼还是回小城市过相对安逸的生活,这是一个近年来争论不休的问题。可是,它真的是一个大问题吗?

20世纪60年代,刘大任从台湾去美国求学,恰在柏克莱遭遇了自由言论运动风潮。最终,他与许多同龄人一样,成为“乌托邦的寻找者”。

尽管刘大任的左翼思维与我并不相投,但不妨碍我被其文章《柏克莱那几年》打动。这位如今已垂垂老矣的小说家写道:“也正是直接参与运动的亲身体验,因‘柏克莱人’而感
染的‘寻找乌托邦’旅程,接受了残酷考验,所有事业梦想全部报废,学位自动抛弃,人生大转弯,甚至对人性的本质产生了难以解决的怀疑,然而,直到今天,扪心自问,没有
一丝一毫后悔。”

他还写道:“对于今天十八九岁的大孩子,我还是可以问心无愧地说这句话,任何机缘,当乌托邦出现在你的人生轨道上时,即使玉石俱焚,也千万不要放弃。因为,人活着,不
为这个,为了什么?”

他还提到了有名的《休伦港宣言》,开篇是那个著名的句子:“我们这一代的人,孕育于至少是相当舒服的环境,被安置在各地的大学殿堂里,不安地看着我们继承的世界……”

这多像个预言,如今的中国年轻人,不也是身处一个至少相当舒服的环境,但又不安地看着这个世界吗?只是,比起那个风起云涌的大时代,如今的中国更加物质化,甚至使得许
多年轻人不得不屈从于生活的压力。但反过来说,如今这种琐碎的物质化生活所遭遇的种种问题,在旧日的风起云涌面前也注定是小儿科。换言之,如果你是一个能为“寻找乌托
邦”放弃一切的人,那么“大城市还是小城市”式的问题根本不值得一提。

大城市和小城市都有显而易见的优缺点:大城市生活丰富,工作机会多,如果是非体制内领域,相对更注重能力,尤其是在创意产业、科技产业等新兴领域,一定程度上形成了业
务重于人际的氛围,缺点是生活成本高、工作压力大;小城市生活成本低,日子相对安逸,但工作机会少,又普遍是人情社会,办任何事都得靠关系,又因人际关系复杂,隐私空
间常被侵犯。

这些优缺点并非绝对,往往会随着个体的特点而转化。比如在家办公的自由职业者,工作主要依靠网络传递,那么小城市的低房价就显得有诱惑力;但如果他又特别喜欢丰富的生
活和多元化的资讯,那么大城市的高房价也不会阻挠他前行的脚步。

正如有人所说,世间所有的选择,到最后其实都是五个字——你想要什么?

许多过来人看到这句话,会不屑地说一句“too young too simple(很傻很天真)”,告诉你这种想法实在太不成熟了,因为许多事情不是想想就能实现的
。他们会摆出各种大道理,列出一连串的“反面教材”,告诉你若不循规蹈矩,人生将会如何悲惨……可是,如果你连想想的勇气都没有,你又能实现什么?

在大城市和小城市的问题上,我的感情一直倾向于前者。当然,我并不是认为大城市一定比小城市好,更不是说年轻人必须选择大城市,毕竟每个人都有自己的活法。但必须承认
的是,在这个选择中,天平从一开始就是倾斜的,前者的生存压力更大,也因此更需要勇气。而遵循内心的勇气,不但是我自己缺少的,也是我喜欢并尊重的。

对于逃离大城市的年轻人,我同样尊重,因为他们尝试过。对于选择小城市安逸生活的年轻人,我也并不反感,因为那也未必不是遵循内心的选择。我唯一不能认同的,是某些人
对打拼者的嘲笑和他们庸俗化的论调。

我见过不少世俗眼光中的失败者,他们无一例外地遭遇了嘲笑。比如有人被迫从北上广回到家乡,就有一些这辈子未曾离开家乡的人嘲笑他在外面混不下去了,当然还少不了“早
说过这条路走不通”之类的论调。还有一些人正在大城市里打拼,可逢年过节回到家乡,就会成为七大姑八大姨的谈资以及被训导的对象,告诫你生活应该安守本分,结婚生子再
去考个公务员才是世界上唯一的人生标准。

我甚至认为,正是这群人的存在,才逼得许多年轻人背井离乡,宁愿在大城市孤独打拼,也绝不回去。

没错,大城市里有许多平凡的打拼者,终其一生也无法跻身于这个城市的上游,他们甚至买不起一套小房子,终日为温饱奔波。但谁有资格嘲笑他们呢?没有人。正如毛利在《普
通女孩,就该滚出大城市?》中所写:“为什么一定非要成功、出色,才能留在大城市?为什么女人不能像男人一样自由选择去留,她永远都该仰仗别人的意见生活吗?”

在中国人的人生选择中,女性比男性的空间更为狭窄,没在30岁前把自己嫁出去仿佛是一条死罪,结婚后没生出孩子来同样是死罪。

一个社会对女性的苛求与偏见,意味着整体价值观的缺陷。女性遭遇苛求,男性同样不会好过。认为女性留在小城市安于现状最好的七大姑八大姨,同样也是逼婚、逼考公务员的
主力,她们的逼迫对象其实不分男女,这也许是小城市最让人窒息的一面。

我有一个朋友,不谙世事、不善交际,有一份稳定的工作和中等收入。与许多独生子女一样,她在父母的支持下买房买车,一个人住着140平方米的房子,每日按部就班地开车
上下班,不知不觉已经年过三十。也是在30岁这一年,她放弃了这一切,选择北漂,租房、挤地铁……

当然有人会说她傻,可她比以前开心多了。她离开这个小城市的唯一理由是孤独,同时,她又不愿像长辈们所说的那样,随便找个人结婚生子,告别孤独——那样的话,也许会更
孤独。

在某些人看来,这种孤独似乎有点矫情。他们还会搬出“适应社会”这一万能法则,告诉你这是你自身的问题,你要改变自己、释放自己,接触社会,就能有更广阔的圈子。可是
,这个说法从根本上抹杀了人与人之间原本就具有的差异,忽略了人的个性。

价值观的差异也与身份、地位无关,即使都是高学历,即使都有体面的工作,但一个读哈耶克、萨义德和《古拉格群岛》的人,怎么可能和一个除了课本再没读过其他书的人有心
灵上的契合呢?因为价值观而造成的孤独,无法因为自身的改变而缓解。而且,即使改变,也只能就高不就低,也就是说,你可以让自己变得更好,去适应别人的高度,但无法刻
意拉低自己的智商,去迁就比自己更平庸的人。

在男权社会里,有较高文化素养和能力的女性,更容易在小城市里感受到这种孤独。工作没有挑战性,缺少有共同话题的朋友,找不到看得上眼的男人,还要因为没对象、不结婚
和没生孩子这样的事情被当成异端,这已经不仅仅是孤独的问题,更关乎尊严的丧失。

所以,一个人越出色,小城市的面目就越可憎。别说那些内地封闭小城了,即使是东南沿海的富庶地区,即使距离港澳仅仅一两个小时的距离,小城市仍然只是小城市,你依然要
忍受以下这些事情:同样的杂志和电影,比广州深圳迟一个多星期上市和上线;你还是得自己开着车跑去大城市看话剧和演唱会;如果你没考公务员,某些人更是会替你痛心疾首
;即使是年轻人,也往往早早老去,坐下来就跟你谈赢在起跑线上的孩子经,见到育儿和养生讲座就像打了鸡血;许多你的同龄人,有着高学历和体面的工作,可家里没有一本书
,你们永远找不到共同的话题;在事业上,你不能靠创意打动客户,跟人搂着肩膀,忍着满口酒气,称兄道弟干上几杯也许更管用……

有时,我甚至会有这样的错觉:能忍受这些,简直需要比在大城市打拼还要多万倍的勇气。当然,后来我明白了,这不是勇气,而是妥协和懦弱。大城市当然也存在这些问题,但
你起码有躲开的机会,如果你有足够的能力,还可以主宰自己的生活。

我有一个朋友,他的故乡在一个内陆不发达省份的小城市,他曾说过这样一句话:“我死也不会回去的,因为我不想在20多岁时看到自己60岁的样子。”因为,在那样的小城
市里,除了公务员、国企、学校、医院之外,你几乎没有什么其他的选择。他用可以在老家买别墅的钱,供了一套北京的小房子,然后告诉我:“房子再小,也是我买的;路再难
,也是我自己选的,这样的话,谁也没有借口来干涉我的生活。”

我知道,这就是勇气。它似乎可以回应某些人的另一种荒谬论调——年轻人选择大城市是一种逃避,比如逃避生活的责任和传宗接代的重任等。且不说年轻人选择大城市大多有理
想和追求的因素,即使真的是逃避,我也建议持此论调的人先检讨一下自己:为什么人家甘愿放弃安逸,以孤身去大城市打拼的代价去逃避你和你所期盼的那些东西,是什么让你
和你的期望比巨大的生活压力和激烈竞争更恐怖?

很多时候,我们都过早老去,然后定义生活。比如认为房子、车子和金钱就代表生活的全部,认为别人也应该这样想,否则就是不成熟、不知足,或是以过来人的姿态强调平庸的
可贵,把“平庸”等同于“平淡”。可是,许多人未曾想过,你认为好的未必是别人想要的,我们把自己认为好的东西强加于人,未必是关怀,而是侵犯。这样的事,在这个国家
随处可见,小城市似乎更明显一些,同时让人无处可躲,也无从辩驳。越是没有能力选择自己生活的人,越是庸碌无知的人,越喜欢嘲笑那些有勇气去承受压力的人。

不够现实的乌托邦,总会引来嘲笑。但是,如果你现在20多岁,你是希望看到一个乌托邦,还是看到自己60岁时的样子?

2014,我很喜欢这一年,过得很平淡,或许是我20几岁中最平淡的一年。当然,平淡中还是有不少的心灵上的起伏,今年最大的收获便是想明白了很多事情,没有以前那么
迷茫了。

那些一如往常的事

  • 还是拿了二等奖学金(1000),还是没有挂科(这学期没算上),今年没去考什么证了(一直不想考证,四六级只是毕业的需要),依然没想去参加什么比赛
  • 今年,依然看了很多的书,算下来,大概看了十二本技术书籍,六本非技术书籍,当然还有二十四本《读者》(唉,今年涨价了)

那些万万没想到的事

  • 万万没想到,今年还是没找到女朋友
  • 万万没想到,曾经视金钱如粪土的我,如今也开始为钱、为工作发愁了
  • 万万没想到,今年居然有腾讯的一个负责人邀请我加入
  • 万万没想到,曾经那么讨厌Web、Android的我,今年却学习了Html/PHP/Java/JS/NodeJS等语言以及相关的一些框架,并参与了一个实际的web项目
  • 万万没想到,一直对信息安全专业感兴趣并且因此而来到重邮的我,在大二大三分专业之际,如愿以偿进入了信息安全专业,并且还是最好的一个班之后,我却突然不想学了。那种感觉就像,你一直在追逐某样东西,但当你最终要到达终点的时候,结果已经不重要了。之所以放弃信息安全,是因为我认为这个行业技术要求确实高,而且技术分层太明显了,我从来不认为自己是一个高手,并且我不大喜欢去研究别人的东西(信安,必须知己知彼),我更喜欢创造,所以,即使我现在在信息安全专业,但也没怎么用心学习那个方向
  • 万万没想到,大一大二一直信誓旦旦地说要考研的我,居然在大二下学期突然放弃了考研这个想法,并且把之前的教材都卖了,我称之为破釜沉舟,这或许是我做得最决绝的一次。以前一直认为,大学本科多学一些基本知识,然后研究生阶段就多做一些实际的事情,这样或许能找一个更好的工作。但当我真正去采访了几个研究生后,我发现,考研或许并没有我想象的那么好。考研的学长多半都后悔了(当然,不可否认,没考研的人也多半都后悔了)。三年时间,毕业的时候是2019年,好像是25或者26了吧,我不想把我最美好的20几岁花在这上面,即使这样做或许会有更舒适的未来,但那样获得的未来我一定不会很高兴。所以,我还是坚持以前的想法,人生得意须尽欢,莫使金樽空对月,及时行乐,万一明天就挂了呢。我这个人想法很多,我喜欢的是创造,而不是看那些无聊的论文,而且没准研究生还要应付比社会上还要复杂的关系。所以,找工作,或者创业吧。

那些难忘的事

  • 今年,全家人在一起照了全家福(虽然还是有几个堂姐堂哥没到)

  • 今年,我发现,世界上不会吐痰的不只我一个,还有胡一菲……

  • 今年,大年初一就和一群朋友去河边吃烧烤,永远忘不了他们

  • 今年,家里终于把宽带升级为4M了,学校的宽带也免费升级到了4M,不过我回家的时间也越来越少了

  • 暑假参加了一次“三下乡”活动,现在都还记得酉阳那群小朋友

  • 今年,第一次一个人去看了一场电影《后会无期》

  • 今年将域名备案了,把服务器迁移回国内,并且采用了wordpress框架

  • 今年博客的单日最高访问量达到1600

  • 第一次暑假在学校呆了这么长的时间,大概一个月,而且几乎每天都在坚持锻炼,每天至少8圈

  • 第一次一个人生活了那么久,一个人在堂姐的房子里生活,每天按时起床、按时吃饭、按时睡觉,没想到一个人也能生活得这么有规律。但一个人的日子里,真想找另外一个人陪,那段日子,真的好憧憬能拥有自己的一个家

  • 第一次记错了开学时间,还好原计划就是提早来了几天

  • 第一次拥有了自己的一个云服务器,Github学生计划,Digitalocean的服务器

  • 第一次参加了开源活动,在我们学校举行的opensuse的发行party

  • 第一次参与实际的项目中去

  • 第一次在网上参加活动中奖¥600

  • 第一次因为写代码获得¥500

  • 终于买了一个机械表,顺便买了一个win8平板

  • 今年,侄女儿终于到我们家对面的学校上学了,我当年可是上初中才享受到这种待遇

  • 今年,哥哥又生了一个孩子,我终于有侄儿了,哈哈

  • 今年,火影漫画完结了,不过还好,我从不看漫画,不过明年,电视版也要结束了吧

  • 今年,学习了四个Coursera课程,并获得了三个完成声明

  • 今年,总共花费两万多

感情方面

  • 以前:和前女友分手两年了,今年终于没有怎么找她了,偶尔朋友式的聊聊天,完全没有了以前的感觉,这样也挺好,大家都能去追求新的幸福。不过,在我的内心,依然渴望能找到一个女朋友,因为我渴望爱情,渴望有一个家,我想为这个家努力奋斗。
  • 现在:曾经看到一句话:我们不是越长大越不相信爱情,而是越长大越分不清那是不是爱情。2014,上半年的我,什么都没想,连我都不知道上半年都做了什么,下半年却一直在和一个女生几乎天天聊天,年底就想向她表白,但是突然发现,我对她,她对我,都只是朋友的关系,其实完全没有其他的感情。
  • 未来:曾经有人问我,世界上有没有人会心甘情愿做备胎?我当时就说,有人。真正爱一个人的时候,你会心甘情愿付出,完全不会去想她会不会回报;真正爱一个人的时候,即使是做备胎,你也愿意一直守护在她身边;真正爱一个人的时候,哪怕十年,你也愿意等。其实,在我心里一直有这么一个人。现在的我不再迷茫,所以,无论她还会不会在意我长得矮,我也想自信一次,我只想为她努力一次。(其实,花了几天学习前端然后做了一个网页http://love.haofly.net想给她看的,但被v2ex上的网友批得惨不忍睹,想想还是放弃吧,女生或许更喜欢当面表白)
    我还真不相信会有谁一字一句把我的总结看完的,不过,反正主要是写个自己看的,也是为了写给以后的自己看看。

平淡的一年,继续走我的平凡之路。

![2014-the-last4](http://haofly.net/wp-content/uploads/2014/12/2014-the-
last4.jpg)

Docker:是一个开放源代码软件专案,在软件容器下自动布署应用程序,借此在Linux操作系统上,提供了一个额外的软件抽象层,以及操作系统层虚拟化的自动管
理机制[2]。Docker利用Linux内核中的资源分离机制,例如cgroups,以及Linux内核名称空间,来建立独立的软件容器(containers)。
这可以在单一Linux实体下运作,避免启动一个虚拟机器造成的额外负担。(维基百科)

Docker无疑是2014年人们谈论最多的虚拟开发环境构建工具,在我看来它是VirtualBox虚拟机最佳的替代方案,使用它的理由有三点:
1.轻量级,一个box只需要几百兆(Vagrant) 2.部署方便,有现成的base
boxes可供下载
(Vagrant),并且可以自己制作Image
3.运行流畅,几秒开机,占用内存十分的少(在我的电脑上,它甚至比Chrome占用的内存还要少)

而本文所要说的Vagrant这是其在Windows上的替代方案,它是使用VirtualBox动态创建和配置虚拟环境。它基于Ruby,但必须依赖其他的虚拟环境
构建工具,比如VirtualBox或者VM等。下面主要介绍其安装部署过程。

注:有一个快速的生成Vagrantfile的网站:https://puphpet.com,可以选择不同的操作系统,不同的开发环境(lamp,lnmp),如果设置了apache的域名,那么需要修改主机的host文

基础环境:Windows 7 + Git for Windows

  1. 下载并安装基本工具

Oracle VM VirtualBox:https://www.virtualbox.org/wiki/Downloads
Vagrant:https://www.vagrantup.com/downloads.html
安装完Vargrant后,可以直接在bash里查看是否安装成功

    $vagrant -v
Vagrant 1.7.1
  1. 下载box

Vagrant提供了一些常用的人们已经打包好了的box镜像,当然可以使用vargrant命令进行下载,但是总没有迅雷快吧,所以直接去官网下载:<http:/
/www.vagrantbox.es/> 其中,我选择的是Ubuntu Server Trusty 14.04 amd64:<https://oss-bin
aries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-amd64-vbox.box>[
](https://oss-binaries.phusionpassenger.com/vagrant/boxes/latest/ubuntu-14.04-
amd64-vmwarefusion.box)注意是virtualbox版本还是vmware版本,大小只有399M

  1. 初始化工作目录

vagrant init

此时会生成一个Vagrantfile文件,它就是该虚拟机的配置文件,可在里面配置端口或者文件的映射规则。
:其实添加box可以在任意位置添加,vagrant应该只是记录了其路径,然后vagrant init + name才是初始化的时候指定所需要的box,而默认的vagrant init会默认去寻找名为base的镜像。

  1. 添加镜像

vagrant box add

其中”base”就是你给镜像取的名字,vagrant box list可以列出当前所有的box(不仅仅是该目录),需要注意的是,由于我之前添加了一个同名的镜像,并且没删除干净,所以这里添加了一个--force参数

  1. 启动


这就是其启动过程,可以发现它的一些基本设置:如SSH端口为2222,用户名密码均是vagrant,/vagrant映射到本地的F:/docker/ubunt
u-server

  1. 连接进入

当虚拟机启动后,可以使用SSH连接工具XShell或者putty进行登录: 地址:127.0.0.1 端口:2222(虚拟机不同,端口会变的)
用户名:vagrant 密码:vagrant 或者直接使用vagrant命令登录:vagrant ssh

到这里,就可以确定安装完成了。 PS:所有创建了的box也都可以通过VirtualBox进行查看和配置:

Vagrant box的打包

通常,官网的list列表并不能提供我们自己所需要的运行环境,比如我有时候需要14.04的LAMP环境或者LNAMP环境,但又不想每次都重新安装一下,这时候就
可以去官网下载一个干净的base,对其修改后打包成自己的box,以后谁要用就直接取,里面已经安装好了所需要的环境了,打包很简单,使用的是vagrant package命令,但首先得启动该虚拟机:

注意我在该虚拟机的root用户目录里新建了一个名为haofly的文件,待会儿方便证明其确实是我修改后的box,下面只需要将package.box添加
到vagrant即可使用它来创建新的虚拟机了,为了方便管理,我将其复制了出来并重命名为ubuntu-14.04-amd64-lamp-20141225.b ox

Vagrant Manager的安装

vagrant
manager是一个正在开发中的vagrant的管理工具,主页在https://github.com/lanayotech/vagrant-
manager-windows

安装步骤:

  1. 下载安装 到其releases列表进行下载:https://github.com/lanayotech/vagrant-manager-windows/releases 然后直接运行安装即可。不过要是出现以下错误

    [ ](http://haofly.net/wp-content/uploads/2014/12/windows-install-
    vagrant5.jpg)表示你的电脑没有安装.NETFramwork 4.5那么就去安装,但如果这里点击“是”那么会跳到4.5.2去,我没安装上,所以
    之后直接下载了4.5([下载地址](http://www.microsoft.com/zh-
    cn/download/details.aspx?id=30653))安装上了

  2. 界面

    它没什么单独的界面,就是在右下角的一个控制图表,点击就可以了。

  3. 需要注意的是:vagrant manager目前存在一个很大的缺陷就是只能操作C盘下的box,不然什么操作都会出现错误 _A Vagrant environment or target machine is required to run this command. Run vagrant init to create a new Vagrant environment. Or, get an ID of a target machine from vagrant global-status to run this command on. A final option is to change to a directory with a Vagrantfile and to try again. _其实,开发人员也一直在关注着这个问题:https://github.com/lanayotech/vagrant-manager-windows/issues/8

Vagrant常用命令:

vagrant box add name:添加box vagrant box list:列出当前所有的box vagrant box remove
name:列出某个box(名字就是自己给取的,比如上面的base) vagrant box repackage name:对某个box重新打包
vagrant init [name]:初始化当前目录为工作目录 vagrant up [name]:启动虚拟机 vagrant destroy
[name]:删除虚拟机 vagrant suspend [name]:暂停某个box vagrant reload [name]:重新加载 vagrant
resume [name]:恢复虚拟机 vagrant halt [name]:关闭虚拟机 vagrant ssh:连接虚拟机 vagrant
package –output name:如果对虚拟机的配置进行修改过后,如果想把当前环境打包,可使用这个命令 vagrant
status:查看虚拟机状态

TroubleShooting

  1. 在linux环境下,共享目录的权限无权限问题: Vagrant Synced Folders Permissions 解决方法是在Vagrantfile里面进行如下配置:

    config.vm.synced_folder “/docker/ubuntu/“, “/var/www/html”,
    id: “vagrant-root”,
    owner: “nobody”,
    group: “nobody”,
    mount_options: [“dmode=775,fmode=664”]

  2. 连接mysql数据库出现如下错误:

    Lost connection to MySQL server at ‘reading initial communication packet’, system error: 0

那么应该是mysql的bind-address未配置正确,应该将其改为eth0的地址,而不是该虚拟机的IP地址,当然,改为0.0.0.0也行

  1. 集群(同时开启多个虚拟机,虚拟机之间通过IP访问),vagrantfile可以这样配置,例如:

    -- mode: ruby --

# vi: set ft=ruby :




Vagrant.configure(2) do |config|
    config.vm.define :master do |master|
        master.vm.provider "virtualbox" do |v|
            v.memory = "1024"
            #v.gui = true
        end
        master.vm.box = "django"
        master.vm.hostname = "master"
        master.vm.network "private_network", ip: "192.168.111.10"
        master.vm.network "forwarded_port", guest: 8000, host: 8000
        master.vm.network "forwarded_port", guest: 3306, host: 3307
        master.vm.synced_folder "F:/workspace/wh_operation", "/django"
    end




    config.vm.define :slave do |slave|
    slave.vm.provider "virtualbox" do |v|
        v.memory = "1024"
        #v.gui = true
    end
    slave.vm.box = "django"
    slave.vm.hostname = "slave"
    slave.vm.network "private_network", ip: "192.168.111.11"
end

end

由于在实际项目中,经常遇到前后端传递错误代码,或者发现错误代码的情况,而每次遇到都不一定能快速找到原因,所以这里就把常见的错误代码列出来,并附上我在实际开发中所遇到的问题的原因。

注意:HTTP状态码本身是支持以小数的方式进行扩展的,比如403表示禁止访问,403.1表示禁止可执行访问,403.2表示禁止读访问等。

httpstat.us: 能够测试不同的状态码的接口返回,并且支持自定义cors参数

阅读全文 »

原文地址:<http://segmentfault.com/blog/lpgray/1190000002397061?utm_source=weibo&ut
m_medium=shareLink&utm_campaign=socialShare>

还记得第一次看到CC协议的时候,我惊叹道:世界上竟有如此可爱的协议。之后渐渐融入了开源的世界,了解了更多类似的协议,我个人非常尊重别人的知识,所以可以看到
在我的博客里面每一篇文章,凡是有借鉴别人的,我一定把别人的文章链接放在文章开始处,以显示对对方的尊重,另外,我的博客完全采用CC协议,转载必须注明出处。以下
是该文章的内容。

最近想搞一个个人小项目,比较在意版权问题,平时在github上经常看到其他人的项目有各种License,却一直没明白过,今天查阅了一些软件License方面
的资料,在此记录一下。

什么是License?

License并不意味着你对你的产品放弃了著作权,一旦你使用了License,则表示你授权给他人以约定的形式来使用你的产品。

几种常用License

GPL (GNU General Public License)

GNU General Public License (GPL)的可能是开源项目最常用的许可证。GPL赋予和保证了开源项目开发者广泛的权利。

它允许用户合法复制,分发和修改软件,甚至在改良版本上收取费用,但必须要写明GPL License,而且要告诉客户原始版本。

LGPL

还有另一个GNU License:GNU Lesser General Public License (LGPL)。比起GPL它授予的权限较少。一般来说,L
GPL比较适合连接到非GPL或者非开源文件的库文件。由于GPL的规定,使用到部分GPL代码的软件,必须也使用GPL,开发人员不能使用GPL来开发收费软件或者
专有软件。

LGPL不要求使用与部分代码相同的 License。

BSD

BSD License与其他自由软件License相比,如GPL,限制更少。但是请注意到BSD License两种版本之间的差别:New BSD
License/Modified BSD License 和Simplified BSD License/FreeBSD
License。它们两者都是于GPL兼容的自由软件License。

New BSD License

New BSD License (”3-clause license”) 可以用于任何作为版权声明和保证许可的免责声明的目的,可以通过无限长的再分发来得以维
持,也就是说如果再发布的产品中包含源代码,则在源代码中必须带有原来代码中的BSD协
议。它还有一个特殊限制条款,不用特别的许可就是限制使用派生工作的工作者名字,也就是说不可以用开源代码的作者/机构名字和原来产品的名字做市场推广。

New BSD License和Simplified BSD License的主要区别是,后者忽略了非认可条款。

MIT

MIT是和BSD一样宽松的许可协议,作者只想保留版权,而无任何其他了限制.也就是说,你必须在你的发行版里包含原许可协议的声明,无论你是以二进制发布的还是以源
代码发布的。

  • 你可以修改、复制和使用
  • 你可以出售
  • 但必须附带MIT授权协议

Mozilla Public License 1.1 (MPL)

MPL协议允许免费重发布、免费修改,但要求修改后的代码版权归软件的发起者。这种授权维护了商业软件的利益,,它要求基于这种软件得修改无偿贡献版权给该软件。这样
,围绕该软件得所有代码得版权都集中在发起开发人得手中。但MPL是允许修改,无偿使用得。MPL软件对链接没有要求。

商业软件可以使用,也可以修改MPL协议的代码,但修改后的代码版权归软件的发起者。

CDDL

CDDL(Common Development and Distribution License,通用开发与销售许可)开源协议,是MPL(Mozilla
Public License)的扩展协议,它允许公共版权使用,无专利费,并提供专利保护,可集成于商业软件中,允许自行发布许可。

商业软件可以使用,也可以修改CDDL协议的代码。

Apache License

Apache Licence是著名的非盈利开源组织Apache采用的协议。该协议和BSD类似,同样鼓励代码共享和尊重原作者的著作权,同样允许代码修改,再发布
(作为开源或商业软件)。

  • 需要给代码的用户一份Apache License
  • 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明
  • 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache
    License。你可以在Notice中增加自己的许可,但不可以表现为对Apache License构成更改
  • 商业软件可以使用,也可以修改使用Apache协议的代码

Eclipse Public License

EPL是一个与CPL相类似的许可证,任何扩展自Eclipse源码的代码也必须是开源的

Creative Commons(CC)

Creative Commons(CC)的许可证不太开放源代码授权,它们通常用于设计项目。
CC许可证有着宽广的定义,每个定义都会授予一定的权利。它有四个基本部分,可以单独或者组合使用。

  • 作者必须是作品的原创者。 除此之外,作品可以修改,分发,复制和以其他方式使用
  • 工作可以修改,分发等等,但必须在一个许可证下
  • 可以修改,分发等,但不用于商业目的。 关于什么是“商业”,说法比较含糊(没有提供明确的定义),因此您可能需要在自己的项目中澄清这一点
  • 禁止修改,这意味着您可以复制和分发许可工作,但你不能以任何方式修改,或在原有的基础开发
  • 商业软件的使用要遵从CC协议的具体规定,最严格的许可证将是“署名,非商业,不能修改”的授权。这意味着你可以自由共享的工作,但不能改变它,你必须把
    它归功于原创者

Common Public License 1.0

  1. 明确了专利授权。一般的开源软件都明确源代码的版权人将自己的修改权、复制权等版权权利向公众许可,但保留署名权,而Common许可证在此基础上还明确假如源代码中含有专利权,源代码专利权人将复制、使用的专有权利向公众许可。
  2. 规定可以将源代码及修改过的源代码与其他类型的不受本许可证约束的代码结合,以新产品的形式发布,只要其中经该许可证获得的源代码及修改过的源代码能按该许可证的要求发布即可。
  3. 细化了该许可证终止的情形,包括发生专利侵权诉讼。
  4. 明确了一个独立承担责任的原则,就是假如按该许可证使用源代码的使用者将获得的源代码应用于商业使用,那么他就要对在商业应用中出现的由于使用该源代码程序而产生的侵权诉讼承担完全责任。这一条规定是比较特殊的,绝大多数开源软件许可证都不这么要求。
  5. 商业软件可以使用,也可以修改Common协议的代码,但要承担代码产生的侵权责任。

这一个多月来都没发过任何的博文,就是因为一直在忙工作室的项目。而今天我终于了解到,老板貌似已经放弃这个项目了,而且我居然完全不知道。不过,无论怎样,在这次项
目中我还是学到了很多很多。

首先,简单说一下,我们做的是一个外卖网站,我担任的角色是后端开发和服务器与数据库的运维,前端4人,后端2人,我是后端负责人。
![](http://7xnc86.com1.z0.glb.clouddn.com/the-conclusion-of-the-first-project-
of-studio.png)

团队协作出现的问题

1.无需求,无策划,无设计,项目开始后基本只有开发人员

这是最大的弊端,我也是醉了。项目开始前,我一直催老板快把需求拿来,最后拿是拿来了,但是至今我也没看过,当项目正式开始时他就叫前端去设计接口,但是今天突然了解
到,前端也没有看到过需求。也就是说整个项目做到现在,所有的功能,基本上都是前后端开发人员自己“臆想”出来的。而且整个过程无策划、无设计人员的参与。项目开始几
天后,我的概念就变成了,完全复(chao)制(xi)另外一个外卖网站。

2.前后端缺乏沟通

前期前端的接口出的比较慢,不过我们后端也一直在按自己的想象做着“可能”有的功能,但后端并没有对前端的接口进行审核。当项目进行对接的时候我们才意识到问题的严重
性。接口基本上对不上,整个网站,全是404,503等错误,怎么办呢?改吧,改的时间居然花费了整个项目1/3的时间,这时候大家才开始加强了沟通。

Deadline是第一生产力(中间就是项目对接的时候):
![](http://7xnc86.com1.z0.glb.clouddn.com/the-conclusion-of-the-first-project-
of-studio_1.png)
另外,虽然老板专门租了一个房间给我们,但距离学校太远,所以几乎没人去那里写代码,我们更多的算是一个远程团队,但完全没有交流。

3.分工明确,但不清楚自己和别人具体该做什么

项目里分工应该是明确的,我们后端就按照功能分为了三个部分,前端由于人多,分得有点杂。但我们却不大明确自己和别人具体该做什么。比如我们后端,虽然按功能划分,但
毕竟有些功能是有交叉的,而没有好好的沟通进一步明确,导致有些功能两个人都以为自己不做,就最后就都没做(由于另外一个后端系大四学长,能力应该比我强,所以我对他
太放心了,但其实可能他太忙了,并没有太在意这个)。另一个就是不清楚别人做的什么地方,每次遇到前端的问题,不知道该找谁,无论是谁,都说不是自己负责的,看样子他
们跟我们后端的情况差不多。我觉得分工这些地方一定得形成文档。

4.没有测试过程

工作室处于初期,没有专门的测试团队或人员,我觉得这一点无可厚非,完全可以理解。但却没人从来没人去把整个业务流程完整走一遍,只是偶尔老板会主动去走一下,然后发
现一大堆的问题,然后统一写一个文档发到群里,然后,没多少人在意。

个人学到的经验

我也不知道这个项目最终会变成怎么样,但在这次项目中确实学习到了不少东西。

1.工具的使用

好吧,我承认,之前基本上没用过PHP的,但是我觉得我的学习能力还是挺快的,基本上很快就熟练了。之前并没有用过框架开发,这次使用的是Laravel框架,前期花
费了大量的时间学习,对项目为什么要使用框架有了一些了解,并对框架的特性有了一些了解。对于实际的项目,框架是必须的,不可能不使用框架而纯使用PHP的基本语法来
实现,学习了一个框架看其他的类MVC框架其实都差不多的。 另外,一定要好好利用github和git,github可不仅仅是代码托管的地方,在github上,
还可以对问题进行跟踪,提交issue。一旦发现了不是自己的bug千万不要憋着,立马提交上去,看不看是他们的事(当然,可能因为我们都是大学生,基本上这算是我们
的第一个项目,所以基本不会主动去看,我也是后期才意识到的)

2.学会沟通

为什么还要去学会沟通,因为项目中沟通和普通的沟通不一样。不要因为某位成员技术不够就无视他(好吧,我一般是被无视的一方,程序员钻牛角尖怎么了?),也不要因为某
位成员比你厉害就害怕与其沟通。另外在QQ聊天中如果有问题要提出就一定要一下说完,别说一句顿一下的,不知道为什么80%的人都这样。之前我很少在写代码的时候把Q
Q登录上,但这次项目大家只有在QQ里交谈,所以只能一直在线。一般的情况就是这样:当我在很认真的写代码的时候,QQ突然叫一下,显示“我发现了一个问题”,就等着
他发具体的问题过来,但许久没发过来(大概1分钟),于是最小化窗口,继续写代码,一会儿又跳出来,这次发了张截图过来,但是我还是无法看出具体问题,就等他进一步描
述,又1分钟,最小化,继续写代码,又弹出来QQ,好吧,终于知道问题是什么了,每次都想骂一句,你他妈就不会一次说完吗?

3.时间的安排

我认为在本次项目中,我时间安排上还是合理的,不过太投入了。平时都没有去学习其他的东西,因为害怕一学习就会耽误时间,唉,太投入也有错。

4.对远程工作的看法

虽然本次项目在概念上不算是远程工作,但大家都是通过QQ交流的,所以在性质上还是比较类似。而且我一直挺关注远程工作的,最近对远程工作也有了一些新的看法。
远程工作,必须要有完整的管理流程 团队必须及时交流,并提供定时交流的时间 项目不同的模块,谁拍板谁负责
PS:我很喜欢远程工作的模式,但始终找不到志同道合的人。找一个前端都太难了,但我主要觉得还是性格和价值观上的不同早就的,不过我相信我会找到的。

Laravel指南

Laravel项目基本结构

十分推荐安装laravel-ide-helper

配置

  • .env文件中,如果有空格,那么值需要用双引号包围,并且里面如果用\n,那么必须转义\\n
  • 如果.env不起作用,可以尝试清理缓存php artisan cache:clear
  • laravel可以根据不同的系统环境自动选择不同的配置文件,例如,如果APP_ENV=testing,那么会自动选择读取.env.testing中的配置,如果有.env则会被覆盖,特别是单元测试和artisan命令中

Laravel的主配置文件将经常用到的文件集中到了根目录下的.env目录下,这样更高效更安全。其内容如下:

阅读全文 »

Html

基本格式

  • deferasync的区别:
    • defer: <script defer src="myscript.js"></script>,加载后续文档元素的过程将和该脚本的加载并行进行(异步),并在最后执行
    • async: <script async src="script.js"></script>,加载后续文档元素的过程将和该脚本并行进行,并在最后执行
    • 什么都没有则是立即加载并且立即执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>                   <!--文档声明-->
<html lang="zh-CN"> <!--指定页面语言-->
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"> <!--兼容IE-->
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <!--编码声明-->
<meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests"> <!--将网页中的http请求默认提升到https请求,防止出现mixed-content错误-->
<title>标题信息</title>
<link href="styles.css" rel="stylesheet" ><!--添加样式表-->
<link rel="icon" href="favicon.ico" type="image/gif" sizes="16x16"> <!--设置favicon-->
<link rel="canonical" href="https://haofly.net/html" /> <!--权威内容标签,SEO有用,可以参考https://ahrefs.com/blog/zh/canonical-tags/-->
<link rel="alternate" href="https://haofly.net/en/html" hreflang="en" /> <!--网页可选语言-->

<script src="scripts.js"></script> <!--添加Js脚本-->
<style type="text/css"></style> <!--内嵌CSS-->
</head>
<body>
页面主体
<p>段落</p> <!--段落-->
<br> <!--换行-->
<hr> <!--水平线-->
<img alt="Horsehead" src="Horse.jpg" /> <!--图片-->
</body>
</html>
阅读全文 »