6

经验法则 - 如果您在布局中过多地使用 CSS,请切换到框架。我一直在研究几十个网格/布局框架,其中大多数都专注于传统的文档网格布局。

我的页面更像是一个 SPA(单页应用程序)。它类似于桌面应用程序使用的布局。显然 HTML 不能很好地处理这个问题,需要大量的 CSS 修补。

这是我试图实现的布局示例(这应该填满整个屏幕): 在此处输入图像描述

请注意,固定菜单不应悬停在其后面的滚动内容上。每个块都应该驻留在自己单独的“框架”中——即左侧长列表的滚动条应该出现在固定菜单的下方。

我还没有找到支持这个的轻量级网格框架(像 Sencha 或 Kendo UI 这样的框架有点矫枉过正)。手动完成 CSS 非常费力。特别是如果我决定显示一个模式对话框,并且需要在此对话框内进行类似的布局(顺便说一句,这最终杀死了我)。或者,如果我决定要在底部放置另一个固定菜单,那么一切都会崩溃。

我什至不确定这是否仅适用于 CSS(我知道至少固定底部菜单需要 CSS 中的一些硬编码值才能缩小其后面的内容,以免滚动条重叠)。如果需要 JS 解决方案,并且我希望它能够处理浏览器屏幕大小调整事件 - 再一次崩溃,因为没有简单的常见事件可以做到这一点。

我应该如何以可维护/灵活的方式解决这个问题?

评论:您会注意到,我自己添加了一个答案,建议使用 HTML 表格实现此布局。我真的不想接受我自己的答案。我有一种感觉,没有人会“勇敢”地推荐桌子(这毕竟是有争议的),我愿意为了讨论而遭受反对票

澄清:在说可维护和灵活时,我似乎不够清楚。我的意思是让布局优雅地处理各种场景或需要的修改(即代表我做的工作很少)。为了绝对具体,让我们举一些例子:

  1. 布局不应该介意它是显示为整页还是在固定模式对话框(即引导对话框)内。在这些场景之间切换应该尽可能少地改变布局代码。

  2. 布局应该支持多种方式来描述宽度和高度(即侧边栏的宽度或顶部菜单的高度)。更具体地说,应支持以下大小调整方法:

    • 精确的固定像素大小。
    • 通过使用容器的百分比来确定相对大小。例如:侧边栏宽度是整个容器(整页或对话框)宽度的 30%。另一个例子:顶部菜单高度是容器(整页或对话框)整个高度的 20%。
    • 环绕它自己的内容。示例:顶部菜单的高度将取决于其中的内容。如果您输入一行文本,它将在不滚动的情况下换行。如果您输入两行文本,它将是两倍大并按住它们而不滚动。
    • 奖金:两者的简单组合。就像侧边栏宽度为 20% 但不少于 50 像素。

正如 Ian Clark 最专业地指出的那样,CSS 可以开箱即用地实现大多数这些请求。对此没有任何争论。问题仍然存在,如果原始 CSS 是最简单的使用,以及是否有任何东西可以通过框架/另一种机制(如 flexbox/表格)从开发人员那里卸载。

4

9 回答 9

8

更新 2(这个问题似乎在演变!):

标准 1 - 在整页或内部模式之间切换应尽可能少地更改代码

因为在这种情况下,我们的宽度/高度body始终是宽度/高度的 100% window,如果您希望您的代码轻松适应模态等,您始终可以使用position:absolute,因为没有任何上下文,这将相对于body.

标准 2 - 布局应该支持多种方式来描述宽度和高度

这是一个 JSFiddle,几乎可以完成您提到的所有操作。它在固定元素上使用百分比和固定像素宽度。首先要注意的是,我必须做的唯一更改是在box-sizing:border-box我们的每个元素中添加一个。与 flexbox 不同,这对 IE8 有很好的支持,因此不会引起任何问题。添加它允许我们向元素添加填充,而无需更改宽度以进行补偿。

虽然左侧边栏的宽度为 20%,但它们的最小宽度也为 100 像素。为了防止与右侧的主要内容重叠,我们使用一些简单的逻辑来建立逆:

Reaches Min At = Min-width / Width * 100

在我们的示例中,我们的左侧边栏因此在 处达到最小值100/20*100 = 500px。然后@media当我们达到这个窗口大小时,我们使用一个选择器来改变我们主要内容的宽度:

@media(max-width:500px) {
  #scrolling-content { 
    left:100px;
  }
}

