不可思议的纯 CSS 导航栏下划线跟随效果

2018/04/02 · CSS ·
下划线

本文作者: 伯乐在线 –
chokcoco
。未经作者许可,禁止转载!
欢迎加入伯乐在线 专栏作者。

先上张图,如何使用纯 CSS 制作如下效果?

澳门微尼斯人手机版 1

在继续阅读下文之前,你可以先缓一缓。尝试思考一下上面的效果或者动手尝试一下,不借助
JS ,能否巧妙的实现上述效果。

OK,继续。这个效果是我在业务开发的过程中遇到的一个类似的小问题。其实即便让我借助
Javascript
,我的第一反应也是,感觉很麻烦啊。所以我一直在想,有没有可能只使用 CSS
完成这个效果呢?

 

CSS Grid中的陷阱和绊脚石

2018/04/02 · CSS ·
Grid

原文出处: Rachel
Andrew   译文出处:大漠   

2017年3月,CSS
Grid在几个星期内就被发送到Chrome、Firefox和Safari的生产版本中。很高兴,大家可以使用它来解决实际问题。

CSS
Grid是一种不同的布局方式
,在大家开始使用规范的时候,有很多常见的问题。这篇文章的目的是回答其中的一些问题,并且将会是Smashing
Magazine中有关于CSS Grid一系列文章中的一篇。

Web性能优化系列:借助响应式图片来改进网站图片显示

2015/06/22 · HTML5 ·
响应式

本文由 伯乐在线 –
yvonne
翻译,黄利民
校稿。未经许可,禁止转载!
英文出处:deanhume.com。欢迎加入翻译组。

开始使用
<picture> 元素

响应式网页设计太棒了,它改变了我们向手机端用户呈现内容的方式,无论用户使用何种尺寸的手机,我们都能够为其提供定制化的体验。响应式网页设计使用起来很灵活,也容易上手。然而,如果没有正确使用,它会对网页性能带来负面影响。

用于在 PC
端展示的图片对于手机来说太大了。我们知道,在手机设备上大尺寸高分辨率的图片会大大降低页面加载性能。响应式设计和非固定图片(fluid
image)在保证正确显示的同时,也保证大图片在页面显示的性能大大提高。Tim
Kaldec
对响应式图片的研究表明,使用响应式图片策略最多可以减少图片72%的负担。72%,这是一个相当大的数量。

过去这些年里,出现了一些响应式图片解决方案,开发人员也习惯了使用这些方案来解决响应式图片问题。但都现在看来,这些方法都有一点hacky的味道。这就是
<picture> 元素被引入的原因。

澳门微尼斯人手机版 2

<picture>
元素作为一种向不同设备输出高性能图片数据的客户端解决方案,目前已经纳入
WHATWG HTML
规范
。为了向大家展示 <picture>
元素的强大,我们一起来看一个简单的例子。

XHTML

<picture> <source media=”(min-width: 1024px)”
srcset=”dest/1024/tiger.jpg”> <source media=”(min-width: 640px)”
srcset=”dest/640/tiger.jpg”> <source
srcset=”dest/320/tiger.jpg”> <img src=”dest/640/tiger.jpg”
alt=”This picture will load on browsers that don’t yet support the
element.”> <p>This is some accessible text.</p>
</picture>

1
2
3
4
5
6
7
<picture>
   <source media="(min-width: 1024px)" srcset="dest/1024/tiger.jpg">
   <source media="(min-width: 640px)" srcset="dest/640/tiger.jpg">
   <source srcset="dest/320/tiger.jpg">
   <img src="dest/640/tiger.jpg" alt="This picture will load on browsers that don’t yet support the element.">
   <p>This is some accessible text.</p>
</picture>

浏览器在解析上面的 HTML
语句时会根据设备的屏幕分辨率来选取大小最合适的图片。点击这个链接观看实际效果。

澳门微尼斯人手机版 3

