前端开发中的一些黑魔法Pt2

上一篇介绍了前端开发中的九个黑魔法,比如链接的嵌套、破裂图片美化、表格列高亮显示、内联文本背景颜色设置、响应式EDM等,那么这篇文章继续根据 @Vitaly Friedman 在今年3月份分享了一个主题《 Dirty Tricks From The Dark Corners Of Front-End 》往下梳理,希望对您平时开发有所帮助。

神奇的Flexbox

CSS中Flexbox的出现,对于前端开发的同学来说绝对是一种福音,虽然它的版本众多,浏览器对其支持力度还不完全,甚至规范还在不断的修改,但其部分功能已经运用到实际开发当中。而且这些功能解决我们很多以前认为很痛苦的事情。你可能会说,是不是真的,如果你觉得言过其实,那希望你花点时间继续往下阅读。

Input Add-ons

初次看到Input Add-ons还是在 Bootstrap中 。别的先不多说,上张图先:

上图的演示,大家应该看到了效果,或许有些同学已经开始在思考,中间的 input 输入框是如何根据容器的空间来自动调整的。说实在的,早其实现这种效果是件痛苦的事情,不管是使用 float 还是绝对定位 absolute ,都无法让 input 根据其容器空间自动调整。Twitter的工程师想出的一个解决方案是采用 display:table-cell 来完成。虽然效果实现了,但灵活性还是没有Flexbox的强大。接下来看Flexbox是如何实现的:

HTML:

<!-- appending -->
<div class="InputAddOn">
  <input class="InputAddOn-field">
  <button class="InputAddOn-item">…</button>
</div>

<!-- prepending -->
<div class="InputAddOn">
  <span class="InputAddOn-item">…</span>
  <input class="InputAddOn-field">
</div>

<!-- both -->
<div class="InputAddOn">
  <span class="InputAddOn-item">…</span>
  <input class="InputAddOn-field">
  <button class="InputAddOn-item">…</button>
</div>

CSS:

.InputAddOn {
  display: flex;
}

.InputAddOn-field {
  flex: 1;
  /* field styles */
}

.InputAddOn-item {
  /* item styles */
}

水平垂直居中

水平垂直居中常常是前端面试当中会碰到的一个题目,对于一位前端人员来说,这也是必须掌握的技能,而且到目前为止,实现这样的效果方案有多种多样。早在2011年,整理过近八种方案可以实现水平垂直居中的效果。当然,在不同的时代,不同的环境,不同的方案各有千秋。对于目前来说,Flexbox绝对是一个最佳方案:

.box {   
    display: flex;  
    align-items: center;  
    justify-content: center; 
}

扩展阅读

媒体对象(Media Object)

在行业内,一般将上图的组件效果都称之为媒体对象(Media Object)。其实就是 @Nicole 写的一个CSS代码片段,这个代码片段是常用来阐述OOCSS的最佳示例。如果你不知道Media Object是什么东东,建议你 阅读一下这篇文章 ,了解一二。

将上面的效果拆分一下,就是这样:

最早实现这样的效果是借用BFC的概念,虽然能实现我们需要的效果,但存在一定的缺陷。比如:

  • media-objetmedia-body 顶部对齐(可以轻松实现)
  • media-objectmedia-body 中间对齐(蛋疼了)
  • media-objectmedia-body 底部对齐(蛋疼了)

如下图所示:

不过后来有同学提出Flag Object的概念,采用 display:table-cell 能顺利解决上述的蛋疼问题:

而这里要说的是,还是Flexbox来实现Media Object的效果:

HTML:

<div class="media">
    <img class="media-figure" src="" alt="" />
    <div class="media-body">...</div>
</div>

CSS:

.media {
    display: flex;
    align-items: flex-start;
}
.media-figure {
    margin-right: 1em;
}
.media-body {
    flex: 1;
}

Sticky Footer

上图的效果就是常说的 Sticky Footer 效果。就是当内容只有一点点时,Web页面显示在浏览器底部,当内容高度超过浏览器高度时,Web页面的Footer部分在页面的底部,总而言之Web页面的Footer部分永远在页面的底部,换句说,Footer部分永远沉底。如下图所示:

