本文由大漠根据Jackie Balzer的《Sassy Z-Index Management For Complex Layouts》所译,整个译文带有我们自己的理解与思想,如果译得不好或有不对之处还请同行朋友指点。如需转载此译文,需注明原作者相关信息http://www.smashingmagazine.com/2014/06/12/sassy-z-index-management-for-complex-layouts/。
——作者:Jackie Balzer
——译者:大漠
z-index
本身就是一个棘手的事情,在一个复杂的布局中管理z-index
的顺序(层级)更是困难。不同的层叠顺序和内容,要跟踪他们的数字增加是很难的事情——而且他们来自CSS文件,忘了他吧!因为z-index
可以造就一个UI元素可见或不可见,使您的网站的用户界面工作秩序是很微妙的。
因为z-index
值跟上下文有关系,一旦你开始使用它,它可以很容易为其他元素先显示(如果元素需要)。在网站上查找z-index: 99999
规则,它并少见,但使用臭名昭著的99999实属无耐之举。它经常被误用,认为让元素可以高于一切元素,但z-index
并不总是那么简单。它也不是完全可扩展:你有什么东西是要放在最顶上的?
另一种策略是两位数递增z-index
的值,让你有足够的空间给其他元素插入值,但并没有解决如何跟踪z-index
值的问题,当你想在他们之间添加值时,它不能很好的扩展。
每个实例提出了一个问题:
z-index
值?所有其他元素上下文关系是什么?z-index
合适?如果我增加一项,哪个会受影响?z-index
的值我必须增加?使用Sass的列表来控制上述所有因素是非常容易的。让我们以Behance主页做为一个例子:
我们需要管理的顺序包括项目遮罩层、过滤器栏、位置搜索弹出窗、下拉菜单和导航。按这个顺序,从下到上。我们可以创建一个Sass的列表,如下:
$elements: project-covers, sorting-bar, modals, navigation;
在这个列表中,我们希望我们的元素的出现,从低到高。数组的顺序表示元素的z-index
值。我们使用Sass的index()
函数将z-index
的值分配给每个元素。
例如:
.project-cover {
z-index: index($elements, project-covers);
}
这将输出:
.project-cover {
z-index: 1;
}
这是因为project-cover
是列表中的第一个元素,他的索引值是1,z-index
顺序中最低的元素。让我们用Sass给列表中其他元素指定z-index
值:
.sorting-bar {
z-index: index($elements, sorting-bar);
}
.modal {
z-index: index($elements, modals);
}
.navigation {
z-index: index($elements, navigation);
}
现在编译出来的CSS看起来像这样:
.project-cover {
z-index: 1;
}
.sorting-bar {
z-index: 2;
}
.modal {
z-index: 3;
}
.navigation {
z-index: 4;
}
现在你可以将类名应用到相应的元素上。但是,如果我们想要给一个元素添加到现有的层叠顺序中呢?假设用户鼠标悬停在一个用户名上会弹出一个提示框(tooltip
),他的位置在project-cover
上面,但在其他元素的下面。
在乏味的CSS中,我们需要重新更新sorting-bar
、modal
和navigation
的z-index
的值。使用Sass,我们只需要为新元素更新列表:
$elements: project-covers, user-tooltip, sorting-bar, modals, navigation;
因为sorting-bar
、modal
和navigation
的z-index
的值在列表中已发生变化(以前他们的z-index
的值是2,3,4,现在变成了3,4,5)。我们编译出来的CSS会自动调整他们的z-index
值,用以新的位置。我们只需要在Sass中添加下面的代码:
.user-tooltip {
z-index: index($elements, user-tooltip);
}
这个时候,编译出来的CSS如下:
.user-tooltip {
z-index: 2;
}
.sorting-bar {
z-index: 3;
}
.modal {
z-index: 4;
}
.navigation {
z-index: 5;
}
假设我们的布局更复杂,有多个层叠的上下文和层叠顺序。(请记住,要让z-index
起作用,需要确保position
的值不是static
,这就是新创建一个层叠的内容,只要将层叠顺序值指定所有元素的父元素上。)在这种情况下,一个列表可能不够使用。我们需要创建多个列表,每个列表会被认为是一个上下文。
$elements: project-covers, user-tooltip, sorting-bar, modals, navigation;
$modal-elements: fields, form-controls, errors, autocomplete-dropdown;
.modal {
z-index: index($elements, modals);
.field {
z-index: index($modal-elements, fields);
}
.form-controls {
z-index: index($modal-elements, form-controls);
}
.error {
z-index: index($modal-elements, errors);
}
.autocomplete-dropdown {
z-index: index($modal-elements, autocomplete-dropdown);
}
} /* .modal */
编译出来的CSS:
.modal {
z-index: 4;
}
.modal .field {
z-index: 1;
}
.modal .form-controls {
z-index: 2;
}
.modal .error {
z-index: 3;
}
.modal .autocomplete-dropdown {
z-index: 4;
}
这种技术最主要的要求就是坚持维护。任何硬性的z-index
值都可能危及到那些列表的完整性。正因为如此,你会发现,你可能在一个网站会有多个页面要定义z-index
的值。最简单的方案就是创建一个局部的文件,包括整个网站的列表,然后就可以在需要的地方使用。(你可能有了这样的局部文件,比如用来存储网站颜色,字体等变量——这是类似的一个做法)。
$elements: project-covers, user-tooltip, sorting-bar, modals, navigation;
$modal-elements: fields, form-controls, errors, autocomplete-dropdown;
@import '_zindex.scss'
.modal {
z-index: index($elements, modals);
}
每个页面修改或合并全局的列表也是可能的。你导入你的那部分,然后使用Sass的列表函数(或者更高级的功能)修改你需要的部分。例如:
import '_zindex.scss'
$modal-elements: append($modal-elements, close-button);
$elements: insert-nth($elements, sidebar-filters, 3);
.modal .close-button {
z-index: index($modal-elements, close-button);
}
.sidebar-filter {
z-index: index($elements, sidebar-filter);
}
这个Sass会在modal-elements
列表最后面插入一个close-buttons
和在elements
列表第三个顺序中插入sidear-filters
,而且不会影响其他页面使用的_z-index.scss
。
经常检查代码中的错误,以避免造成错误。例如你想给不在你列表中的项设置z-index
值,你可能会发现一个意想不到的输出:
.objects {
z-index: index($elements, thing-not-in-my-list);
}
.objects {
z-index: false;
}
因为false
不是z-index
的有效值,我们不希望他出现在我们编译出来的代码中。我们可以自定义一个函数,使用Sass的@warn
,在一开始就告诉我们东西是否出了问题。
@function z($list, $element) {
$z-index: index($list, $element);
@if $z-index {
@return $z-index;
}
@warn 'There is no item "#{$element}" in this list; choose one of: #{$list}';
@return null;
}
这个函数接受 index()
相同的参数,但在返回值之前他会检查我们要求的东西是否存在列表中。如果该值存在,他就会返回index()
的索引值,就像刚才一样。如果该值不存在,他会发现两件事:
null
值,告诉Sass不会打印出相应的规则而不是以下无效的CSS:
.objects {
z-index: false;
}
z-index
的值一直不会打印出来。如果他在你的规则中是唯一的一个规则,那么Sass甚至会做出不打印的选择,从而最大限度的减少不必要的输出。
跟踪上下文的层叠顺序,使用CSS是非常难的,但使用预处理程序使它变得更容易。有许多方法可以处理它,但我们看到这里的做法是最简单的,需要最少的维护。而且由于Sass的列表和函数如此强大,你必须扩大这项技术,因为你需要更好的掌握他们。
译者手语:整个翻译依照原文线路进行,并在翻译过程略加了个人对技术的理解。如果翻译有不对之处,还烦请同行朋友指点。谢谢!
出处:
英文出处:http://www.smashingmagazine.com/2014/06/12/sassy-z-index-management-for-complex-layouts/
中文译文:http://www.w3cplus.com/preprocessor/sassy-z-index-management-for-complex-layouts.html