金沙澳门官网网址_金沙国际登陆

欢迎加入金沙澳门官网网址体验更多不一样的精彩.,金沙国际登陆提供最丰厚回馈!,因为金沙澳门官网网址这里的游戏是多种多样的,为大家打造一个最专业的化的超级五星酒店。

金沙澳门官网网址 > 金沙澳门官网网址 > 记一次换行引发的血案,以20像素为基准的CSS网页

原标题:记一次换行引发的血案,以20像素为基准的CSS网页

浏览次数:192 时间:2019-10-09

以20像素为基准的CSS网页布局实践分享

2016/03/24 · CSS · 布局

原文出处: 张鑫旭(@张鑫旭)   

记一次换行引发的血案

2018/06/19 · 基础技术 · 换行

原文出处: 怡红公子   

话说最近真是流年不利,感觉各种BUG犹如天灾一样全部冒出来了,这不昨天又解了一个非常无语的问题,大概是关于换行和正则的臭虫,下面给大家吐槽一下。

前端性能优化 – 资源预加载

2015/11/19 · JavaScript · 预加载

原文出处: ROBIN RENDLE   译文出处:bubkoo的博客(@问崖的崖)   

当提到前端性能优化时,我们首先会联想到文件的合并、压缩,文件缓存和开启服务器端的 gzip 压缩等,这使得页面加载更快,用户可以尽快使用我们的 Web 应用来达到他们的目标。 

资源预加载是另一个性能优化技术,我们可以使用该技术来预先告知浏览器某些资源可能在将来会被使用到。

引用 Patrick Hamann 的解释:

预加载是浏览器对将来可能被使用资源的一种暗示,一些资源可以在当前页面使用到,一些可能在将来的某些页面中被使用。作为开发人员,我们比浏览器更加了解我们的应用,所以我们可以对我们的核心资源使用该技术。

这种做法曾经被称为 prebrowsing,但这并不是一项单一的技术,可以细分为几个不同的技术:DNS-prefetchsubresource 和标准的 prefetchpreconnectprerender

 

一、一切从line-height行高说起

想想看,你CSS构建页面的时候,默认的字体大小和行高分别是多少?

下面是我统计的一些数据:

  • 新浪微博:12px/1.5
  • 腾讯微博:12px/1.75
  • 淘宝网/天猫/腾讯微云:12px/1.5
  • 京东:12px/150%

计算下来,基本行高要么是18像素,要么是21像素~

我想,大多数小伙伴应该没关注过这方面的细节,基本行高大致就可以,取1.5方便计算,1.75呢似乎也无伤大雅。

当下的网页早已告别当初就只能浏览信息的那种状态,页面结构更加复杂,大段描述文字的情况只占少数,因此,行高的角色有点从阅读体验层面转换为更方便的计算或者其他什么角色。

这里的“其他什么角色”看似平淡无奇的一句话,其实才是本文的主角。在本文,行高担任了网页垂直格栅基准的角色!

金沙澳门官网网址 1

我们以前可能听过网页格栅布局,老实讲,我对水平格栅一点兴趣也没有,几百篇CSS文章我也从来没有介绍过,因为跟自己的布局理念不符;但是,我今天倒是要提一提垂直格栅!

页面内容往往是自上而下瀑布式的呈现,内容千变万化,元素的高度也是变幻莫测,因此对于垂直方向,所谓格栅,几乎是无稽之谈。确实是这样,但是,局部的格栅有时候会让我们的页面变得更加规范,以及可以让我们的工作更加轻松。

而这一切,就要从行高说起。我们以前写页面,都是设置字体大小以及行高值,确定单行文本所占据的高度内容;而我们这里,则逆向思维,我们希望页面基本文字所占据的高度是20像素,则我们的行高应该是?

现在是大屏时代,假设我们的默认字号大小是14像素,我们计算下:20/14≈1.4285714285714286,四舍五入的结果,于是得到:

CSS

body { line-height: 1.42857; font-size: 14px; }

1
2
3
4
body {
  line-height: 1.42857;
  font-size: 14px;
}

不好意思,给大家下套子了,注意了,在CSS中,行高计算的时候,一定不要向下四舍五入,而要向上。类似上面的代码,虽然14*1.42857近乎就是20像素,但是,不好意思,最后还是以19像素的高度呈现,在Chrome浏览器下就是如此!

因此,实际的设置应该是:

CSS

body { line-height: 1.42858; font-size: 14px; }

1
2
3
4
body {
  line-height: 1.42858;
  font-size: 14px;
}

于是,我们就得到了一个20像素为基准的网页布局环境了,此时,普通一行文字的高度就是20像素,那又有什么好处呢?

