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

tal*_*kol 6 html css layout frameworks single-page-application

经验法则 - 如果您在布局中过多地使用CSS,请切换到框架.我一直在浏览那里的几十个网格/布局框架,其中大部分都集中在传统的文档网格布局上.

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

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

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

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

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

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

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

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

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

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

    • 精确的固定像素大小.
    • 使用容器的百分比进行相对大小调整.例如:侧栏宽度是整个容器宽度的30%(整页或对话框).另一个例子:顶部菜单高度是容器整个高度的20%(整页或对话框).
    • 包裹自己的内容.示例:顶部菜单的高度取决于其中的内容.如果输入一行文本,它将包装它而不滚动.如果输入两行文本,它将是两倍大并且不滚动就保持它们.
    • 奖金:两个简单的组合.像侧边栏宽度为20%但不小于50像素.

正如Ian Clark最专业地指出的那样,CSS可以实现大部分开箱即用的请求.对此没有任何争论.问题仍然是原始CSS是否最简单易用,以及是否有任何可以通过框架/其他机制(如flexbox/tables)从开发人员卸载的内容.

Ian*_*ark 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
Run Code Online (Sandbox Code Playgroud)

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

@media(max-width:500px) {
  #scrolling-content { 
    left:100px;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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


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

我仍然不明白为什么使用简单的CSS很难实现你的目标position.您不需要使用任何JavaScript和.我认为这是非常易于管理的.如果您真的在努力维护样式表,那么为什么不使用像Sass/SCSS或Less这样的东西,因为您可以创建变量,混合,函数等,并显着减少您需要进行的更改次数.


也就是说,他是一个非常快速的解决方案模型,只使用纯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;
}
Run Code Online (Sandbox Code Playgroud)

很容易注意到菜单的重复40px和200px高度和宽度.考虑到这一点,您可以简单地使用动态语言的变量并仅定义它们一次(更少示例):

@leftwidth: 200px;

#scrolling-content {
    left:@leftwidth;
}
#menu, #longlist {
    width:@leftwidth;
}
Run Code Online (Sandbox Code Playgroud)

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

您提到很难轻松操作CSS框架,因为依赖于静态内容,他们必须根据要使用的列数做出决策(在Bootstrap和其他许多情况下,他们选择12,因为它很容易被1,2,3整除, 4,6).但是,在Bootstrap 2中,可以很容易地自定义列数.当Bootstrap 3 RC2出现时,预计此功能也会存在.还有许多资源允许您使用Less with Bootstrap.也就是说,创建一个Less-style灵活的流体网格系统是相当常规的,请参阅演示(免责声明:我没有使用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);
Run Code Online (Sandbox Code Playgroud)

然后你的HTML标记变成:

<div class="cf rows">
    <div class="dynamic-4-15">4/15th width</div>
    <div class="dynamic-7-15">7/15th width</div>
</div>
Run Code Online (Sandbox Code Playgroud)

争议#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;
}
Run Code Online (Sandbox Code Playgroud)