从上面的 HTML 代码可以看到, <picture> 元素由一组 <source>
标签组成。<source>
标签里面声明了设备的视口(viewport)宽度以及与之相应尺寸的图片。这样不同设备上的浏览器就可以根据这些信息选取最适合的图片源。这是一个出色的解决方案,因为所有的操作都是在客户端完成,开发者对展现给用户的图片具有控制权。

值得一提的是,通过设置 <img> 标签的 srcset 属性和 size
属性也可以达到相同的效果。这两个属性由 <img> 标签和 <source>
标签扩展而来,提供一系列图片资源和相应的图片大小。浏览器根据这些信息来选取最合适的图片。假如你不考虑图片的艺术美感,可以使用这种方法。

XHTML

<img src=”dest/320/tiger.jpg” srcset=”dest/1024/tiger.jpg 1024w,
dest/640/tiger.jpg 640w, dest/320/tiger.jpg 320w” alt=”A TIGER!!!”>

1
2
3
<img src="dest/320/tiger.jpg"
  srcset="dest/1024/tiger.jpg 1024w, dest/640/tiger.jpg 640w, dest/320/tiger.jpg 320w"
  alt="A TIGER!!!">

如果你还想了解更多关于 <picture>
元素的历史和起源,推荐你读这篇文章。

定义需求

我们定义一下简单的规则,要求如下:

  • 假设 HTML 结构如下:
&lt;ul&gt; &lt;li&gt;不可思议的CSS&lt;/li&gt;
&lt;li&gt;导航栏&lt;/li&gt; &lt;li&gt;光标小下划线跟随&lt;/li&gt;
&lt;li&gt;PURE CSS&lt;/li&gt; &lt;li&gt;Nav Underline&lt;/li&gt;
&lt;/ul&gt;

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content" style="font-size: 13px !important; line-height: 15px !important;">
<div class="crayon-num" data-line="crayon-5b8f6b0473490387173502-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6b0473490387173502-2">
2
</div>
<div class="crayon-num" data-line="crayon-5b8f6b0473490387173502-3">
3
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6b0473490387173502-4">
4
</div>
<div class="crayon-num" data-line="crayon-5b8f6b0473490387173502-5">
5
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5b8f6b0473490387173502-6">
6
</div>
<div class="crayon-num" data-line="crayon-5b8f6b0473490387173502-7">
7
</div>
</div></td>
<td><div class="crayon-pre" style="font-size: 13px !important; line-height: 15px !important; -moz-tab-size:4; -o-tab-size:4; -webkit-tab-size:4; tab-size:4;">
<div id="crayon-5b8f6b0473490387173502-1" class="crayon-line">
&lt;ul&gt;
</div>
<div id="crayon-5b8f6b0473490387173502-2" class="crayon-line crayon-striped-line">
  &lt;li&gt;不可思议的CSS&lt;/li&gt;
</div>
<div id="crayon-5b8f6b0473490387173502-3" class="crayon-line">
  &lt;li&gt;导航栏&lt;/li&gt;
</div>
<div id="crayon-5b8f6b0473490387173502-4" class="crayon-line crayon-striped-line">
  &lt;li&gt;光标小下划线跟随&lt;/li&gt;
</div>
<div id="crayon-5b8f6b0473490387173502-5" class="crayon-line">
  &lt;li&gt;PURE CSS&lt;/li&gt;
</div>
<div id="crayon-5b8f6b0473490387173502-6" class="crayon-line crayon-striped-line">
  &lt;li&gt;Nav Underline&lt;/li&gt;
</div>
<div id="crayon-5b8f6b0473490387173502-7" class="crayon-line">
&lt;/ul&gt;
</div>
</div></td>
</tr>
</tbody>
</table>

  • 导航栏目的 li 的宽度是不固定的
  • 当从导航的左侧 li 移向右侧
    li,下划线从左往右移动。同理,当从导航的右侧 li 移向左侧
    li,下划线从右往左移动。

 