@Matthew James Taylor 提供了 一种解决方案 。当然除Matther James Taylor介绍的方案之外,还有其它几种类似的方案。虽然这些方案能达到所需效果,但有一个最大的缺陷,就是要明确指定Footer部分的高度,这样一来受到的局限性就非常的大。而Flexbox可以改变这一局限性。

HTML

<body>
    <header>...</header>
    <main class="content">...</main>
    <footer>...</footer>
</body>

CSS

body {
    display: flex;
    min-height: 100vh;
    flex-direction: column;
}
.content {
    flex: 1;
}

这里运用到了CSS新提供的单位—— 视窗单位 ( vwvhvminvmax )

响应式等高区块

早期实现上图的效果,一般采用的方法是 float 或者 display:inline-block ,但这两种方法要做到上图的效果,都需要显式的设置每个区块的高度。如果只是根据内容来的话,就常会有这样的现象:

这也是常常有同学问我,为什么我的block掉到别的地方了。具体原因,是由于Block的高度不一致造成的。如果要解决上图的问题,我们需要给每个Block设置高度。而实际情况,我们又不想这么做,这个时候Flexbox的魅力就更显现出来了。

HTML

<ul class="list">
    <li class="list-item">...</li>
    <!-- other items -->
</ul>

CSS

.list {
    display: flex;
    flex-wrap: wrap;
}
.list-item {
    display: flex;
}

详细的解说,可以阅读 @Osvaldas Valutis 写的《 Flexbox Based Responsive Equal Height Blocks With JavaScript Fallback 》一文。

这里通过五个小点,也是前端人员常常碰到的痛楚,来阐述Flexbox的神奇功能。其实Flexbox还有其它神奇的功能,如果你还在担心浏览器对它的兼容性而放弃使用,那真是你的一大损失。这也注定你将为这些痛苦继续痛苦。如果你以前没有接触过,但又想去了解Flexbox相关的知识,你可以阅读以下文章:

currentColor

很多时候我们希望图标的颜色能够继承当前主体颜色。比如:

比如上图,按钮中的SVG图片希望能根据不同的按钮状态颜色同步,言外之意就是继承按钮的颜色。很多同学一般都会这样去写:

.button{
    color: #000;
    border: 2px solid #000;
}
.button:hover,
.button:focus{
    color: #333;
    border-color: #333;
}
.button:active{
    color: #666;
    border-color: #666;
}
.button svg{
    fill: #000;
}
.button:hover svg,
.button:focus svg{
    fill: #333;
}
.button:active svg{
    fill: #666;
}

其实,在CSS中有一个变量关键词 currentColor ,它能让我们的事情变得简单:

svg{
    fill: currentColor;
}
.button{
    color: #000;
    border: 2px solid currentColor;
}
.button:hover,
.button:focus{
    color: #333;
}
.button:active{
    color: #666;
}

这个 currentColor 关键字就像是一个CSS变量,不同的是它有一个主要的限制:你只可以在能够接受 <color> 值的地方使用它;如果该属性不能接受 <color> 值,它也就不能接受 currentColor 作为值。

为了演示 currentColor 的可用性,Simon创建了一组UI元素,包括一些滑动条等。这些元素应用了相同的配色方案。对于滑动条的颜色和输入类型,他使用了 currentColor 变量来迫使滑动条上滑块的背景颜色继承了 color 属性,而下方的滑动框则不继承该颜色。