单一来看,20像素的高度单元和21像素似乎没什么差别,但是,如果放在一个完整的体系里面,价值就能很好地体现了!

数据“野”了

昨天同事反馈某个页面的数据没有正常显示,最开始我还以为是接口没有返回数据,结果看了下请求发现接口有正常的数据呀。没办法就一路反查回去,最后查到居然代码里接口请求抛错了?!因为定义了 Promise 的 catch 流程,所以也没有把错误抛出来。因为之前这个页面都是正常的,很久都没有改动所以我第一反应是这个数据异常了,查了半天的数据格式问题。可是问题就在于明明看到数据是正常的呀,服务端没有报错,接口数据也是可以正常解析的。最后我突然想起来,我们的接口是 JSONP 的会不会是 JSONP 功能挂了?查了一下果然是这样。

金沙澳门官网网址 2

我们都知道 JSONP 需要定义一个 callback 回调名称,最后数据加载的时候执行这个回调返回数据才算成功。可以看到图里面虽然加了 callback=? 但是并没有对 ? 进行替换,服务端那边应该也是增加了校验这种情况下并没有给我们添加回调方法名。实际上服务端这里的处理都是没问题的,因为即使 ? 被添加到数据里了也会有问题,因为 ? 是逻辑运算符并不能被定义成变量。而没有加回调方法的后果就是虽然接口返回正常,但是最终数据没有人接收就“野”了。

DNS 预解析 DNS-Prefetch

通过 DNS 预解析来告诉浏览器未来我们可能从某个特定的 URL 获取资源,当浏览器真正使用到该域中的某个资源时就可以尽快地完成 DNS 解析。例如,我们将来可能从 example.com 获取图片或音频资源,那么可以在文档顶部的 `` 标签中加入以下内容:

<link rel="dns-prefetch" href="//example.com">

1
<link rel="dns-prefetch" href="//example.com">

当我们从该 URL 请求一个资源时,就不再需要等待 DNS 的解析过程。该技术对使用第三方资源特别有用。

在 Harry Roberts 的文章中提到:

通过简单的一行代码就可以告知那些兼容的浏览器进行 DNS 预解析,这意味着当浏览器真正请求该域中的某个资源时,DNS 的解析就已经完成了。

这似乎是一个非常微小的性能优化,显得也并非那么重要,但事实并非如此 – Chrome 一直都做了类似的优化。当在浏览器的地址栏中输入 URL 的一小段时,Chrome 就自动完成了 DNS 预解析(甚至页面预渲染),从而为每个请求节省了至关重要的时间。

二、20像素为基准的20*20像素的小图标策略

基本上每一个网站都离不开小图标,国际通用的图形语言,对于一个网站而言,无论是体验还是辨识度都是必不可缺的。

目前而言,绝大多数网站还是处于12像素字体时代,设计师设计的图标都是按照16*16像素规格设计的偏多;不太专业的设计师可能会14~20像素之间摇摆。

反正不管怎样,最后(加上sprite工具盛行)我们图形在网页中的尺寸基本上就是16px*16px:

CSS

.icon-hi { display: inline-block; width: 16px; height: 16px; }

1
2
3
4
.icon-hi {
    display: inline-block;
    width: 16px; height: 16px;
}

当然,17px*18px也是很常见的:

CSS

.icon-hi { display: inline-block; width: 17px; height: 18px; }

1
2
3
4
.icon-hi {
    display: inline-block;
    width: 17px; height: 18px;
}

这种一小图标真实尺寸构建CSS代码的方式有3个比较大的问题:

  1. 与后面文字的对齐
  2. 点击区域大小
  3. 重复冗余的CSS代码

1. 与后面文字的对齐
由于vertical-align属性的兼容性,以及vertical-align:middle并不是严格意义的垂直居中,因此,小图标+文字的对齐,基本上都要针对不同浏览器加个hack补丁;在加上,如果你的图标尺寸一会儿16像素,一会儿18像素,显然,没法通过全局一个设置使得整站的小图标和文字都对齐良好!

例如,腾讯微博这里,图标就是16像素尺寸,然后,一些五花八门的处理:
金沙澳门官网网址 3 金沙澳门官网网址 4

很多补丁,很多CSS处理,里面图标使用了absolute绝对定位,这倒是处理兼容挺不错的方法,但是,显然不具有普遍适用性。

2. 点击区域大小
有时候,我们的小图标直接就是点击按钮,此时,如果你的尺寸就是16像素*16像素,会不会点不准的概率就上升了,如果图标是20px*20px呢?