通过更改小提琴上的窗口大小,您会注意到当您达到最小大小时,我们的主要内容区域会改变颜色。现在我承认,这可能看起来令人困惑,但同样,通过使用诸如 Less 之类的语言,您可以轻松地将widthand设置min-widths为变量,并使用一个简单的函数来更改您的 CSS。现在我使用“几乎所有东西”这个短语的原因是因为如果你想在模态中做类似的事情,这可能会变得更加复杂,但谁知道呢,这可能是可能的!

需要注意的一点:如果您打算使用 JavaScript 来获取调整大小的事件,请务必考虑使用jQuery debounced resize 插件,因为您不想进行比您需要的计算次数多数百倍的计算!我将在此答案中留下额外的内容,因为大多数内容仍然与您的发展中的问题相关且在历史上是准确的


更新:有很多建议使用 Flexbox 的答案,但我现在真的不认为这是一个很好的解决方案。不要误会我的意思,如果 FlexBox 是一个真正可行的解决方案,我会喜欢它,但目前对它们的支持很糟糕,如果你打算为大多数网络填充它,你可能会使用任何其他 JavaScript 解决方案,我认为 JavaScript 不是用于整个页面呈现的正确工具。

仍然不明白为什么使用简单的 CSS 很难实现您的目标position。您不需要使用任何 JavaScript 和。我认为这非常易于管理的。如果您真的在维护您的样式表方面遇到困难,那么为什么不使用Sass/SCSSLess之类的东西,因为您可以创建变量、mixin、函数等,并显着减少您需要进行的更改数量。


也就是说,他是您解决方案的一个非常快速的模型,仅使用纯 CSS 和 HTML 工作。我使用的是 4 个固定divs,并且可以进行简单的修改,以便“滚动内容”不固定,而只是使用边距来正确定位。这将有额外的好处,不必在 div 内滚动,但能够对身体进行滚动。

所有必需的CSS:

div { position:fixed; }
#top {
    top:0;
    left:0;
    right:0;
    height:40px;
}

#menu {
    top:40px;
    height:40px;
    left:0;
    width:200px;
}

#long-list {
    top:80px;
    left:0;
    width:200px;
    bottom:0;
    overflow-y:auto;
}
#scrolling-content {
    top:40px;
    bottom:0;
    right:0;
    left:200px;
    overflow-y:auto;
}

很容易注意到40px200px作为菜单的高度和宽度的重复。考虑到这一点,您可以简单地使用动态语言的变量并只定义一次(较少示例):

@leftwidth: 200px;

#scrolling-content {
    left:@leftwidth;
}
#menu, #longlist {
    width:@leftwidth;
}

争议#1:框架不灵活或不易编辑

您提到很难轻松操作 CSS 框架,因为依赖于静态内容,他们必须决定要使用的列数(在 Bootstrap 和许多其他情况下,他们选择 12,因为它很容易被 1、2、3 整除, 4,6)。但是,在 Bootstrap 2 中,自定义列数非常容易。预计当 Bootstrap 3 RC2 出现时,此功能也会存在。还有许多资源可让您将Less 与 Bootstrap一起使用。也就是说,创建一个 Less 风格的灵活流体网格系统是相当常规的,请参阅演示(免责声明:我没有使用 Less 的经验,这篇文章帮助我进行循环):

/* The total number of columns you wish to use */
@columns: 15;
/* 
    We loop through and for each create class
   .dynamic-<index>-<columns> 
*/
 .looping (@index) when (@index > 0) {
    (~".dynamic-@{index}-@{columns}") {
        width: percentage(@index/@columns);
    }
    .looping(@index - 1);
}
/* Stop and do nothing at 0 */
.looping (0) {}
/* Call our function */
.looping (@columns);

然后你的 HTML 标记就变成了:

<div class="cf rows">
    <div class="dynamic-4-15">4/15th width</div>
    <div class="dynamic-7-15">7/15th width</div>
</div>

争议 #2:基于百分比的模态很难使用 CSS

在您提到的评论中,您“希望布局相对于对话框宽度,而不是浏览器窗口宽度”。那么这当然也是可能的。事实上,这真的很简单,几乎不需要更改我们的代码

#some-modal {
   position:fixed;
   top:10%;
   bottom:10%;
   left:10%;
   right:10%;
}
/* Before this was simply div, and it was fixed, now it's absolute */
#some-modal div {
   position:absolute;
   padding:10px;
}
于 2013-08-04T16:03:55.573 回答
2

