得益于 CSS3 弹性盒布局模块,创建灵活的应用布局变得非常容易。在本文中,我们将实现一个简单的应用布局,它填充整个屏幕,随着浏览器窗口大小调整,并且附带一个可拖动的分割器的额外好处。
除了经典的 <div>
元素外,我们还可以使用一些 HTML5 结构化标签。这不仅使代码更具语义化,而且更方便使用,因为我们可以直接使用 CSS 类型选择器来定位元素,而无需依赖 id 属性或父子关系。
查看 完整的演示 以了解其工作原理。
第一步:添加垂直盒子
我们从主体中的三个标签(<header>、<main> 和 <footer>)开始。
CSS3 Application Layout
让我们添加 CSS 以使这三个元素垂直填充空间。这是通过将 <body>
的 CSS display
属性设置为 flex
以及 flex-direction
属性设置为 column
来实现的。这告诉浏览器将主体的子元素(<header>
、<main>
和 <footer>
)作为垂直弹性盒子进行布局。
可以使用 flex
简写属性控制可用空间的分配方式。您可以在 MDN 上阅读相关信息。但是,在此应用布局中,我们不希望大小按比例缩小或扩展。相反,<header>
和 <footer>
元素应具有固定高度,而 <main>
应通过将其 flex
属性设置为 auto
来填充剩余空间。
html, body {
height: 100%;
width: 100%;
padding: 0;
margin: 0;
}
body {
display: flex;
flex-direction: column;
}
header {
height: 75px;
}
main {
flex: auto;
}
footer {
height: 25px;
}
第二步:水平盒子
让我们在 <main>
元素内再添加三个元素(<nav>
、<article>
和 <aside>
)。但这次我们希望它们水平而不是垂直地填充 <main>
元素内的空间。
这是通过将 <main>
元素的 display
属性也设置为 flex
,但 flex-direction
属性设置为 row
来实现的(这是默认值)。<nav>
和 <aside>
元素应具有固定宽度,而 <article>
应填充剩余空间:这与之前的方式相同。
main {
display: flex;
flex-direction: row;
flex: auto;
}
nav {
width: 150px;
}
article {
flex: auto;
}
aside {
width: 50px;
}
就是这样。调整浏览器窗口大小并享受灵活的应用程序布局。
下一步:CSS 优化
但是等等。当内容很多时,某个元素可能会变得比指定的小,并且还会出现滚动条。
因此,我们需要为添加了 width
属性的所有元素添加 min-width
属性。我们还应将 <body>
和 <main>
元素的 overflow
属性设置为 hidden
,并将 <article>
和 <aside>
的 overflow-y
设置为 auto
,以便仅在我们需要的地方显示滚动条。
body {
overflow: hidden;
display: flex;
flex-direction: column;
}
header {
height: 75px;
min-height: 75px;
}
footer {
height: 25px;
min-height: 25px;
}
main {
display: flex;
flex-direction: row;
flex: auto;
border: solid grey;
border-width: 1px 0;
overflow: hidden;
}
nav {
width: 150px;
min-width: 150px;
}
article {
border: solid grey;
border-width: 0 0 0 1px;
flex: auto;
overflow-x: hidden;
overflow-y: auto;
}
aside {
width: 50px;
min-width: 50px;
overflow-x: hidden;
overflow-y: auto;
}
注意:这可能在 Safari 中尚无法使用。您可以尝试使用 -webkit-
前缀来使其工作。
最后一步:加入一些 JavaScript
作为最后一步,我们希望用户能够在用鼠标拖动时调整 <aside>
元素的大小。为此,我们添加了一个 <div>
元素作为分割器,它将用作拖动手柄。
我们将手柄的宽度设置为 4px,并将 cursor
属性的值设置为 col-resize
,以向用户显示此元素可以东西方向调整大小。
.splitter {
border-left: 1px solid grey;
width: 4px;
min-width: 4px;
cursor: col-resize;
}
现在剩下的就是添加一小段 JavaScript 来启用移动分割器。
var w = window, d = document, splitter;
splitter = {
lastX: 0,
leftEl: null,
rightEl: null,
init: function(handler, leftEl, rightEl) {
var self = this;
this.leftEl = leftEl;
this.rightEl = rightEl;
handler.addEventListener('mousedown', function(evt) {
evt.preventDefault(); /* prevent text selection */
self.lastX = evt.clientX;
w.addEventListener('mousemove', self.drag);
w.addEventListener('mouseup', self.endDrag);
});
},
drag: function(evt) {
var wL, wR, wDiff = evt.clientX - splitter.lastX;
wL = d.defaultView.getComputedStyle(splitter.leftEl, '').getPropertyValue('width');
wR = d.defaultView.getComputedStyle(splitter.rightEl, '').getPropertyValue('width');
wL = parseInt(wL, 10) + wDiff;
wR = parseInt(wR, 10) - wDiff;
splitter.leftEl.style.width = wL + 'px';
splitter.rightEl.style.width = wR + 'px';
splitter.lastX = evt.clientX;
},
endDrag: function() {
w.removeEventListener('mousemove', splitter.drag);
w.removeEventListener('mouseup', splitter.endDrag);
}
};
splitter.init(d.getElementsByClassName('splitter')[0], d.getElementsByTagName('article')[0], d.getElementsByTagName('aside')[0]);
注意:由于某种原因,调整大小在 IE11(、Safari?)或 Chrome 31 中不起作用。这似乎与 display: flex;
属性值有关。
关于 Simon Speich
Simon Speich 是一位 Web 开发人员,相信 Web 标准,并且从 Mozilla 0.8 开始就热爱 Mozilla。他还热衷于 摄影。您可以在他的网站 www.speich.net 上了解更多关于他的信息。
关于 Robert Nyman [荣誉编辑]
Mozilla Hacks 的技术布道师和编辑。发表关于 HTML5、JavaScript 和开放 Web 的演讲和博客文章。Robert 坚定地相信 HTML5 和开放 Web,自 1999 年以来一直从事 Web 前端开发工作 - 在瑞典和纽约市。他还定期在 http://robertnyman.com 上发表博客文章,并且喜欢旅行和结识新朋友。
6 条评论