为什么使用CSS Grid而不是CSS Flexbox?

在CSS网格布局在浏览器中可用之前,很多人都认为Flexbox是我们所有设计相关问题的答案。然而,Flexbox并没有提供比浮动更好的网格系统,尽管它确实比浮动创建一个网格系统更简单。一个真正的网格是二维的。这两个维度就是行和列,并且使用网格布局,你可以同时控制它们。使用Flexbox,你可以选择是否将这些项列成一行或列,一个或另一个,而不是两个。

这里有一个简单的示例,突出其区别。第一个布局使用Flexbox,为了能尽可能多的使用盒子,以适合可用的宽度。这里我们控制了整个行中的布局。允许Flex项目进行包裹,因此会创建新的行,但是每一行都是一个新的Flex容器。空间分布在行中发生,所以取决于最后一行多少项,它们有时不会与上面的Flex项对齐。DEMO1

第二个示例使用CSS
Grid实现相同的布局,但是,你可以看到,最后一行中的项目始终保持在它们的列中。这是因为在网格中,我们将项目排列成行和列
—— 二维布局。

 DEMO2

你还可以在第二个示例中看到,在CSS
Grid布局中,我们不需要向网格添加任何内容来进行布局。所有东西都被放在容器上。在Flexbox布局中,你必须针对Flex项目来设置flex-growflex-shrinkflex-basis属性。这是理解网格布局关键所在,也可能是大家有很多困惑的地方。Grid主要是关于包含元素的,而我们之前的所有布局方法都依赖于我们在布局中设置的宽度,使某些东西看起来像一个网格。

如果你使用一个简化版本的浮动12列“网格”,我们必须计算每一列的百分比大小,加上每个列之间间距的百分比大小。要创建跨多个列的项,需要将所有项的宽度加上用于分隔它们的边界宽度。DEMO3

使用Flexbox创建的网格也是如此。当我们在父节点上通过display:flex创建Flex布局时,Flex所有的大小都需要在单个Flex项目上进行。为了制作一个Flexbox的“网格”,我们必须阻止Flexbox做灵活的操作,而是应该设置百分比宽度,就像我们前面的浮动网格示例一样。使用Flexbox要比浮动更有一些优势,比如控制对齐和列等高之类的要简易得多。然而,在Flexbox和浮动的方法中仍然没有网格,只是通过设置项目的大小,并将它们排列起来,让其看起来像网格的东西。DEMO4

在网格中,所有的大小都发生在容器上。一旦我们创建了我们的网格轨道,我们就可以告诉单个项目(Grid项目)有多少个轨道可以跨越,但我们却有一个实际的网格。我们可以完全抛弃行的容器,因为网格已经有行了。这也意味着,我们也可以使用相同的方式进行跨列。这对于以前而言是件很难做的事情。

 DEMO5

处理图片

<picture>
元素在网页性能上效果显著,同时也给我们带来很大的便利,问题是,我们怎样去生产这些不同大小的图片呢?假如你需要多份不同的图片,怎样得到这些图片呢?庆幸的是,有一种简单的方法可以解决这个问题。

使用 Grunt
响应式图片插件可以自动处理、剪裁图片。假如你对
Grunt
任务不熟,也不知道怎样将它引用到你的工程,请参考我之前发表的这篇博文。
Grunt
官网也提供了非常好的教学资源帮助你立刻开始使用它。

npm install grunt-responsive-images –save-dev

配置好 Grunt
,并且保证它能在你机器上运行之后,打开你的网站,在命令行里输入以下命令来下载相应的包。

npm install grunt-responsive-images –save-dev

接下来你还需要安装 ImageMagick 或 GraphicsMagick 命令行工具,然后配置
gruntfile.js
文件。下面是一个参数配置例子,有很多配置选项,可以根据实际需求设定不同的参数。

XHTML

