CSS网格/布局框架,侧重于固定元素和单页全屏布局

时间:2013-07-30 08:43:16

标签: html css layout frameworks single-page-application

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

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

这是我想要实现的布局示例(这应该填满整个屏幕): enter image description here

请注意,固定菜单不应悬停在其后面的滚动内容上。每个块应位于其自己的单独“框架”中 - 即左侧长列表的滚动条应显示在固定菜单下方。

我无法找到支持此功能的轻量级网格框架(像Sencha或Kendo UI这样的框架有点过分)。手动执行CSS非常费力。特别是如果我决定显示一个模态对话框,并在此对话框中需要类似的布局(这是最终杀了我的东西)。或者,如果我决定在底部需要另一个固定菜单,那么一切都会破裂。

我甚至不确定只使用CSS是否可行(我知道至少固定的底部菜单需要CSS中的一些硬编码值以缩小其后面的内容,以便滚动条不重叠)。如果需要JS解决方案,并且我希望它能够处理浏览器屏幕大小调整事件 - 那么所有地狱都会破裂,因为没有简单的常见事件可以做到这一点。

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

评论:正如您将注意到的,我自己建议使用HTML表格来实现此布局。我真的不想接受我自己的答案。我有一种感觉,没有人会“勇敢”地建议表格(毕竟它有争议)而且我愿意为了讨论而遭受挫折

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

  1. 如果布局显示为整页或固定模式对话框(即引导对话框),则不应介意布局。在这些场景之间切换应尽可能少地更改布局代码。

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

    • 确切的固定像素大小。
    • 使用容器的百分比进行相对大小调整。例如:侧栏宽度是整个容器宽度的30%(整页或对话框)。另一个例子:顶部菜单高度是容器整个高度的20%(整页或对话框)。
    • 包装自己的内容。示例:顶部菜单的高度取决于其中的内容。如果输入一行文本,它将包装它而不滚动。如果输入两行文本,它将是两倍大并且不滚动就保持它们。
    • 奖励:两个简单的组合。就像侧边栏宽度为20%但不小于50像素一样。
  3. 正如Ian Clark最专业地指出的那样,CSS可以实现大部分开箱即用的请求。对此没有任何争论。问题仍然存在,原始CSS是否最简单,如果有任何东西可以通过框架/其他机制(如flexbox / tables)从开发人员卸载。

9 个答案:

答案 0 :(得分:8)

更新2 (这个问题似乎在不断发展!):

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

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

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

<强> Here's a JSFiddle that can do almost everything you mention 即可。它在固定元素上使用百分比和固定像素宽度。首先要注意的是,我必须做的唯一改变是为每个元素添加box-sizing:border-box。与flexbox不同,this has good support会回到IE8,因此不会引起任何问题。添加这个允许我们为元素添加填充,而不必更改宽度来补偿。

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

Reaches Min At = Min-width / Width * 100

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

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

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

要带走一件小事:如果您打算使用JavaScript来获取调整大小事件,请务必考虑jQuery debounced resize plugin,因为您不希望进行数百倍于您需要的计算至! 我在这个答案中留下了额外的内容,因为大多数内容仍然与您正在发展的问题相关并且在历史上是准确的


更新:有很多建议使用Flexbox的答案,但我真的不认为这是一个很好的解决方案。不要误会我的意思,如果FlexBox是一个非常可行的解决方案,那么喜欢它,但是 Support for them is terrible ,如果你要去然后,您可以使用任何其他JavaScript解决方案来填充它,我不认为JavaScript是用于整个页面呈现的正确工具。

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


那就是 he's a really quick mockup of your solution ,只使用纯CSS和HTML。我正在使用的是4个固定的div,并且可以进行简单的修改,以便“滚动内容”不固定,但只是使用边距来正确定位。这将有额外的好处,不必在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中,customise the number of columns非常容易。当Bootstrap 3 RC2出现时,预计此功能也会存在。还有许多资源允许您使用Less with Bootstrap。也就是说,创建一个Less-style灵活的流体网格系统see demo(免责声明:我没有使用Less,this article helped me with looping的经验)是相当常规的:

/* 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

难以使用基于百分比的模态

在您提到的评论中,您“希望布局相对于对话框宽度,而不是浏览器窗口宽度”。那当然也是可能的。事实上,它非常简单, and requires almost no change to our code

#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;
}

答案 1 :(得分: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

答案 2 :(得分: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)。

答案 3 :(得分: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>

答案 4 :(得分:0)

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

答案 5 :(得分:0)

为了记录,我认为Ian在这里给出了一个纯粹的CSS答案的最完整和准确的答案,这将完美地工作。但是,你也想知道你有什么替代品,我必须至少提供另一种选择,以便你知道它可用:

我挑战你的前提,即Javascript没有做你想做的事。在我看来,JQuery是一个真正革命性的Javascript库,并且极大地简化了它。根据维基百科的说法,Jquery在10,000个访问量最大的网站中超过65%使用了#34;根据个人经验,尝试在我的网站上使用纯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做很多事情。当然,只需要一点学习曲线就可以找到你想要的东西。

答案 6 :(得分:0)

  

“有数十个网格/布局框架,其中大部分都集中在   传统的文档网格布局。“

你觉得这听起来很糟糕。我不明白你为什么不使用网格框架。如果您有任何意图使您的应用程序平板电脑和移动设备友好,这是相当标准的做法。他们中的大多数设置非常快,几乎不需要额外的CSS。

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

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

这种类型的步骤不会混淆模态或ifames。修改你需要做的就是更改类..需要更大的左手边,只需更改div的类

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

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

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

foundation也非常好,我用于项目的那个

答案 7 :(得分:0)

您可能需要查看Cascade Framework并使用this template作为布局的起点。

enter image description here

答案 8 :(得分:-1)

披露:我是OP,我想要得到一般回应。

  

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

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

在我看来,大多数理由在这种情况下无效(SPA):

从布局中分离内容 - 由于SPA不是真正的内容(它只是具有AJAX填充数据的骨架),因此该参数不适用。这只是一个界面,我不希望谷歌将其编入索引。

表格维护性较差 - 不是这种情况。你需要通过div来实现这个CSS的可维护性要低得多。

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

相关问题