一个使用 currentColor 来让滑动条的滑块应用 color 属性的值的例子。( 地址

同样的,其它的UI组件也可以通过继承级联中某个你想要的位置的 color 值来创建。由此,一个UI组件就创建好了。然后,利用级联和 currentColor ,每次你都可以通过改变主要的 color 值,然后得到一组新颜色的组件,这样几乎就把这整个过程给切实地自动化了。

如下面这个GIF图像所示。Simon使用了浏览器中的开发工具以及颜色拾取器来改变 color 属性的值,然后得到了一个实时的组件颜色改变的预览。

currentColor 已经得到众多浏览器的支持,大家可以放心在自己的项目中使用。上述的内容也再次向大家展示了,通过关键词 currentColor 能很好的继承 color 的值,能让更简单的控制需要的颜色。

有关于 currentColor 详细的介绍,可以阅读这篇文章《 http://www.w3cplus.com/css3/extending-the-color-cascade-with-the-css-currentcolor-variable.html 》。

扩展阅读

给JPG添加透明通道

如果你有一张很大的图片,需要在上面添加透明阴影效果。使用PNG文件又太大,但使用JPG,质量又不够好。

现在有一种新技术,就是将一个常规的JPG和一个带有透明通道的8位PNG一起放到一个SVG的容器内。

<svg preserveAspectRatio="xMinYMin" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 560 1388">
  <defs>
    <mask id="canTopMask">
      <image width="560" height="1388" xlink:href="img/can-top-alpha.png"></image>
    </mask>
  </defs>
  <image mask="url(#canTopMask)" id="canTop" width="560" height="1388" xlink:href="can-top.jpg"></image>
</svg>

在HTML或者CSS可以调用这个SVG文件

<img src="hero-image.svg" />, background: url("hero-image.svg")

这种技巧简单的可以理解成:在JPG的文件上添加了一个PNG的蒙层,然后输出一个SVG文件,并且在HTML或者CSS中按正常调用图片的方式调用SVG文件。

如果你对这方面的技术感兴趣,可以阅读下面几篇文章:

有效快速缩放UI组件

大家在定制自己的UI组件的时候,是否已将自己的组件大小尺寸限制死了,而每次为了调整而感到痛苦。那么有没有什么有效的方法,可以快速,准确无误的按比例调整自己UI组件的尺寸,比如 widthheightborder-radius 呢?

是不是感觉上面的效果很神奇,其实并不是什么先进技巧,只不过大家平时并未留意。

使用 em 映射字体大小。因此使用 em 可以按一定的比例设置组件大小。我们可以使用 font-size 大小来控制这个比例。如果我们继承 font-size 大小,我们只需要在根元素或某个父元素上设置这个值。

rem 的工作原理是一样的,只不过他只是相对于根元素 html 。可以使用 rem 来控制组件的 marginpadding ,调整他们的间距。

言外之意,在制作UI组件库的时候,最好使用 em 或者 rem 来控制尺寸。这样你只需要调整 font-size 的值,就可以让自己的组件库达到缩放自如。例如 digit 这个组件库。

扩展阅读

逐帧动画

动画特效在Web的使用中越来越频繁,而且要求也越来越高,希望看到的效果是平滑细腻的。比如鼠标悬浮效果,希望描述一个运动的幻觉。而要做到这样的效果,我们就需要在一个元素上使用一系列的图片。比如Twitter上的点赞动画(这个是早期的效果,现在换成这样的效果)

这就类似于西洋镜一样,每转动一下,看到一个不一样的景色:

而将其运用到Web动画中来是一样的道理,需要一张雪碧图,这图上放置了动画所效果对应的图片,当然,图片越多,效果越平滑细腻。常把这样的图称之为雪碧图。比如前面演示的Twitter点赞效果,它就有一张这样的雪碧图:

为了驱动这些图片帧,我们需要把他们放在同一水平线,这样我们只需要移动背景图的位置就行了。

有图还不够,这里最主要的是使用 animation-timing-function 中的 steps() 功能。对于大多数timing function而言(比如 cubic-bezier ),过度的开始和结束都会很平滑。但是 steps 方法不同,它把过度切分成很多步。每一步的区别很明显。

.fave { 
    width: 70px;  
    height: 70px; 
    background-size: 50em 2em; 
    background: url(images/fave.svg) no-repeat;  background-position: 0 0; 
} 

.fave:hover { 
    background-position: -50em 0; 
    transition: background 1s steps(55);  
}

驱动背景图片精灵生成动画只是 steps 的一种使用方法。任何使用一些列特定步骤的动画都可以用 steps 生成,比如做一个时钟。

使用CSS的Sprites图配合 animation-timing-function 或者 transition-timing-functionsteps() 做的动画起来越多,效果越来越复杂。我们也常将这样的效果运用到自己的实际业务当中。比如 手淘年货节舞龙揭幕动画实战

再给大家展示一个这样的动画案例:

扩展阅读

如果你想深入的学习Web动画相关的知识,建议你移步这里,在这里你可以看到很多有关于Web动画的优秀教程和经典案例。

颜色的反转

如果你想在一个亮色的背景颜色和深色的背景图片有不同的样式风格,或者文本颜色能根据背景颜色自动做调整。在CSS中要怎么做到呢?比如说,深色背景颜色之下,文本颜色是亮色;反之在亮色背景颜色之下,文本颜色是深色。让用户的视觉感最好。

如果你说像这样做就可以了。那么也可以说,你这样做不是明智的。

@kennethcachia 提供了一个 BackgroundCheck 的JavaScript库,可以让你轻松实现所要的效果:

Automatically switch to a darker or a lighter version of an element depending on the brightness of images behind it.

当然除了使用JavaScript库之外,还可以使用CSS的混合模式 mix-blend-mode 。将其值设置为 difference (差值模式)或者 darken (变暗模式),将会得到意外的效果。

当然,还可以使用 mix-blend-mode 的其它的属性值。

扩展阅读

有关于 mix-blend-mode 更多的详细介绍,可以点击这里阅读。

高级选择器

在Web开发当中,时间碰到这样的效果。比如在一个list当中,除最后一个都需要添加底部的边框,还有在一些导航当中,除最后一个菜单项之外的每个菜单项添加右边框。早前实现这样的效果都需要在最后的一个 li 标签添加一个类名,比如说 last 。但对于现在来说,不再需要这样去做了,可以使用CSS3选择器中的 :not() ,并且配合伪类选择器 :last-child 来实现。

还有 :empty 选择器。比如你创建了一个信息弹出框,而这个弹出框并不是一直都显示出来的,只有内容的的时候才显示,没有内容的时候是隐藏的。那么如何能更好的实现这样的效果呢?

.alert {
    background-color: beige;
    border: 2px solid rgb(150, 150, 150);
    border-radius: 5px;
    padding: 5px 10px;
    display: inline-block;    
}

.alert:empty {
    display: none;
}

除此之外,CSS3还提供了很多先进而又高级的选择器。我们再来看一个选择器 :lang 。比如在Web页面中有一个 blockquote 元素,希望根据不同的语言,设置不同的引号格式:

blockquote:before {
    content: open-quote;
    padding-right: 1rem;
}

blockquote:after {  
    content: close-quote;
    padding-left: 1rem;
}

blockquote:lang(fr) {  
    quotes: '«' '»';
}

blockquote:lang(zh-Hans) {  
    quotes: '「' '」';
}

@ireaderinokun 在《 5 Lesser Used CSS Selectors 》一文中介绍了上述选择器的使用,除上之外,这篇文章介绍了五个先进的选择器 :empty:not()::first-letter::first-line:lang():target

扩展阅读

其它

在PPT中还介绍了几个其它的知识点,比如在移动端按钮点击触发事件反应时间、CSS的 touch-action 属性、创建失真的视觉效果、地图等等。这几个部分在此不再花过多的时间去阐述。如果你对这方面感兴趣,建议您直接去阅读PPT。

总结

上一篇介绍了前端开发中的九个黑魔法,比如链接的嵌套、破裂图片美化、表格列高亮显示、内联文本背景颜色设置、响应式EDM等。在这篇文章中着重介绍了CSS的Flexbox、 currentColor 、弹性修改UI组件库等。两篇文章加在一起,差不多有近15个知识点。希望这些技巧对你平时的工作有所帮助。

有关于前端开发中的一些黑魔法就介绍到此。其实PPT还有另一部分内容,就是Web的可访问性以及无障碍方面的知识。而这一部分对于前端开发人员也是很有意义的,如果想让你的产品可访问性更强,这部分知识还是有需要去了解和掌握的。那么后期将再花一定的时间将这部分内容整理出来与大家分享。如果你想急切的了解有关于Web无障碍方面的知识,可以先阅读早前分享过的一篇文章《 WAI-ARIA 无障碍Web规范 》。

如果你有其它关于前端开发的黑魔法技巧,欢迎在下面的评论中与我们一起分享。

大漠

常用昵称“大漠”,W3CPlus创始人,目前就职于手淘。对HTML5、CSS3和Sass等前端脚本语言有非常深入的认识和丰富的实践经验,尤其专注对CSS3的研究,是国内最早研究和使用CSS3技术的一批人。CSS3、Sass和Drupal中国布道者。2014年出版《 图解CSS3:核心技术与案例实战 》。

我来评几句
登录后评论

已发表评论数()

相关站点

+订阅
热门文章