grunt.initConfig({ responsive_images: { myTask: { options: { sizes: [{
width: 320, height: 240 },{ name: ‘large’, width: 640 },{ name: “large”,
width: 1024, suffix: “_x2”, quality: 60 }] }, files: [{ expand: true,
src: [‘assets/**.{jpg,gif,png}’], cwd: ‘test/’, dest: ‘tmp/’ }] }
}, })

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
grunt.initConfig({
  responsive_images: {
    myTask: {
      options: {
        sizes: [{
          width: 320,
          height: 240
        },{
          name: ‘large’,
          width: 640
        },{
          name: "large",
          width: 1024,
          suffix: "_x2",
          quality: 60
        }]
      },
      files: [{
        expand: true,
        src: [‘assets/**.{jpg,gif,png}’],
        cwd: ‘test/’,
        dest: ‘tmp/’
      }]
    }
  },
})

通过上面的参数设置,图片将生成 320 像素, 630 像素和 1024
像素的图片,每种像素的图片将放在不同的目录里。

现在,可以处理图片了。在命令行中运行 Grunt
命令,这个时候,可以看到目录下会新增加三个目录,每个目录中已经存在裁剪好了的图片!
Hooray !

如果还在想什么工具可以自动帮助你生成相关的 HTML 标签的话,这个 Grunt
插件能替你做这些苦差事。把这个插件和
Grunt responsive images 插件结合起来用,会给你带来更多意外惊喜。

实现需求

第一眼看到这个效果,感觉这个跟随动画,仅靠 CSS 是不可能完成的。

如果想只用 CSS 实现,只能另辟蹊径,使用一些讨巧的方法。

好,下面就借助一些奇技淫巧,使用 CSS
一步一步完成这个效果。分析一下难点:

是否应该将网格用于主布局和Flexbox用于组件布局

随着大家开始接触和学习CSS
Grid的布局,这个神话不断涌现。也许它来自于网格系统的使用,比如在Bootstrap或Foundation,大家关心的是一个整体网格上放置项目。这当然是使用网格布局的一种方法。不过,我还是会考虑在上一节提到的不同之处。问问你自己,这个布局是一维的还是二维的?

如果你可以使用你的组件,并且用行和列在它的上面绘制一个网格。它是二维的,那就使用CSS
Grid来布局。澳门微尼斯人手机版 4

如果相反,你希望单个项目在一行中进行扩展,而不考虑上面一行中发生的情况,那就应该使用Flexbox布局更为合适。

澳门微尼斯人手机版 5

不管你想要展示的是一个完整的页面,还是一个很小的组件。重要的是你想在布局里面的项目分配空间和相互关联。

OLDER BROWSERS

关注浏览器的新特性的同时,也要兼顾到老版本的浏览器。目前,只有 Chrome 38
和 Opera 支持 <picture> 元素。好消息是, <picture>
元素已经正式被 WHAT working
group 接受,逐渐所有现代浏览器都会支持这个标签。通过 caniuse.com 可以查到,你喜欢的浏览器现在是不是支持它。

幸好,现在有一个插件可以解决大部分传统浏览器不支持 <picture>
元素的问题。 Filament Group
的团队开发出 picturefill.js 这个文件,这个插件可以使不支持
<picture>
元素的浏览器解析这个标签以及标签相关的属性。这意味着,你今天就可以开始使用
<picture> 元素了!

要使用这个插件,你需要在你的页面中添加这个 JavaScript 文件。

XHTML

<picture> <source media=”(min-width: 1024px)”
srcset=”dest/1024/tiger.jpg”> <source media=”(min-width: 640px)”
srcset=”dest/640/tiger.jpg”> <source
srcset=”dest/320/tiger.jpg”> <img src=”dest/640/tiger.jpg”
alt=”This picture loads on non-supporting browsers.”>
<p>Accessible text.</p> </picture> <script> //
Picture element HTML5 shiv for older browsers document.createElement(
“picture” ); </script> <script src=”picturefill.min.js”
async></script>

1
2
3
4
5
6
7
8
9
10
11
12
<picture>
   <source media="(min-width: 1024px)" srcset="dest/1024/tiger.jpg">
   <source media="(min-width: 640px)" srcset="dest/640/tiger.jpg">
   <source srcset="dest/320/tiger.jpg">
   <img src="dest/640/tiger.jpg" alt="This picture loads on non-supporting browsers.">
   <p>Accessible text.</p>
</picture>
<script>
// Picture element HTML5 shiv for older browsers
document.createElement( "picture" );
</script>
<script src="picturefill.min.js" async></script>

再补充一句,这个插件和 picture
标签的功能是一样的。点击这个链接可以看到实例效果。在
Responsive Images Community Group
网站上还有很多例子。

宽度不固定

第一个难点, li 的宽度是不固定的。所以,我们可能需要从 li
本身的宽度上做文章。

既然每个 li
的宽度不一定,那么它对应的下划线的长度,肯定是是要和他本身相适应的。自然而然,我们就会想到使用它的
border-bottom

li { border-bottom: 2px solid #000; }

1
2
3
li {
    border-bottom: 2px solid #000;
}

那么,可能现在是这样子的(li 之间是相连在一起的,li 间的间隙使用
padding 产生):

澳门微尼斯人手机版 6

网格轨道大小是否由内容来决定?

我们已经看到了如何在使用网格布局时,在容器上设置网格和网格大小。但是,网格中的项可以指定网格轨道大小。这里要记住的关键是,一个单元格大小的改变将会改变整个轨道的大小。如果你不希望这种情况发生,你可能需要一个单一维度的Flexbox布局。

最简单的方法就是使用auto,因为它会默认在隐式网格中创建网格轨道。一个自动大小的网格轨道将扩展到包含所有的内容。在下面的示例中,我有一个两列布局,在右边的列中添加更多的内容会导致整个行的扩展。第二行也是自动大小,再扩展以包含内容。

 DEMO6

我们可以使用两个参数来控制网格轨道大小,例如创建一个最小的网格轨道,但其仍然会增长以适应较大的网格项目。我们可以使用minmax()函数来做这个。传给minmax()函数的第一个值,它是网格轨道最小的值,第二个值是网格轨道最大的值。因此,你可以设置200px的行,但通过auto设置为网格轨道最大值,那么当有较多的内容时,不会出现内容溢出。

DEMO7

也有一些有趣的关键词可以设置大小,将在以后的文章中对它们进行适当的阐述。这些关键词在指定网格中允许内容来改变网格轨道大小,并且可以在CSS内部和外部的大小模块(CSS
Intrinsic and Extrinsic Sizing
Module)中找到相关的详细内容。例如min-content关键词的示例,使用它创建一个网格轨道时,将会创建尽可能小的网格轨道。

在我的例子中,这个词意味着其成为最宽的东西,网格轨首缩小以适应它。

 DEMO8

相反,如果你使用的是max-content,你会得到一个尽可能大的网格轨道。这可能会导致溢出情况,在下面的示例中,使用了overflow: scroll设置了网格溢出,所以max-content的网格轨道会导致滚动条出现。

DEMO9

关键要记住的是,这将会发生在整个网格轨道上。你需要确保网格轨道的其他网格项目也能巧妙地吸收额外的空间。

了解了如何对网格轨道大小进行调整,以及内容将如何改变网格轨道大小,这可能是新手使用CSS
Grid布局中会感到最为困惑的事情之一。这需要花一点时间来理解 ——
我们之前没有任何类似的行为。这是理解事物如何运作的最好方法。

附注

我第一次使用 picture 标签的时候,出现了这个错误:

“<source src> with a <picture> parent is invalid and
therefore ignored. Please use <source srcset> instead.”

这次错误提示信息非常明确,在引用图片资源时不要使用 src 标签,使用 srcset
标签就可以了。

1 赞 1 收藏
评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注