3. 重复冗余的CSS代码
当下类似grunt-spritesmith的小图标合并工具基本成了前端团队的标配,而根据我的观察,基本上,大家都是设计师给的图标直接扔到文件夹里面进行合并,于是,产出的代码基本上就是width/height/background-position的模式,然而,可能里面70%宽高都是16像素,20%是18像素,还有10%是其他小尺寸,也就是,其实很多CSS代码是可以合并的,然而,都浪费了。

如下生成less代码截图(源自真实项目):
金沙澳门官网网址 5

以上这些问题实际上一个对策就可以搞定,就是所有图标统一按照20px*20px的标准处理!
金沙澳门官网网址 6

你想啊,我们网页文字基础高度是20像素,图标也是20像素高,天然对齐,问题1解决;20*20的点击区域对吧,显然比16*16要大,问题2解决;所有图标都是20*20的尺寸范围内,所有width/height都可以合并,大大减少CSS代码,问题3也搞定了!

如下图CSS生成模板示意:
金沙澳门官网网址 7

————-低调的分隔线————-

然而,实际上的处理要比上面说的复杂和深奥的多!

图标和文字天然对齐
按照我们直观的认知,两个元素都是20像素高,都在自己的垂直范围内居中,那这两个元素应该是在一个水平线上的。实际上真的是这样吗?是的,但是,注意这里的但是,是有条件限制的!

在“CSS深入理解vertical-align和line-height的基友关系”一文中,其中就已经提及过:

The baseline of an ‘inline-block’ is the baseline of its last line box in the normal flow, unless it has either no in-flow line boxes or if its ‘overflow’ property has a computed value other than ‘visible’, in which case the baseline is the bottom margin edge.

中文直译就是:

‘inline-block’的基线是正常流中最后一个line box的基线, 除非,这个line box里面既没有line boxes或者本身’overflow’属性的计算值而不是’visible’, 这种情况下基线是margin底边缘。

翻译成白话就是:

如果inline-block水平元素’overflow’不是’visible’,或者里面没有内联元素(图片、文字之类),则整个元素的基线就是自身的下边缘;否则,基线就是里面最后一行图文元素的基线(金沙澳门官网网址 8这是我们需要的)。

有点不太理解?没关系,不是本文的重点。你只要知道,我们要想20像素高的图标和20像素高的文字天然对齐显示,需要满足这两个条件:

  1. overflow属性值除了visible都不行;
  2. 里面需要有不加修饰的文本内容;

所以,下面两种情况都是淘汰的!

CSS

.icon { display: inline-block; width: 20px; height: 20px; background: ... overflow: hidden; }

1
2
3
4
5
6
.icon {
    display: inline-block;
    width: 20px; height: 20px;
    background: ...
    overflow: hidden;    
}

JavaScript

<i class="icon"></i> .icon { display: inline-block; width: 20px; height: 20px; background: ... }

1
2
3
4
5
6
7
<i class="icon"></i>    
 
.icon {
    display: inline-block;
    width: 20px; height: 20px;
    background: ...
}

第一种情况是overflow:hidden拖后腿了;第二种情况是<i>标签里面是空大屁,基线还是元素底边缘而不是里面的文字(如果有)。

因此,要想实现小图标天然对齐,我们不能有overflow:hidden同时HTML标签内部有文本内容,我靠,好多限制,貌似很烦啊,然而,经过本人的实践,是可以有CSS代码段满足各种场景的对齐效果的,如下:

CSS

.icon { display: inline-block; width:20px; height:20px; background: ...; white-space:nowrap; letter-spacing: -1em; text-indent: -99em; color: transparent; /* IE7 */ *text-indent: 0; *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '3000'); } .icon:before { /* 伪元素插入空格文本 */ content: '3000'; }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
.icon {
    display: inline-block;
    width:20px; height:20px;
    background: ...;
    white-space:nowrap;
    letter-spacing: -1em;
    text-indent: -99em;
    color: transparent;
    /* IE7 */
    *text-indent: 0;
    *zoom: expression( this.runtimeStyle['zoom'] = '1', this.innerHTML = '3000');
}
.icon:before {
    /* 伪元素插入空格文本 */
    content: '3000';
}

您可以狠狠地点击这里:小图标文字对齐的终极解决方案demo

结果,无论是空标签HTML,还是内置可访问性提示文字的HTML,都是对齐效果棒棒哒!

XHTML

<i class="icon"></i> <a href="javascript:" class="icon">删除</a>

1
2
3
<i class="icon"></i>
 
<a href="javascript:" class="icon">删除</a>

金沙澳门官网网址 9

而且,就算文字的字号大小变化,例如14px16px图标和文字也是对齐良好的,因为,对齐的本质是图标元素里面的文字和后面的文字对齐,文字和文字对齐,自然是天然对齐的,千古难题就这么有了解决方案,以前的CSS hack啊,什么vertical-align控制,还有margin负值偏移都是浮云了!金沙澳门官网网址 10