我不知道为什么你的回答被否决了。每个人似乎都同意“不需要专门的框架”至少是一个好的答案的一部分。使用表格当然有缺点,但你似乎意识到了这一点,列出缺点在我看来是一个非常一致的答案。

尽管考虑了您的回答,但我还是会使用 Flexbox 模型。它似乎更合适(正如@cimmanon 在另一个答案中所说的那样)、语义化,甚至比表格更容易维护。此外,使用最新的技术可能会延长您的应用程序的生命周期。如果您担心向后兼容性,请查看这个库 - http://flexiejs.com/

您还可以使用其他元素和 css Table 模型来模拟表格的行为,例如:<div style="display:table">. 以这个小提琴为例 - http://jsfiddle.net/JWqVQ/

这里有更多关于不同渲染选项的信息 - https://developer.mozilla.org/en-US/docs/Web/CSS/display

于 2013-08-07T03:58:07.810 回答
1

您可以使用直接、最少的 CSS完全灵活(用户更改字体大小或您的内容长度未知?没问题)。

http://codepen.io/cimmanon/pen/vusmz

假设这个标记:

<header>Header</header>

<div class="container">
  <div class="sidebar">
    <aside>Menu (fixed)</aside>
    <nav>long list</nav>
  </div>
  <main>
    <p>...</p>
  </main>
</div>

CSS:

body, html {
  height: 100%;
  max-height: 100%;
  margin: 0;
  padding: 0;
}

body {
  display: -ms-flexbox;
  display: -webkit-flex;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
}
@supports (flex-wrap: wrap) {
  body {
    display: flex;
  }
}

.container {
  display: -ms-flexbox;
  display: -webkit-flex;
  -webkit-flex-flow: column wrap;
  -ms-flex-flow: column wrap;
  flex-flow: column wrap;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
}
@supports (flex-wrap: wrap) {
  .container {
    display: flex;
  }
}

.sidebar {
  display: -ms-flexbox;
  display: -webkit-flex;
  -webkit-flex-direction: column;
  -ms-flex-direction: column;
  flex-direction: column;
  -webkit-flex: 1 100%;
  -ms-flex: 1 100%;
  flex: 1 100%;
}
@supports (flex-wrap: wrap) {
  .sidebar {
    display: flex;
  }
}

header {
  background: yellow;
  height: 3em; /* optional */
}

aside {
  background: green;
  height: 4em; /* optional */
}

nav {
  background: orange;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
  overflow-y: scroll;
  height: 1px;
}

main {
  background: grey;
  -webkit-flex: 1;
  -ms-flex: 1;
  flex: 1;
  overflow-y: scroll;
  height: 1px;
}

由于需要flex-wrap: wrap支持,浏览器支持受到限制(IE10 是唯一支持它的“部分支持”浏览器:http: //caniuse.com/#feat=flexbox)。当前浏览器支持仅限于 Chrome、Opera、IE10 和 Blackberry 10。

请注意,滚动元素的高度非常小,这可能会导致缺乏完全 Flexbox 支持的浏览器出现问题(有关更多信息,请参阅:Flexbox and vertical scroll in a full-height app using NEWER flexbox api)。

于 2013-08-06T02:06:15.357 回答
0

在某些项目中,我借助这样的代码(在 FF 上测试)完成了它:

<style>
#topMenu {
    position: fixed;
    left: 0px;
    top: 0px;
    width: 100%;
    height: 100px;
}
#sidePanel {
    position: fixed;
    left: 0px;
    top: 100px;    
    width: 100px;
}
#sideMenu {
    width: 100%;
    height: 50px;
}
#sideList {
    border-width: 0px;
    width: 100%;
    padding: 0px;
    margin: 0px;
    background-color: #FFF0F0;
}
#content {
    border-width: 0px;
    padding: 0px;
    margin: 0px;
    background-color: #F0FFF0;
}
body {
    border-width: 0px;
    padding: 100px 0px 0px 100px;
    margin: 0px;
}
</style>

<div id="topMenu">Top menu</div>
<div id="sidePanel">
    <div id="sideMenu">Size menu</div>
    <iframe id="sideList"></iframe>
</div>    
<iframe id="content"></iframe>

