对于同一个页面布局,几乎每个人的写法都不一样,有人喜欢Flex弹性盒子布局,有的人则喜欢Float浮动布局,有些人喜欢Margin负值布局,等等。从来就没有一种统一的布局方案,现在大伙写代码也就放飞自我,只要能在规定的环境上跑起来,不会乱就行了。但是,身为脑瘫正经前端,我们还是有必要分出在不同情况应使用的布局。
这一篇博客比起作为文章,不如作为工具书。当你对布局迷茫时,不妨打开看看。我们可以不求甚解,只需要先把所有布局掌握熟练。
文章目录
CSS3 终极布局指南
正常布局(语义化布局)
正常布局,按照浏览器的内置CSS渲染
应用场景
带来的问题
挫
不兼容
没有自适应
解决方案
Float浮动布局
什么是浮动?
浮动元素的排列
浮动解决的布局问题
浮动带来的问题
父元素高度坍缩
不希望浮动时清除浮动
总结
定位布局
定位的应用
static
relative
absolute
高度坍缩
对比float
总结
fixed
祖先未使用transform:none
使用
sticky 粘性定位
Flex布局
浏览器支持
Flex使用介绍
Flex容器属性
flex-direction 排布方向
flex-wrap 控制换行
flex-flow [排布方向/控制换行]的简称
justify-content 子项目在主轴上的排布
align-items 子项目在交叉轴排布
align-content 定义多根轴线排布
Flex子项属性
order 子项排布靠前排名
flex-grow 子项放大比例
flex-shrink 子项缩小比例
flex-basis
flex
align-self
Grid 布局
参考
声明
正常布局(语义化布局)
正常布局,按照浏览器的内置CSS渲染
大道至简在远古时代,CSS还有没被发明,浏览器渲染HTML的时候,只是按照规定好的如标题、段落、表格等格式渲染。且不同的浏览器对于相同元素的渲染也是不同的,现在这项传统艺能保留到了今天。
不过到了今天,正常布局也稍微被W3C重视了一下。在HTML5的规定中,新增加了不少语义化的元素。所谓语义化元素就是让大家规定它就是来做这件事的。
新增加的语义化元素。
标签名称 作用
hearder header 标签定义文档的页面组合,通常是一些引导和导航信息。
nav nav 标签定义显示导航链接不是所有的成组的超级链接都需要放在nav标签里。nav标签里应该放入一些当前页面的主要导航链接。 例如在页脚显示一个站点的导航链接(如首页,服务信息页面,版权信息页面等等),就可以使用nav标签,当然,这不是必须的。
article article标签装载显示一个独立的文章内容。例如一篇完整的论坛帖子,一则网站新闻,一篇博客文章等等,一个用户评论等等 artilce可以嵌套,则内层的artilce对外层的article标签有隶属的关系。例如,一个博客文章,可以用article显示,然后一 些评论可以以article的形式嵌入其中。
section section 标签定义文档中的节(section、区段)。比如章节、页眉、页脚或文档中的其他部分。
aside aside 用来装载非正文类的内容。例如广告,成组的链接,侧边栏等等。
hgroup hgroup 标签用于对网页或区段的标题元素(h1-h6)进行组合。例如,在一个区段中你有连续的h系列的标签元素,则可以用hgroup将他们括起来。
time time 标签定义公历的时间(24 小时制)或日期,时间和时区偏移是可选的。该元素能够以机器可读的方式对日期和时间进行编码,这样, 举例说,用户代理能够把生日提醒或排定的事件添加到用户日程表中,搜索引擎也能够生成更智能的搜索结果。
mark mark 标签定义带有记号的文本。请在需要突出显示文本时使用 <mark> 标签。
figure figure标签规定独立的流内容(图像、图表、照片、代码等等)。figure 元素的内容应该与主内容相关,但如果被删除,则不应对文档流产生影响。
可以看到HTML5规定中增加了不少新的标签,但是这些标签大部分并不是为了补充正常的文档布局的,而是服务于搜索引擎的爬虫。不要觉得页面布局只是给人看的!对于布局清晰地页面,搜索引擎的爬虫也会给出更高的分数。
应用场景
作为布局的基石。
开发较为单一的页面,比如电子书阅读页面,面向视力障碍人士的报纸页面等。
带来的问题
挫
使用浏览器默认的CSS意味着你不可定制自己的页面,对于像<ul>、<table>这样的标签,你也只能忍受上世纪的设计风格了。
不兼容
先前说了,每个浏览器对于基础的HTML节点的渲染都不一样,也就是说你写的页面在IE上是一个风格,换到Safari上又是一种风格。
没有自适应
有一说一,正常布局(语义化)还是用来当基石比较好,对于响应式、自适应那还得看下面伙计的发挥。
解决方案
解决挫的方法就是使用style属性,也就是使用CSS美化我们的页面。解决不兼容的问题则需要初始化CSS,大伙应该在不少的页面的头部见过一大坨css代码吧,就像下面Google页面。(部分)
body{color:#000;margin:0}body{background:#fff}a.gb1,a.gb2,a.gb3,.link{color:#1a0dab !important}.ts{border-collapse:collapse}.ts td{padding:0}#res,#res .j{line-height:1.2}.g{line-height:1.2;text-align:left;}.ti,.bl{display:inline}.ti{display:inline-table}#rhs_block{padding-bottom:15px}a:link,.w,#prs a:visited,#prs a:active,.q:active,.q:visited,.kl:active,.tbotu{color:#1a0dab}.mblink:visited,a:visited{color:#609}.cur,.b{font-weight:bold}.j{width:42em;font-size:82%}.s{max-width:48em}.sl{font-size:82%}
1
页面初始化也是很重要的,它可以使我们的代码健壮的运行在各个环境的浏览器上。
Float浮动布局
什么是浮动?
如果首先要认识一个物品,认识一个东西的最好方式是了解为什么会产生它,也就是要翻它的历史。——NaoTan·Ma·Nong
看上图,啊,报社最爱的环绕,一堆文字环绕一张图片,这样的布局使得页面紧凑,并且有较好的阅读体验。如果我们要在HTML中实现这样的布局应当怎么设置呢?手动设置换行?不行,缺少灵魂。如果能使文字绕过图片排列下来就好了。
于是Float属性出世,它不仅解决了文字环绕问题,并且带来了新的布局方案。
如上面的布局,我们用代码实现主要部分。
.side-bar{
float:left;
}
.main-content{
float:left;
}
1
2
3
4
5
6
浮动元素的排列
当一个元素被设置为浮动元素时,首先,它会被移除文档流,设置float:left|right则元素会向设置方向排列,直到遇到父元素边框(或者说最大宽度)或者另一个浮动元素时停止。
当设置父元素display:flex时,子元素的浮动值无效!
浮动解决的布局问题
使用浮动我们可以解决传统的两列布局、三列布局的自适应。下面代码是用浮动实现的两列布局。
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>两列布局</title>
<style>
body,
html {
margin: 0;
background-color: rgb(228, 228, 228);
}
header {
margin-bottom: 20px;
}
footer {
margin-top: 20px;
}
.layout {
height: 50px;
border: 1px solid black;
}
aside {
width: 25%;
float: left;
border: solid 1px black;
height: 500px;
}
article {
width: 70%;
border: solid 1px black;
height: 500px;
float: right;
}
</style>
</head>
<body>
<header class="layout"></header>
<div style="overflow:auto;">
<aside>
</aside>
<article>
</article>
</div>
<footer class="layout"></footer>
</body>
</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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
效果如下
浮动带来的问题
父元素高度坍缩
一般来说新手在学习浮动布局之后,遇到的第一个问题就是父元素高度坍缩。什么是高度坍缩?
看上图,在父元素的四个子元素均为浮动元素,由于浮动元素的特性浮动元素脱离文档流,所以父元素不会被撑起高度。
如何解决?答案很简单,使用BFC块级格式上下文。当父元素为BFC的时候,内部计算高度会带上浮动元素的高度。
不希望浮动时清除浮动
使用clear属性可以使元素清除周围的浮动。
如上图,对段落文字清除浮动,导致原本环绕的文字,另起一行。顺便解决了高度坍缩的问题。
总结
浮动在带来方便的同时也引入了新的问题,如果能处理好这些问题那么浮动也可以当做布局的主力,但是都已经9102年了,我们应该追随CSS3的布局方案,尽量少使用浮动。
定位布局
收拾房子的时候总会把物品按照相应的位置放置,这样会让房间看上去更加整洁。所以,我们CSS也是可以这样做的。
使用position属性,调整元素的位置。position一共有四种定位类型:定位元素、相对定位、绝对定位、粘性定位,五种取值:static、relative、absolute、fixed、sticky。
名称 描述 定位类型
static 该关键字指定元素使用正常的布局行为,即元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index属性无效。 定位元素
relative 该关键字下,元素先放置在未添加定位时的位置,再在不改变页面布局的前提下调整元素位置(因此会在此元素未添加定位时所在位置留下空白)。position:relative 对 table-*-group, table-row, table-column, table-cell, table-caption 元素无效。 相对定位
absolute 不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。 绝对定位
fixed 不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先。 绝对定位
sticky 盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky对 table 元素的效果与 position: relative相同。 粘性定位
一般使用position属性时,会使用其相对定位与绝对定位、粘性定位,它们都使用top、bottom、left、right来调整自身位置,但是调整的基准不一样。
定位的应用
static
static是元素正常出现在文档流中的定位,文档流中的排列为自上而下,自左至右。一般来说block元素自占一行,inline元素横向排列。
正常情况下在我们的页面中大部分元素为static定位,对于一些特殊需求我们需要使用其他定位。比如像wiki中的关键词,鼠标移动上去的时候,关键词下面显示式卡片。
relative
relative是在实现一些特殊布局的时候经常使用的一种定位方式。设置为relative的元素并不会脱离文档流,但是可以通过top、bottom、left、right调整元素对于默认基准的位置。
.box {
display: inline-block;
width: 100px;
height: 100px;
background: red;
color: white;
}
position: relative;
top: 20px;
left: 20px;
background: blue;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
使用相对定位可以实现一些炫酷的效果。
.content{
text-align: center;
margin: 20px;
}
.card{
position: relative;
display: inline-block;
width: 200px;
height: 200px;
background-color: darkgray;
top: 210px;
right: 170px;
visibility: hidden;
}
span:hover+.card{
visibility:visible;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="content">
<span>鼠标移到我身上!</span>
<div class="card">
</div>
</div>
1
2
3
4
5
6
效果
但是,使用相对定位依然会出现一些问题。relative定位并不会脱离文档流,所以.content元素的高度为200px。
absolute
与relative定位不同的是absolute是脱离文档流的,而且相对基准是position属性不为static的祖先元素,如果祖先都是static则元素相对body定位。并且,对于absolute元素,如果不设置top/bottom/left/right的话依然排列在正常布局位置。
html,
body {
margin: 0;
}
.content {
position: relative;
/ top: 50px; /
margin-top: 50px;
}
.static {
position: static;
}
.relative {
position: relative;
margin: 20px 0;
}
.absolute {
display: inline-block;
width: 50px;
height: 50px;
background-color: lightcoral;
position: absolute;
}
.non-ab {
display: inline-block;
width: 50px;
height: 50px;
background-color: darkblue;
margin-left: 100px;
}
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
<div class="content">
<div style="height: 50px;"></div>
<div class="static">
<div class="non-ab">
</div>
<div class="absolute">
</div>
</div>
<div class="relative">
<div class="absolute">
</div>
<div class="non-ab">
</div>
</div>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
上面的代码很有意思,有兴趣的同学可以放在codepen上面跑一下子。这个例子验证了absolute的排列方式。当我们知道我们在做什的时候,也就不需要墨守成规(对于absolute元素的父元素统一设置relative属性)了。
高度坍缩
只要是脱离了文档流的元素都会出现高度坍缩,所以在使用absolute属性时,请确保父元素不会因此而改变。
对比float
Float与absolute都会使元素脱离文档流,但是众所周知对相同元素设置float与设置absolute会出现不同的效果。这是因为float与absolute本身的排列不一样。
float:脱离文档流,排列时以父元素为基准,并且会为占用其他浮动元素的位置。
absolute:脱离文档流,排列时分情况:第一种情况,对于未设置left、right、top、bottom属性的元素,排列在正常显示位置,并不占用空间。第二种情况,设置位置属性的元素,基于非static祖先元素排列。
上面两者比较显著的差异为float会影响下一个float元素,但是absolute元素不会。
总结
说absolute为绝对定位也并不贴切,它也是基于祖先元素定位的,只是脱离了文档流。我个人还是比较推荐在处理元素相对位置问题上使用absolute属性的,但前提是您已经深刻理解了absolute的排列方式。
fixed
不为元素预留空间,而是通过指定元素相对于屏幕视口(viewport)的位置来指定元素位置。元素的位置在屏幕滚动时不会改变。打印时,元素会出现在的每页的固定位置。fixed 属性会创建新的层叠上下文。当元素祖先的 transform 属性非 none 时,容器由视口改为该祖先。
fixed元素也会脱离文档流,并且和absolute元素一样,当不设置任何left、top、bottom、right值的时候,元素依然按照正常定位的位置放置。
祖先未使用transform:none
当祖先元素未使用transform:none的时候,fixed元素相对于该祖先元素进行定位。
在上面的图片中,我设置小黄块为fiexd属性,并让父元素设置为 使用transform:matrix(1, 0, 0, 1, 0, 0);,这时候小黄块并没有相对于body进行定位,当滚动条下拉时,小黄块定位固定在父元素左上角。
使用
fiexd元素一般用在如:to-top按钮,或者侧边悬浮面板,或者悬浮导航栏之中。
sticky 粘性定位
盒位置根据正常流计算(这称为正常流动中的位置),然后相对于该元素在流中的 flow root(BFC)和 containing block(最近的块级祖先元素)定位。在所有情况下(即便被定位元素为 table 时),该元素定位均不对后续元素造成影响。当元素 B 被粘性定位时,后续元素的位置仍按照 B 未定位时的位置来确定。position: sticky对 table 元素的效果与 position: relative相同。
上面我们使用了fiexd与transform,发生了我们意想不到的效果,那就是fixed元素并未相对于body进行移动,也没有在父元素中进行标准的fixed定位。现在我们使用以下sticky属性来看一下效果。
<style>
.box{
box-sizing: border-box;
height: 150px;
border:solid 3px black;
margin: 0 0 20px 0;
overflow: auto;
}
.block{
width: 50px;
height: 50px;
background-color: orange;
}
.sticky-1{
position:sticky;
top: 0px;
}
</style>
<div class="box box-1">
<p>下面这个小黄块设置为sticky</p>
<div class="sticky-1 block">
</div>
<p>
hahah
</p>
<p>
hahah
</p>
<p>hahaha</p>
<p>hahaha</p>
</div>
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
当我们向下滚动的时候神奇的事情发生了。
小黄块固定到了父元素的top:0位置了,不仅如此,再向上滑动后,小黄块又回复了当时的位置,而且占用了文档本身的位置。
使用这个特性我们可以制作浮动的Header组件,当用户向下滑动至窗口上侧的时候,Header组件也跟随窗口滑动。
Flex布局
对于前端工程师来说,最让人头疼的莫过于自适应布局。对于不同分辨率的设备要做到页面统一,在CSS3出现之前,还是挺不容易的。还有就是前端工程师头疼的一个布局问题:垂直居中。
CSS3中新出了一种布局技术:CSS弹性盒子布局,我们来看一下MDN是如何介绍的。
CSS 弹性盒子布局是 CSS 的模块之一,定义了一种针对用户界面设计而优化的 CSS 盒子模型。在弹性布局模型中,弹性容器的子元素可以在任何方向上排布,也可以“弹性伸缩”其尺寸,既可以增加尺寸以填满未使用的空间,也可以收缩尺寸以避免父元素溢出。子元素的水平对齐和垂直对齐都能很方便的进行操控。通过嵌套这些框(水平框在垂直框内,或垂直框在水平框内)可以在两个维度上构建布局。
接下来,我会使用Flex布局技术,设计一些我们常使用页面布局,并指出优点与缺点。但是,我们首先要来看一下浏览器的支持程度。
浏览器支持
特性 Firefox (Gecko) Chrome Internet Explorer Opera Safari
基础支持 20.0 (20.0) 21.0-webkit 29.0 10.0-ms 11.0 12.10 6.1-webkit
主流的浏览器全部支持Flex属性。注:与社会脱轨的IE9并不支持Flex,如果想写出兼容IE9的页面,请不要使用Flex。
Flex使用介绍
使用flex务必清楚一些属性概念。
Flex容器:对于一个基本元素(不含任何CSS属性,如div),设置display:flex,即可创建一个Flex容器。
Flex子项:父元素为Flex容器的元素,称之为Flex子项,其排布受到父元素影响。注:一定是父元素为Flex容器的元素,祖先不算。
排布方向:指Flex子项在Flex容器中的排布方向。排布方向有两种:column、row。在Flex容器上使用flex-direction: column|row(默认);即可设置。
主轴:指的Flex容器中是与排列方式相同的方向的轴。如设置Flex容器direction: column;则其主轴为竖直方向。
交叉轴:指的Flex容器中是与排列方式相反的方向的轴。如设置Flex容器direction: column;则其主轴为水平方向。
我们一定要清楚上面的基础概念,这对深入使用Flex有很大的帮助。下面我会介绍一些Flex常用的属性,主要分为两部分:对Flex容器、对Flex子项。
Flex容器属性
flex-direction 排布方向
flex-direction 属性指定了内部元素是如何在 flex 容器中布局的,定义了主轴的方向(正方向或反方向)。
flex-direction属性接受以下值:
row:子项目在flex容器中横向,从左至右排列。
row-reverse:表现和row相同,也是横向,但是是从右到左。
column:子项在容器中竖向排列,从上至下。
这里不贴图了
column-reverse:表现和column相同,子项在容器中竖向排列,从下至上。
这里不贴图了
flex-wrap 控制换行
CSS flex-wrap 指定 flex 元素单行显示还是多行显示 。如果允许换行,这个属性允许你控制行的堆叠方向。
取值:
nowrap(默认)
flex 的元素被摆放到到一行,这可能导致溢出 flex 容器。 cross-start 会根据 flex-direction 的值 相当于 start 或 before。
wrap
flex 元素 被打断到多个行中。cross-start 会根据 flex-direction 的值选择等于start 或before。cross-end 为确定的 cross-start 的另一端。
wrap-reverse
和 wrap 的行为一样,但是 cross-start 和 cross-end 互换。
flex-flow [排布方向/控制换行]的简称
CSS flex-flow 属性是 flex-direction 和 flex-wrap 的简写。
示例:flex-flow: column-reverse wrap;
justify-content 子项目在主轴上的排布
CSS justify-content 属性定义了浏览器如何分配顺着父容器主轴的弹性元素之间及其周围的空间。
justify-content同时受到父容器主轴的影响。
取值:
start
从行首开始排列。每行第一个元素与行首对齐,同时所有后续的元素与前一个对齐。
flex-start(默认)
从行首开始排列。每行第一个弹性元素与行首对齐,同时所有后续的弹性元素与前一个对齐。
flex-end
从行尾开始排列。每行最后一个弹性元素与行尾对齐,其他元素将与后一个对齐。
center
伸缩元素向每行中点排列。每行第一个元素到行首的距离将与每行最后一个元素到行尾的距离相同。
left
伸缩元素一个挨一个在对齐容器得左边缘,如果属性的轴与内联轴不平行,则left的行为类似于start
right
元素以容器右边缘为基准, 一个挨着一个对齐,如果属性轴与内联轴不平行,则right的行为类似于start.
space-between
在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素与行首对齐,每行最后一个元素与行尾对齐。
space-around
在每行上均匀分配弹性元素。相邻元素间距离相同。每行第一个元素到行首的距离和每行最后一个元素到行尾的距离将会是相邻元素之间距离的一半。
space-evenly
flex项都沿着主轴均匀分布在指定的对齐容器中。相邻flex项之间的间距,主轴起始位置到第一个flex项的间距,主轴结束位置到最后一个flex项的间距,都完全一样。
看上去与space-around的排布很相似,但其实还是有一些区别的。space-evenly会在每一行均匀分布间隙,而space-around是均匀分布项目。
借一张图
看上去我们要学的属性很多,但是其实我们只需要记住我们常用的几个属性就行:flex-start、flex-end、space-between、center、space-around、space-evenly。以上这几个就是我们常用的属性值,通过设置主轴方向、设置排列方式,我们可以灵活地组织我们的元素。
align-items 子项目在交叉轴排布
CSS align-items属性将所有直接子节点上的align-self值设置为一个组。 align-self属性设置项目在其包含块中在交叉轴方向上的对齐方式。
取值:
normal
这个关键字的效果取决于我们处在什么布局模式中:在绝对定位的布局中,对于被替代的绝对定位盒子,这个效果和start的效果的一样;对于其他所有绝对定位的盒子,这个效果和stretch的效果一样。 在绝对定位布局的静态位置上,效果和stretch一样。对于那些弹性项目而言,效果和stretch一样。对于那些网格项目而言,效果和stretch一样,除了有部分比例或者一个固定大小的盒子的效果像start。这个属性不适用于会计盒子和表格。
flex-start
元素向侧轴起点对齐。
flex-end
元素向侧轴终点对齐。
center
元素在侧轴居中。如果元素在侧轴上的高度高于其容器,那么在两个方向上溢出距离相同。
因为align-items其实和justify-content我这里就不放一些图片凑字数了。
align-content 定义多根轴线排布
该属性对单行弹性盒子模型无效。(即:带有flex-wrap: nowrap)。
CSS的align-content属性设置了浏览器如何沿着伸缩盒子容器(flexbox container)的纵轴和网格容器(Grid Container)的主轴在内容项之间和周围分配空间。
它的取值和align-items差不多,经常有人会把他们搞混。
align-content一般定义多行的交叉轴排列。
绝大多数情况下我们使用align-items即可实现我们的需求。
Flex子项属性
order 子项排布靠前排名
CSS order 属性规定了弹性容器中的可伸缩项目在布局时的顺序。元素按照 order 属性的值的增序进行布局。拥有相同 order 属性值的元素按照它们在源代码中出现的顺序进行布局。
取值:
<integer>
表示此可伸缩项目所在的次序组。
flex-grow 子项放大比例
CSS flex-grow 属性定义弹性盒子项(flex item)的拉伸因子
取值:
<number>
默认值0,即如果存在剩余空间,也不放大。负值无效。
flex-shrink 子项缩小比例
CSS flex-shrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flex-shrink 的值。
总而言之,你定了这个属性,其他项目会先压榨你的空间,然后再均匀缩小其他项目。
flex-basis
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。
注:分配多余空间之前!!
也就是说你给的flex-basis值大于当前分配空间时,依然会被压缩。
flex
flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。
align-self
align-self属性允许单个项目有与其他项目不一样的对齐方式,可覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性,如果没有父元素,则等同于stretch。
这个属性了不得,它也是我们经常用的子项目属性之一。
.item {
align-self: auto | flex-start | flex-end | center | baseline | stretch;
}
1
2
3
就像上面的图,他可以决定子项目的交叉轴单独排列方式。
Grid 布局
未完待续…明天补上
参考
HTML5语义化标签属性-HTML5属性手册
All About Floats | CSS-Tricks
清除浮动的四种方式及其原理理解
【前端Talkking】CSS系列——CSS深入理解之absolute定位
CSS 弹性盒子布局
Flex 布局教程:语法篇
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
three.js 的简单实例
三大主件: 渲染器、场景、相机
思想核心: 相机获取到场景内显示的内容, 然后再通过渲染器渲染到画布上面
渲染器: 实例化渲染器的同时生成的一个 Canvas 画布, 之后将这个画布添加到了 DOM 当中
场景: 场景只是一个容器, 显示的内容需要进行添加, 添加一个内容称作一个网格, 每个网格基本上包括几何体和材质, 网格也称之为模型
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>three</title>
<style>
body {
margin: 0;
}
canvas {
width: 100%;
height: 100%;
display: block;
}
</style>
</head>
<body onload="init()">
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<script type="text/javascript" src="js/three.min.js"></script>
<script type="text/javascript" src="js/stats.min.js"></script>
<script type="text/javascript" src="js/dat.gui.min.js"></script>
<script>
//声明一些全局变量
var renderer, camera, scene, geometry, material, mesh, stats, rotate = true;
//初始化渲染器
function initRenderer() {
renderer = new THREE.WebGLRenderer(); //实例化渲染器
renderer.setSize(window.innerWidth, window.innerHeight); //设置宽和高
document.body.appendChild(renderer.domElement); //添加到dom
}
//初始化场景
function initScene() {
scene = new THREE.Scene(); //实例化场景
}
//初始化相机
function initCamera() {
camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 200); //实例化相机
camera.position.set(0, 0, 15); //初始化的坐标
}
//创建模型
function initMesh() {
geometry = new THREE.BoxGeometry(2, 2, 2); //创建几何体
material = new THREE.MeshNormalMaterial(); //创建材质
mesh = new THREE.Mesh(geometry, material); //创建网格
scene.add(mesh); //将网格添加到场景
}
//运行动画
function animate() {
requestAnimationFrame(animate); //循环调用函数
//判断是否可以旋转
if(rotate) {
mesh.rotation.x += 0.01; //每帧网格模型的沿x轴旋转0.01弧度
mesh.rotation.y += 0.02; //每帧网格模型的沿y轴旋转0.02弧度
}
stats.update(); //更新性能检测框
renderer.render(scene, camera); //渲染界面
}
//性能检测框
function initStats() {
stats = new Stats();
document.body.appendChild(stats.dom);
}
//创建调试框
function initGui() {
//控制参数初始值
controls = {
positionX: 0,
positionY: 0,
positionZ: 0,
rotate: true
};
gui = new dat.GUI(); //实例化对象
gui.add(controls, "positionX", -10, 10).onChange(updatePosition);
gui.add(controls, "positionY", -5, 5).onChange(updatePosition);
gui.add(controls, "positionZ", -10, 10).onChange(updatePosition);
function updatePosition() {
mesh.position.set(controls.positionX, controls.positionY, controls.positionZ);
}
gui.add(controls, "rotate").name("旋转").onChange(function(e) {
rotate = e;
});
}
//初始化函数,页面加载完成是调用
function init() {
initRenderer();
initScene();
initCamera();
initMesh();
initStats();
initGui();
animate();
}
</script>
</body>
</html>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
1.获得内容 - text()、html() 以及 val()
text() - 返回所选元素的文本内容
html() - 返回所选元素的内容(包括 HTML 标记)
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <p id="p1">圣诞快乐,<b>新年快乐</b></p> //给p元素里边的文本一部分加上b标签 <button id="b1">显示文本</button> <button id="b2">显示html</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#b1").click(function(){ alert( $("#p1").text() ); //获取文本 }); $("#b2").click(function(){ alert( $("#p1").html() ); //获取html内容 结果会包含b标签 }); }); </script>
val() - 返回表单字段的value值
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <input type="text" id="ip" value="nihao"> <button id="but">显示value值</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#but").click(function(){ alert($("#ip").val()); 结果返回表单元素的value值(nihao) }); }); </script>
2.获取属性 - attr()
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <a id="aa" href="www.baidu.com"></a> <button id="but">显示元素属性</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#but").click(function(){ alert($("#aa").attr("href")); }); }); </script>
1设置内容和回调函数 - text()、html() 以及 val()
text() - 设置所选元素的文本内容
html() - 设置所选元素的内容(包括 HTML 标记)
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <p id="p1"></p> <button id="b1">显示文本</button> <button id="b2">显示html</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#b1").click(function(){ $("#p1").text("圣诞快乐,<b>新年快乐</b>") ; //设置文本 }); $("#b2").click(function(){ $("#p1").html("圣诞快乐,<b>新年快乐</b>") ; //设置html内容 结果会包含b标签 }); }); </script>
text()、html()回调函数
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <p id="p1">新年快乐</p> <button id="b1">显示文本</button> <button id="b2">显示html</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#b1").click(function(){ $("#p1").text(function(){ return "happy new year"; //调用函数,返回一个新的文本 } ) ; }); $("#b2").click(function(){ $("#p1").text(function(){ return "happy <b>new</b> year"; //调用函数,返回一个新的文本 } ); }); }); </script>
val() - 设置表单字段的value值和回调函数
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <input type="text" id="ip"> <button id="but">显示value值</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#but").click(function(){ $("#ip").val("happy"); }); }); </script>
val()的回调函数
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <input type="text" id="ip"> <button id="but">显示value值</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#but").click(function(){ $("#ip").val(function(){ return "happay"; }); }); }); </script>
2.设置属性 attr()
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <a id="aa" href="www.baidu.com">11111</a> <button id="but">显示元素属性</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#but").click(function(){ alert($("#aa").attr( { "href":"http://news.baidu.com/" } )); //attr()里边,要加{}号 }); }); </script>
attr()的回调函数
<script type="text/javascript" src="jquery-1.11.2.min.js"></script> <body> <a id="aa" href="www.baidu.com"></a> <button id="but">显示元素属性</button> </body> </html> <script type="text/javascript"> $(document).ready(function(e) { $("#but").click(function(){ alert($("#aa").attr({ "href":function(){return "http://news.baidu.com/" } } )); //attr()里边,要加{}号 });}); </script>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
jQuery 拥有可操作 HTML 元素和属性的强大方法。
jQuery DOM 操作
jQuery 中非常重要的部分,就是操作 DOM 的能力。
jQuery 提供一系列与 DOM 相关的方法,这使访问和操作元素和属性变得很容易。
提示:DOM = Document Object Model(文档对象模型)
DOM 定义访问 HTML 和 XML 文档的标准:
“W3C 文档对象模型独立于平台和语言的界面,允许程序和脚本动态访问和更新文档的内容、结构以及样式。”
获得内容 - text()、html() 以及 val()
三个简单实用的用于 DOM 操作的 jQuery 方法:
text() - 设置或返回所选元素的文本内容
html() - 设置或返回所选元素的内容(包括 HTML 标记)
val() - 设置或返回表单字段的值
下面的例子演示如何通过 jQuery text() 和 html() 方法来获得内容:
<!DOCTYPE html>
<html>
<head>
<script src="/jquery/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$("#btn1").click(function(){
alert("Text: " + $("#test").text());
});
$("#btn2").click(function(){
alert("HTML: " + $("#test").html());
});
});
</script>
</head>
<body>
<p id="test">这是段落中的<b>粗体</b>文本。</p>
<button id="btn1">显示文本</button>
<button id="btn2">显示 HTML</button>
</body>
</html>
val()方法例子:
<!DOCTYPE html>
<html>
<head>
<script src="/jquery/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
alert("Value:"+$("#test").val());
});
});
</script>
</head>
<body>
<p>姓名:<input type="text" id="test" value="米老鼠"></p>
<button>显示值</button>
</body>
</html>
获取属性 - attr()
jQuery attr() 方法用于获取属性值。
<!DOCTYPE html>
<html>
<head>
<script src="/jquery/jquery-1.11.1.min.js"></script>
<script>
$(document).ready(function(){
$("button").click(function(){
alert($("#w3s").attr("url"));
});
});
</script>
</head>
<body>
<p><a url="img/001.jpg" id="w3s">W3School.com.cn</a></p>
<button>显示 href 值</button>
</body>
</html>
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
在做设计的过程中,大部分设计师只专注于主操作流程、主页面、分支流程、小页面和页面的不同状态。却容易忽略产品中容易出现的各种异常状态。
当用户停留任何一个界面,进行任何一个操作都可能发生异常状态。
如果接到每个需求都去制定一次异常状态,这样的后果可能会使得产品的不同模块、不同流程,异常状态都不一致。全局规范性被破坏,同时设计师的效率也降低。
因此全局制定异常状态规范很有必要,后续就不需要再设计,开发直接复用异常状态的规范。省时省力、提率、设计规范、运行更流畅、减少代码重复率、安装包也会更小。
异常状态一共有以下 10 类:
当移动设备网络异常时,导致无法上传和下载数据,从而无法正常的使用产品。
网络异常存在两种场景:
1. App主动行为
当无网络时,用户打开 App,通常有三种方式提醒用户当前网络异常。
tips 提示,通过 tips 提示用户当前网络不可用,tips 使用场景一般为用户打开后,界面停留在首页,且首页以列表形式展示,这样的话, tips 才能合理的融入到界面中,常见使用这种布局方式的有微信、qq等。
使用toast提示用户网络异常,同时提示用户可以去使用非数据影响的操作。例如网易云音乐,当无网络时候,告知用户可以去正常听已下载的音乐。
使用对话框,引导用户进入设置页面,关闭飞行模式或者打开 Wi-Fi,例如美团进入首页后的对话框提示。
2. App被动行为
当前无网络时,用户点击操作,无法正常使用产品,这时候通常有两种处理方式。
一种是当前界面出现 toast 提示。另一种是进入下一级界面,以缺省页的形式提醒用户当前网络异常。
例如手机淘宝,没有网络时,用户点击会进入下一页,出现缺省页提示,告知用户网络异常,同时提供刷新按钮。
美团在无网络时,点击其他 tab bar,出现 toast 提示用户当前网络异常,稍后重试。
3. 小结
当涉及需要消耗大量流量数据时,且非 Wi-Fi 情况下,这时候需要告知用户。常见的例如看视频,听/下载歌曲、视频通话、下载上传文件等。
例如B站,当使用移动数据看视频,则通过提示语和对应按钮上的流量值告知用户。
网易云音乐在非 Wi-Fi 情况下,下载音乐时,通过对话框,告知用户当前使用数据流量,同时提供可继续下载的功能,也提供通过办理新业务解决数据流量的问题。
空数据一共分为两种类型,分别为初始状态和清空状态。
1. 初始状态
用户首次使用,没有任何内容数据时,需要用户进行某种操作才能产生内容的界面,这时候需要提示用户需要进行某种操作。
例如淘宝App,当用户没有把商品加入购物车时,进入购物车界面,会给出提示购物车界面为空。给出用户提示,给出相对应的入口按钮,引导用户操作。
如果初始状态,无任何内容直接给出一个空白界面,用户可能会以为该界面出 bug 了。
Gmail 直接用一个插画提示用户收件箱为空。
一般对于初始状态的设计,常规做法是简单的插画配合简洁的文案,必要的时候给出引导用户操作行为的按钮。
现在流行的设计趋势是插画越轻量越简单越好,以免抢夺了文案信息。
2. 清空状态
当用户清空当前的页面内容,产生了空界面,这时候需要有明确的提示告知用户出现当前页面的原因,且告知用户该如何处理。
清空状态是对初始状态的进一步细化。清空状态的界面和初始状态设计很相似,唯一不同的是文案的提示。
有的产品直接把清空状态的界面按照初始状态来设计,这样也是可以的,缺点就是没有告知用户产生空状态原因是初始化还是清空所致。
在加载过程中,App 向服务器请求数据,如果是网络原因导致,则使用网络异常的设计规范。
如果非网络异常原因,则可能因为服务器异常导致接口请求不到数据,从而加载失败。
第一次请求失败,有些场景可能重试 2 次,例如微信支付宝,这种情况可使用 toast 告知用户加载失败的原因。
任何操作行为的交互界面都伴随着操作失败的概率。
当用户操作失败时,在当前页面给予一个反馈,告知用户操作失败,最好告知用户操作失败的原因,让用户知道接下来如何避免操作失败。
因为服务器异常是小概率事件,但是也会发生。
当服务器异常时,且用户在操作过程中,出现这种情况,一般可设计为对话框提示,明确告知用户,服务器出现问题,让用户稍后重试。
例如下图的华为云备份恢复界面:
用户在搜索过程中,除了出现正常的匹配结果,还存在无匹配结果的情况。针对搜索无结果的情况,要给予用户操作无结果的提示。
几乎搜索无结果的状态都是在内容区出现对应提示。例如 iOS 相册,通过搜索关键词,当没有匹配照片时,则出现对应的提示,如下图右侧图:
下图淘宝买家版后台,当用户搜索关键词无结果时,出现对应的提示语和插画。
无权限的场景,通常适用于 b 端产品,对于不同组织架构的企业员工,会存在不同的权限。
例如部分重要的内容,非同一组织架构的员工无权限查看,这种情况,用户点击进入一般给出对应的提示。
当然最好的方案是在 App 上面过滤掉无法查看的内容,但是存在员工间的转发行为,这时候无权限的员工,点击进入,则显示暂无权限查看的提示页面。
一般 App 功能正在开发中,这种情况不会在 App 界面中展示出来,只有完全开发完毕并上线后才会出现在 App 上。
但是也有一些产品的特殊业务,会将一些未开发的功能展示出来,例如微信公众号,长按微信文章,即出现对应的提示。
也有一些新闻频道还没有开发完毕上线,这时候用户点击进入下级界面,则出现对应的提示语/插图提示,如下图所示:
有的时候,文件或者页面内容被删除,但由于文件或者页面内容的上一级页面有缓存,所以当用户点击进入时,会出现文章/文件被删除的情况。
已被删除的异常状态,常见的设计是用户进入新页面出现对应的插画和标题提示。
例如下图微信公众号文章内容被作者删除,读者点击进入,加载后的界面就出现内容被删除的提示。
以上就是常见的 10 种异常状态的简单介绍和说明。在制定异常状态的设计规范时,可以参考本篇文章。
当然也有公司特殊的业务导致存在很特殊的异常状态,针对这种情况,可以适当的增加、删除或者修改,使其更适用于自己公司的项目。
文章来源:优设
局部变量
局部变量:在函数内部声明的变量,只在函数内部起作用。函数的参数也是局部性的,只在函数内部起作用,对于其他的函数或脚本代码是不可用的。
函数可以访问函数内部定义的变量,如:
<p>函数可以访问函数内部定义的变量:</p>
<button type="button" onclick="myFunction()">点我</button>
<p id="demo"></p>
<script>
function myFunction() {
var a = 4;
document.getElementById("demo").innerHTML = a a;
}
</script>
全局变量
在web页面中全局变量属于 window 对象,全局变量的作用域是全局性的,即在整个JavaScript程序中,全局变量处处都在。
函数也可以访问函数外部定义的变量,如:
<p>函数可以访问定义在函数外的变量:</p>
<button type="button" onclick="myFunction()">点我</button>
<p id="demo"></p>
<script>
var a = 4;
function myFunction() {
document.getElementById("demo").innerHTML = a a;
}
</script>
全局和局部变量即便名称相同,它们也是两个不同的变量。修改其中一个,不会影响另一个的值。
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
问题描述:
做抽屉式菜单时候,在 ie 7 下发现 li 元素之间会留白,如下图:
原以为是样式的问题,后来看到有博文写到“行框的排列会受到中间空白(回车\空格)等的影响,因为空格也属于字符,这些空白也会被应用样式,占据空间,所以会有间隔”。
解决办法:
li 标签之间的空白,可以通过设置 li 标签的 font-size 为 0,可以解决:
li{
padding:0;
margin:0;
height: 30px;
line-height: 30px;
font-size: 0; / 设置 font-size 为 0 即可 /
}
修改后的效果如图:
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
如“黄金分割”之于构图,“视觉层级”之于页面节奏,都是基础且必不可少。本文与你分享如果一步步从原型开始构建APP视觉层级。
工作中,你是否经常听到“视觉层级”这词?就犹如“用户体验”一样让人耳熟能详。抛开装逼因素,这两个词的多次提及,可见其重要程度。
音乐有节奏,好的音乐能通过音阶的高低起伏变化表达音乐情绪。
例如:《Main Title》即使你没看过《冰与火之歌》,光听音乐你是否能感觉到音乐给你营造千军万马恢弘之势。《Playing Love from The Legend of 1900》你是否想到一个宁静夜晚,佳人与你倾诉衷肠,柔情似水。
反之,节奏不好,则无法和听众达成共鸣。
绘画有节奏,张驰有度、大小对比、远近疏密变化,构成了画面的节奏。反之,没有节奏,则画面平淡。
同样的,APP UI也有节奏。页面良好的视觉层级,方便用户在浏览的过程中抓取关键信息,帮助用户快速达到目的。
拿到原型,明确页面目的和需求的1、2、3层级,并理解消化。开启设计师的隐形技能:根据一句话或者一个词,在大脑开始构建画面布局。在构思阶段,建议同时浏览同类型UI设计以及交互布局,在找参考的过程中,结合自身APP的页面目的一起构思,并在纸上绘出可行性方案。
由于,APP是为人服务。那么我们需要知道,人眼浏览习惯模式的科学依据。
曾有一数据显示:如果在3S内无法吸引用户,你将流失这个用户。如今我们所在的时代快节奏、碎片化,用户的日常浏览是“扫描”而非“阅读”。所以,了解人眼浏览习惯,变得十分重要。
人眼浏览习惯有:F型;Z型;其他;
还有,其他浏览模式,海哥HMI人机交互在他一篇文中《用户是怎么阅读的?尼尔森F模型》提到:
在明白人眼视线流程后,我们开始运用视觉手段,吸引用户来看我们想给他看的内容,并按照我们的预想顺序,依次阅读。
对比,让视觉有轻重,用户看起来不累。需要强调的信息放大,没那么重要的东西缩小。如果同一层级的模块,通过颜色或者样式的变化来表达。如:字体大小对比,颜色对比;模块大小对比;图片大小对比等。
字体千千万形状各不相同,然而他们都有着相似之处:字重的大与小。在同一字号大小下,字重大的笔画,以面构成,会比字重小的,更具视觉冲击力。
需要强调的信息,字号变大,字体加粗,这样就能区分主与次,建立更易读的视觉层级。
为了各个模块间的和谐组合和视觉上的凸显与美观,我们需要灵活运用各种样式表达。卡片投影;形状;材质等;
同一类别信息,模块化整合。便于用户浏览操作,视觉上不零散,整体美观。多模块化的组合,注意留白以及页面的节奏轻重。
以上要点,要根据实际情况灵活巧妙运用。在做的过程中,通过Mirror工具实时查看页面效果,不断改进,加强表达。
宗白华说过:“一切艺术都趋向音乐”。确切说一切“广义的”艺术都趋向于音乐状态。优秀的UI视觉层级表达,就如音乐一样有节奏变化,波浪起伏,是一种视觉享受。无论是平面还是UI,视觉层级,需要像“黄金分割原理”一样,是内化进设计师的身体里一个元素。多多实战练习,不需要死记硬背,就会刻在我们的大脑深处。
文章来源:站酷
无论是2B产品,还是2C产品,用户系统都是基础。对于非互联网产品从业者,2C用户系统的场景和功能通过日常各类APP的使用,大家都非常熟悉。因此,笔者通过和2C产品的对比,谈谈2B SaaS产品的用户系统设计。
2C产品面向的用户是个人,用户系统的核心是获客,因此大多2C产品的用户系统设计重点在于方便用户注册、登录,能够建立精准的用户画像,从而达到流量变现的目标。
2B产品面向的用户是企业,用户系统的核心是组织、员工精细化管理,提升人效,从而实现节约成本的目标。
2C产品的注册主要用于个人用户注册场景,重点在于提供多种渠道的注册方式,如账号、手机、第三方社交应用(微信、微博等),其核心目标是既能方便用户注册,又能多渠道多平台账号打通。
2B产品的注册分为两部分:企业管理员代表企业注册和企业员工注册。
2B平台型SaaS产品,和2C最大的区别在于产品需要用户付费。因此,平台方为企业(平台租户)提供了注册入口,一方面需要方便租户能够通过其他渠道快速注册试用产品,一方面需要验证企业相关信息,识别该用户确实为潜在用户。
1)企业注册:
当企业管理员代表企业注册时,需要提供的注册信息:管理员昵称、手机号、邮箱、企业工商信息(名称、组织机构代码、地址、法人信息等)。
其中工商信息的完整度,不同的产品要求不一样,需要根据具体产品而定。如果方便注册拉新,尽量减少工商信息填写要求,如果产品安全性要求较高,可以尽量要求工商信息填写完整。
2)企业工商信息认证:
这部分并非强需求场景,取决于产品的安全性要求。一般安全性要求较高的平台产品,会在企业注册后,进入到企业工商信息认证环节。此环节要么是平台管理员人工审核,要么通过第三方认证验证企业工商信息是否合规。企业完成认证后,即可试用产品。
如非安全性要求较高的产品,可以直接跳过该环节,租户通过注册页信息填写完整后既注册成功。
3)企业员工注册:
登录场景比较容易理解,目前B端产品相较C端产品仍然比较传统,多采用邮箱/手机进行登录。
未来也希望可以实现,B端产品能够和更多C端产品平台打通,可通过通用的第三方账号进行登录,实现业务与社交的连接。
用户画像是2C产品至关重要的内容,只有精准的用户画像,才能更精准的服务好用户。无论是电商,还是资讯平台,基于用户画像的精准营销投放才是产品的核心。
2B的产品很少有讲用户画像相关的内容,事实上对于2B产品而言,用户画像也至关重要。
笔者目前从事CRM产品相关工作,CRM核心要解决的问题就是帮助你的客户获客,那么如何去建立客户的企业标签,去按照企业标签属性,借助大数据分析,帮你的客户找到他的客户群,是笔者近期在研究的课题。
2C的产品从本质上来讲不存在组织结构,个人用户即为产品主体,但会存在群组/社群的概念。
2B产品的应用主体是企业,而组织结构是企业运营管理的必要手段和方式。因此组织结构管理是用户系统的重要组成部分。
1)建立组织结构
组织的单元是部门,因此管理员需要能够按照企业组织结构建立、调整(编辑、合并)、删除部门。
2)部门树结构
部门作为组织结构的单元,只是组织结构的分子,而要形成组织,就要按照企业的业务形态要求形成一定的层级体系。因此部门不仅仅只是简单的信息描述,还需要有层级描述,这就需要我们在建立部门时按照层级结构建立部门,定义清楚所建立的部门是上级部门、下级部门。
3)通讯录展示
管理员通过后台创建完组织结构后,企业员工可通过前台查询按照部门结构展示的通讯录。
角色管理是B端产品的特有功能,企业员工按其所负责的业务模块划分不同的岗位职责。
由于企业数据具有较高的安全性和私密性要求,按照岗位职责的不同,不同岗位的员工对于业务数据的操作/查看权限不同。
因此,我们设计了角色管理,该角色并非严格意义上的岗位职能角色,而为了区分不同的员工不同的系统权限所设计的系统角色,这就是RBAC设计。
1)建立角色
建立角色的主要目标即为建立一个用户权限组,该权限组内的用户具有相同的权限。
2)分配角色权限
基于角色分配系统权限,以实现不同的角色下的用户拥有不同的权限。
员工管理是B端产品的特有功能,员工是企业组织的重要组成部分,员工也是产品真正的终端用户。
B端产品从本质上是要能够帮助企业员工提升工作效率,提高企业人效,以实现企业管理者降低运营成本的目标。
1)新建员工
前面提到的用户注册即为新建员工的过程。包括被动邀请和主动注册两种形态,主要目标是将员工信息注册至系统,并建立员工和企业的关联关系。
2)建立员工汇报关系结构
为了实现精细化管理,企业内部一般按照组织结构设定员工的汇报关系,因此从CEO到基层员工会形成组织关系树,该结构可以和组织结构完全一一对应,即该部门下的所有员工均汇报给部门负责人,但也有部门内部分不同的小组,不同的人汇报给不同的小组负责人。
因此汇报关系和组织结构关系有一定关联,但并不是完全一一对应,所以我们需要设计员工汇报关系功能。
3)员工离职设定
为了保证企业数据的安全,员工离职后,需冻结员工账号,离职员工将不能以该企业员工的身份登录系统,以确保企业数据的安全性。
至此,2B用户系统的功能基本设计完整,其重难点在于组织结构、权限控制,需要重点关注。
文章来源:人人都是产品经理
li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
引起这种空白间隔的原因:
浏览器的默认行为是把inline元素间的空白字符(空格换行tab)渲染成一个空格,也就是我们上面的代码
换行后会产生换行字符,而它会变成一个空格,当然空格就占用一个字符的宽度。
解决方案:
方法一: 既然是因为< li>换行导致的,那就可以将< li>代码全部写在一排,如下
<div class="wrap">
<h3>li标签空白测试</h3>
<ul>
<li class="part1"></li><li class="part2"></li><li class="part3"></li><li class="part4"></li>
</ul>
</div>
1
2
3
4
5
6
7
再刷新页面看就没有空白了,就是这么神奇~
方法二: 我们为了代码美观以及方便修改,很多时候我们不可能将< li>全部写在一排,那怎么办?既然是空格占一个字符的宽度,那我们索性就将
内的字符尺寸直接设为0,将下面样式放入样式表,问题解决。
.wrap ul{font-size:0px;}
1
但随着而来的就是
中的其他文字就不见了,因为其尺寸被设为0px了,我们只好将他们重新设定字符尺寸。
方法三: 本来以为方法二能够完全解决问题,但经测试,将li父级标签字符设置为0在Safari浏览器依然出现间隔空白;既然设置字符大小为0不行,那咱就将间隔消除了,将下面代码替换方法二的代码,目前测试完美解决。同样随来而来的问题是li内的字符间隔也被设置了,我们需要将li内的字符间隔设为默认。
.wrap ul{letter-spacing: -5px;}
1
之后记得设置li内字符间隔
.wrap ul li{letter-spacing: normal;}
1
2
详细看这篇文章 li与li之间有看不见的空白间隔是什么原因引起的?有什么解决办法?
蓝蓝设计( www.lanlanwork.com )是一家专注而深入的界面设计公司,为期望卓越的国内外企业提供卓越的UI界面设计、BS界面设计 、 cs界面设计 、 ipad界面设计 、 包装设计 、 图标定制 、 用户体验 、交互设计、 网站建设 、平面设计服务。
蓝蓝 http://www.lanlanwork.com