图标20*20尺寸扩展grunt工具
设计师设计的图标都是16px~20px不等,CSS代码都是Grunt工具生成的,我们很难简单控制让所有图标都是20*20的区域大小。除非,我们对所有的小图标在导出的时候,手动扩展画布到20px*20px。

亲,什么年代了,又不是搞艺术品,手工劳作年代过去了,直接上工具。

我基于GM搞了个20像素以下小图标自动扩展为20像素大小图片的Grunt工具:

精力有限,这个小项目还没细整就扔上去了,可以看到,很多模板生成的文字我还没来得及改。

window用户记得要安装ImageMagick.exe,安装时候记得勾上那个全局变量什么东西的。

如果有什么问题,欢迎……不要来打扰我,忙,自己想办法,么么哒~~

图标的重心像素级处理
有些图标,虽然设计师给的尺寸是标准的,没有多余像素,但是,可能图标本身的形状并不是对称的,尤其上下,这就会导致图标的重心会有些偏上或者偏下,导致和后面的文字呈现的时候,虽然真实尺寸是对齐的,但是视觉感觉却是不在一条线上。如果要求很高,可以让设计师或UI工程师自己微调下,一般1像素就够了,当然,是调整图片,例如,重心低的,下面多1像素高度的透明区域。

我的回调呢?

我们在内部是使用了 zepto 这个基础库的。由于添加回调方法名并做替换肯定是 zepto 内部的行为,所以当我查到这的时候我都懵了。难道一年难遇一次国际知名库的 BUG 就这样被我水逆的碰到了?怀着一脸惊讶的表情我打开了 zepto 的文件继续查了下去。最终我发现还真是 zepto 里面 callback=? 没有替换成功。定义好 callback 方法之后 zepto 里面是这么去替换接口地址的参数的:

JavaScript

// window[callbackName] = function(){ responseData = arguments } script.src = options.url.replace(/?(.+)=?/, '?$1=' + callbackName) document.head.appendChild(script)

1
2
3
4
5
6
7
// https://github.com/madrobby/zepto/blob/master/src/ajax.js#L121-L126
window[callbackName] = function(){
  responseData = arguments
}
 
script.src = options.url.replace(/?(.+)=?/, '?$1=' + callbackName)
document.head.appendChild(script)

通过正则匹配到两个 ? 后并替换最后一个 ? 为回调方法名。最开始我一直没绕过来,我在想这特么是什么骚操作?能匹配到 callback=? 么??callback=? 是可以匹配到,万一这个东西在后面 &callback=? 不就挂了么?最后才反应过来它这么做是直接匹配了整个地址后的 query,忽略了参数名称直接匹配 ?。对于这种操作,我只能说:

金沙澳门官网网址 11

那么在当前的情况下这种操作会有什么问题呢,我怀着不服输的精神又查了下去。结果我发现在这种情况下这个正则居然跪了!最后我在这打印出来看,发现传进去的 URL 里面多了一个回车符,导致这段正则失效了。因为我们知道正则里面的 . 元字符是匹配除了回车符以外的所有字符。(这无语的BUG…果然水逆就算是啥也不干问题也会自动找上门啊…

金沙澳门官网网址 12

当我查到这的时候我就思考了两个问题:

  1. 这个回车从哪里来的?参数里怎么会有回车?因为这个参数是直接从当前页的 URL 获取的,所以是我们在拼接的时候操作的有问题,还是服务端下发的当前地址就有问题?
  2. 为什么到了最后 URL 地址这还有回车,正常情况下到这步的时候应该库都会对其进行转码编译了,例如回车符会被编成 %0A 这样其实 zepto 内部再处理就没有问题了呀?所以是哪里给漏编码了呢?

预连接 Preconnect

与 DNS 预解析类似,preconnect 不仅完成 DNS 预解析,同时还将进行 TCP 握手和建立传输层协议。可以这样使用:

<link rel="preconnect" href=";

1
<link rel="preconnect" href="http://example.com">

在 Ilya Grigorik 的文章中有更详细的介绍:

现代浏览器都试着预测网站将来需要哪些连接,然后预先建立 socket 连接,从而消除昂贵的 DNS 查找、TCP 握手和 TLS 往返开销。然而,浏览器还不够聪明,并不能准确预测每个网站的所有预链接目标。好在,在 Firefox 39 和 Chrome 46 中我们可以使用 preconnect 告诉浏览器我们需要进行哪些预连接。

本文由金沙澳门官网网址发布于金沙澳门官网网址,转载请注明出处:记一次换行引发的血案,以20像素为基准的CSS网页

关键词:

上一篇:没有了

下一篇:没有了