<script>
function onResize() {

    var sizePanel = document.getElementById("sidePanel");
    sizePanel.style.height = (document.documentElement.clientHeight - 100) + "px";   
    document.getElementById("sideList").style.height = (sizePanel.clientHeight - 50) + "px";   

    var content = document.getElementById("content");
    content.style.width = (document.documentElement.clientWidth - 100 - 10) + "px";
    content.style.height = (document.documentElement.clientHeight - 100 - 10) + "px";
}

window.addEventListener("resize", onResize);
onResize();

</script>
于 2013-07-30T10:13:59.193 回答
0

作为记录,我认为 Ian 给出了迄今为止最完整和最准确的答案,纯粹的 CSS 答案,而且效果很好。但是,您还想知道您有哪些替代方案,我至少必须提供另一种选择,以便您知道它是可用的:

我挑战你的前提,即 Javascript 不能做你想做的事。在我看来,JQuery 是一个真正革命性的 Javascript 库,并且极大地简化了它。根据维基百科,Jquery“被 10,000 个访问量最大的网站中的 65% 以上使用”。从个人经验来看,尝试在我的网站上使用纯 CSS 对我来说很失败。使用 JQuery 给了我更多的灵活性和对 CSS 的控制,不再强迫我使用相对值。我是一个控制狂,所以这对我有用。

JQuery 非常容易学习,并且允许使用 Javascript 处理程序和事件来补充 CSS 浏览器事件。例如,如果您想在刷新时更改 CSS:

$(document).ready(function() {
    $(window).resize(function() {
         var windowWidth = $(window).width();
         $('#div').css('width',windowWidth-100); //the # references id, like in CSS
    });
});

在我的JSFiddle上查看更详细的示例

如果 JQuery 听起来是让你的 CSS 在任何场合都动态和灵活的正确途径,那么这里有几个教程。如果您了解 CSS 和 Javascript,用不了多久,它就会像魅力一样工作。即使你不懂 Javascript,你也可以用 JQuery 做很多事情。只需一点学习曲线,您肯定会找到什么。

于 2013-08-10T02:51:04.457 回答
0

我认为您不需要使用框架,尤其是在您不熟悉它们并且遇到麻烦的情况下。如果您只是将不同的视图设置为溢出:滚动,您应该也可以创建您在该图像中描述的内容。您可以做的另一件事是为每个视图设置一个 iframe,就像Javadocs所做的那样。

于 2013-08-05T08:16:56.860 回答
0

“有几十个网格/布局框架,其中大多数专注于传统的文档网格布局。”

你让它听起来像是一件坏事。我不明白你为什么不使用网格框架。如果您有任何意图使您的应用程序平板电脑和移动设备友好,这是相当标准的做法。它们中的大多数都非常快速设置,几乎不需要额外的 css。

kube为例。它非常简约和灵活。您基本上只需将预定义的类添加到您希望应用为大小的 div 标签。

<div class="units-row">
    <div class="unit-30"></div>
    <div class="unit-70"></div>
</div>

这种类型的步骤不会与模态或 iframe 混淆。要修改所有你需要做的就是改变类..需要一个更大的左侧,只需改变 div 的类

<div class="units-row">
    <div class="unit-80"></div>
    <div class="unit-20"></div>
</div>

对于较小的分辨率,这将优雅地降级,同时保持您的编码风格,就像在任何其他应用程序中一样。

如果你愿意,你可以从头开始写,但是..为什么?

基础也非常好,我用于我的项目

于 2013-08-10T14:50:44.443 回答
0

您可能想查看Cascade Framework并将此模板用作布局的起点。

在此处输入图像描述

于 2016-01-14T02:19:39.763 回答
-1

披露:我是 OP,我正在提出一个想法以获得普遍的回应。

不需要专门的框架,因为您可以为此使用TABLES

是的,我说的是被广泛避免的<table> <tr> <td>for 布局区域。众所周知,布局时应避免使用表格。我试图回顾一下这里提到的原因:Why not use tables for layout in HTML?

在我看来,在这种情况下大多数原因都无效(SPA):

内容与布局的分离 - 由于 SPA 不是真正的内容(它只是一个带有 AJAX 填充数据的骨架),因此此论点不适用。这只是一个界面,我不希望谷歌索引它。

表的可维护性较差- 在这种情况下不是。使用 div 实现这一点所必须经历的 CSS 地狱可维护性要差得多。

表格的渲染速度较慢- 当然,但我们想要一个需要更多计算才能渲染的复杂布局。哎呀,我们通常用 JS 调整大小事件来补偿。浏览器在渲染引擎中本地执行此操作会非常有效。

于 2013-07-31T07:34:16.340 回答