转换绝对布局以使用浮动

时间:2014-03-10 09:38:33

标签: javascript jquery html css css-float

我正在寻找关于我正在开展的项目的一些建议,并会感谢任何帮助。

目的:

制作拖放式CMS,允许用户在网格上绘制元素并将其移动到所需位置。更改以JSON格式记录,并在用户按下发布按钮时转换为HTML / CSS。生成的HTML应该是干净和灵活的(即适应高度/长度不同的内容)。 该系统应该能够处理创建电子商务站点以及简单的信息站点。

问题:

在HTML中实现拖放系统的合理方法是使用absolute定位widthheight s;这种方法不适合完成的网站,因为内容可能是可变长度的,并且绝对定位的元素从文档流中取出,它们不知道它们周围的元素。

解决方案:

创建一个系统,将绝对定位的元素转换为浮动元素。

实施例

在CMS系统中,用户通过在网格上绘制框来创建以下布局:

  1. 固定高度的标题
  2. 可变高度的导航
  3. 固定高度的图像
  4. 可变高度页面的主要内容
  5. 可变高度的访问项目列表
  6. 固定高度的页脚
  7. 绝对布局:

    Absolute layout

    HTML / CSS将是这样的:

    body {
        background-color: #999999;
        font-family: verdana, arial, helvetica, sans-serif;
        font-size: 70%;
        margin: 15px 0;
        padding: 0;
    }
    #mainContainer {
        background-color: #FFFFFF;
        height: 500px;
        margin: 0 auto;
        position: relative;
        width: 916px;
    }
    .contentBlock {
        border: 1px solid orange;
        box-sizing: border-box;
        color: orange;
        font-size: 2em;
        text-align: center;
    }
    .contentBlock:after {
        content: "";
        display: inline-block;
        height: 100%;
        vertical-align: middle;
    }
    #contentBlock1 {
        height: 120px;
        left: 0;
        position: absolute;
        top: 0;
        width: 916px;
    }
    #contentBlock2 {
        height: 100px;
        left: 0;
        position: absolute;
        top: 140px;
        width: 136px;
    }
    #contentBlock3 {
        height: 100px;
        left: 0;
        position: absolute;
        top: 260px;
        width: 136px;
    }
    #contentBlock4 {
        height: 220px;
        left: 156px;
        position: absolute;
        top: 140px;
        width: 604px;
    }
    #contentBlock5 {
        height: 220px;
        left: 780px;
        position: absolute;
        top: 140px;
        width: 136px;
    }
    #contentBlock6 {
        height: 120px;
        left: 0;
        position: absolute;
        top: 380px;
        width: 916px;
    }
    <div id="mainContainer">
        <div class="contentBlock" id="contentBlock1">1</div>
        <div class="contentBlock" id="contentBlock2">2</div>
        <div class="contentBlock" id="contentBlock3">3</div>
        <div class="contentBlock" id="contentBlock4">4</div>
        <div class="contentBlock" id="contentBlock5">5</div>
        <div class="contentBlock" id="contentBlock6">6</div>
    </div>

    用户现在点击发布按钮,布局将转换为使用float而不是absolute定位。生成的HTML不能使用absolute定位,因为如果2或4中的内容扩展,它们将超过/低于3和6. Float s将元素保留在流中并相互了解所以以下内容将迎合2和4中的动态内容:

    浮动布局:

    Floated layout

    HTML / CSS将是这样的:

    body {
        background-color: #999999;
        font-family: verdana, arial, helvetica, sans-serif;
        font-size: 70%;
        margin: 15px 0;
        padding: 0;
    }
    #mainContainer {
        background-color: #FFFFFF;
        margin: 0 auto;
        width: 916px;
    }
    .contentBlock {
        border: 1px solid orange;
        box-sizing: border-box;
        color: orange;
        font-size: 2em;
        text-align: center;
    }
    .contentBlock:after {
        content: "";
        display: inline-block;
        height: 100%;
        vertical-align: middle;
    }
    #contentBlock1 {
        margin-bottom: 20px;
        height: 120px;
    }
    #contentBlock2 {
        height: 100px;
        margin-bottom: 20px;
        width: 136px;
    }
    #contentBlock3 {
        height: 100px;
        margin-bottom: 20px;
        width: 136px;
    }
    #contentBlock4 {
        float: left;
        height: 220px;
        margin-bottom: 20px;
        margin-left: 20px;
        width: 604px;
    }
    #contentBlock5 {
        float: left;
        height: 220px;
        margin-bottom: 20px;
        margin-left: 20px;
        width: 136px;
    }
    #contentBlock6 {
        clear: left;
        height: 120px;
    }
    #contentContainer1 {
        float: left;
        width: 136px;
    }
    <div id="mainContainer">
        <div class="contentBlock" id="contentBlock1">1</div>
        <div id="contentContainer1">
            <div class="contentBlock" id="contentBlock2">2</div>
            <div class="contentBlock" id="contentBlock3">3</div>
        </div>
        <div class="contentBlock" id="contentBlock4">4</div>
        <div class="contentBlock" id="contentBlock5">5</div>
        <div class="contentBlock" id="contentBlock6">6</div>
    </div>

    用户无法理解浮动元素的工作原理,因此在发布更改时,此过程需要自动完成。

    这个特殊的例子很简单,虽然也需要处理更高级的布局。

    其他CMS系统的功能:

    据我所知,大多数CMS系统要么将用户修复为设置模板,要么使用JavaScript构建页面来设置绝对定位元素的高度/位置(我想避免)。

    我的问题:

    • 是否可以设计一组规则来将绝对布局转换为浮动布局?
    • 若有,那么现有的CMS是否可以做到这一点?
    • 有关解决此问题的其他方法的任何建议吗?

    感谢。

7 个答案:

答案 0 :(得分:6)

首先:我认为将绝对布局“转换”为浮动是最好的方法。您应该从一开始就考虑浮动,并提示/教导用户相应地构建布局。

第二:我相信您要构建的工具需要用户了解如何使用它。这说明你想让不熟悉HTML / CSS概念的人能够使用它。因此,您需要将此工具的使用基于简单且易于理解的概念,用户可以使用这些概念构建“外观”并生成其背后的代码。

我能想到的是:

  • 块/容器
  • 高度/宽度
  • 缘/填充

现在使用这些概念,您可以让用户创建具有属性的块:内容宽度/高度边距/填充的列数。然后,用户可以使用这些属性无限地嵌套块,并将内容拖放到其中。

以下是它如何适用于您的示例:

标题:

用户创建一个块并为其提供以下属性:

  • 宽度:100%
  • 高度:80px(这可以通过拖动元素边框来完成)
  • 第2列(一个用于徽标,一个用于菜单)

主要:

用户使用以下属性在标题下创建一个新块:

  • 宽度:100%
  • 身高:自适应
  • 列数:3(第1列和第3列:宽度为15%,第2列为70%)

<强>页脚

与标题具有相同属性的新块。

然后可以在每个块/列中重新开始使用,并且可以嵌套具有相同属性的新的

生成代码:

您知道每个块的列数及其宽度,因此您可以轻松地为每个块创建一个div,并使用浮动/宽度将它们并排放置。对于高度:用户可以设置固定的高度,并且他不难理解内容可能溢出。所以如果他不想要他必须选择“自适应”高度( css 中的height : auto;)。

结论:

这是一个非常一般的想法和简单的概念。主要工作将是UI设计以及您将提示/教导用户使用您的工具构建布局的方式。请记住您的辞职人员以及他们在不同情况下的反应。使用您最好的UI技能来提示/教导正确使用方法。

答案 1 :(得分:4)

有一个名为Weebly的网站创建工具,它具有您正在寻找的相同功能。它是免费的,因此您可以查看有关其功能的更多信息。

你要求的内容真的很模糊,所以我将答案分成几个部分:

1-对于拖放功能:

这正是您所寻找的:Gridster

您可以让用户调整框大小,同时保持约束。

2-如果您正在寻找一个干净的CSS框架:

3-如果您正在寻找覆盖整个页面(垂直和水平)的流畅布局:

&#13;
&#13;
html,
body {height:100%; margin:0px; padding:0px;}
.wrapper {position:relative; height:100%; width:100%; display:block;}
.header {position:relative; height:22%; width:100%; display:inline-block; margin-bottom:3%; background:red;}
.footer {position:relative; height:22%; width:100%; display:inline-block; margin-top:3%; background:green;}
.content {position:relative; height:50%; width:100%; display:inline-block;}
.content .left_sidebar {float:left; width:17%; height:100%; position:relative; margin-right:3%; background:yellow;}
.content .right_sidebar {float:right; width:17%; height:100%; position:relative; margin-left:3%; background:purple;}
.content .middle {float:left; width:60%; height:100%; position:relative; background:cyan;}

/**
 * @info Clearfix: clear all the floated elements
 */
.clearfix:after {visibility:hidden; display:block; font-size:0; content:" "; clear:both; height:0;}
.clearfix {display:inline-table;}
	
/**
 * @hack Display the Clearfix as a block element
 * @hackfor Every browser except IE for Macintosh
 */
   /* Hides from IE-mac \*/
   * html .clearfix {height:1%;}
   .clearfix {display:block;}
   /* End hide from IE-mac */
&#13;
<div class="wrapper">
    <div class="header">Header</div>
    <div class="content">
        <div class="left_sidebar">Left Sidebar</div>
        <div class="middle">Middle</div>
        <div class="right_sidebar">Right Sidebar</div>
        <div class="clearfix"></div>
    </div>
    <div class="footer">Footer</div>
</div>
&#13;
&#13;
&#13;

请注意,这样做会破坏移动设备上的用户体验。

答案 2 :(得分:4)

  

是否可以设计一组规则来将绝对布局转换为浮动布局?

并非不可能,但实施起来非常困难。

  

如果是,那么现有的CMS是否可以做到这一点?

不是我知道的。

  

有关解决此问题的其他方法的任何建议吗?

我发现更容易将布局视为一堆行和列,适当地浮动。所以,对于这种布局:

Absolute layout

我会生成类似于此的HTML标记(为了理解而简化):

<div class="box">Content 1</div>
<div class="row">
    <div class="col">
        <div class="box">Content 2</div>
        <div class="box">Content 3</div>
    </div>
    <div class="col">
        <div class="box">Content 4</div>
    </div>
    <div class="col">
        <div class="box">Content 5</div>
    </div>
</div>
<div class="box">Content 6</div>

您需要提供用户可以使用的UI:

  1. 添加内容
  2. 添加列包装器
  3. 在列包装器中添加列
  4. 然后,您可以命名行,列和/或内容元素,并使用CSS调整其宽度。这是一个概念验证:

    &#13;
    &#13;
    $(function() {
        $(".insertable").draggable({ revert: "invalid" });
        $(".insertzone").droppable({ activeClass: "acceptable", drop: handleInsert, accept: ".insertable-box, .insertable-row" });
        $(".removezone").droppable({ activeClass: "acceptable", drop: handleRemove, accept: ".removable" });
        function handleInsert(event, ui) {
            ui.draggable.css({ left: 0, top: 0 });
            var $div = $("<div class='removable'></div>").appendTo(this).draggable({ revert: "invalid" });
            if (ui.draggable.hasClass("insertable-box")) {
                $div.addClass("box").text("Lorem ipsum dolor sit amet.");
            }
            if (ui.draggable.hasClass("insertable-row")) {
                $div.addClass("row").droppable({ activeClass: "acceptable", drop: handleInsert, greedy: true, accept: ".insertable-col" }); ;
            }
            if (ui.draggable.hasClass("insertable-col")) {
                $div.addClass("col").addClass(ui.draggable.find("select").val()).droppable({ activeClass: "acceptable", drop: handleInsert, greedy: true, accept: ".insertable-box, .insertable-row" });
            }
        }
        function handleRemove(event, ui) {
            ui.draggable.remove();
        }
    });
    &#13;
    /* INTERFACE */
    body { font: medium/1 monospace; }
    select { font: inherit; margin: -1em 0; border: 0; padding: 0; }
    .insertzone { margin: 1em 0; box-shadow: 0 0 .25em #CCC; }
    .removezone { margin: 1em 0; box-shadow: 0 0 .25em #CCC; }
    .insertable { cursor: move; display: inline-block; padding: 1em 4em; background-color: #CCC; }
    .removable { cursor: move; }
    .acceptable { background-color: #FEA !important; }
    .insertzone .box { background-color: #EFD; }
    .insertzone .row { background-color: #FEE; }
    .insertzone .col { background-color: #FFD; }
    .insertzone .box:after { display: block; padding: 1em; text-align: center; content: "box"; color: #CCC; margin-bottom: -1em; }
    .insertzone .row:after { display: block; padding: 1em; text-align: center; content: "row"; color: #CCC; }
    .insertzone .col:after { display: block; padding: 1em; text-align: center; content: "col"; color: #CCC; min-width: 8em; }
    .insertzone:after { display: block; padding: 1em; text-align: center; content: "Drag here to insert"; }
    .removezone:after { display: block; padding: 1em; text-align: center; content: "Drag here to remove"; }
    /* LAYOUT */
    .box { margin: 1em 0; padding: 1em; }
    .row { margin: 1em 0; }
    .row:after { display: block; clear: both; content: ""; }
    .col { float: left; }
    .col > * { margin-left: .5em; margin-right: .5em; }
    .col:first-child > * { margin-left: 0; }
    .col:last-child > * { margin-right: 0; }
    .col > *:first-child { margin-top: 0; }
    .col > *:last-child { margin-bottom: 0; }
    .col-10 { width: 10%; }
    .col-20 { width: 20%; }
    .col-30 { width: 30%; }
    .col-40 { width: 40%; }
    .col-50 { width: 50%; }
    .col-60 { width: 60%; }
    .col-70 { width: 70%; }
    .col-80 { width: 80%; }
    .col-90 { width: 90%; }
    &#13;
    <link rel="stylesheet" href="//code.jquery.com/ui/1.9.2/themes/smoothness/jquery-ui.css">
    <script src="//code.jquery.com/jquery-1.9.1.min.js"></script>
    <script src="//code.jquery.com/ui/1.9.2/jquery-ui.min.js"></script>
    
    <div class="insertzone"></div>
    <div class="removezone"></div>
    <div>
        <div class="insertable insertable-box">box</div>
        <div class="insertable insertable-row">row</div>
        <div class="insertable insertable-col">col
            <select>
                <option value="col-10">10%</option>
                <option value="col-20">20%</option>
                <option value="col-30">30%</option>
                <option value="col-40">40%</option>
                <option value="col-50" selected>50%</option>
                <option value="col-60">60%</option>
                <option value="col-70">70%</option>
                <option value="col-80">80%</option>
                <option value="col-90">90%</option>
            </select>
        </div>
    </div>
    &#13;
    &#13;
    &#13;

    这是您使用此工具设计的布局:

答案 3 :(得分:3)

这就是我想要设计一个自动化的系统:
(主要是伪代码)

  1. 获取用户在其屏幕上可视化的window.widthwindow.height
  2. 使用简单的公式计算每个元素的百分比:

    var elWidth =(element.width / window.width)* 100
    var elHeight =(element.height / window.height)* 100

  3. 将每个不是100%宽度的元素表现得像具有
    的内联元素 display:inline-block;
  4. 这应该是一个很好的基础,只要您设计了一个良好的UI来派生每个嵌套的DIV和一种“磁性”网格来对齐项目。

    您怎么看?

答案 4 :(得分:3)

从绝对定位转换为浮动定位的问题是,您将花费大量精力在可能无法很好转化的事物上。从一开始就让元素使用浮动不是更好吗?

我知道你不希望用户必须理解浮动,但想想图像在Microsoft Word中的工作方式 - 用户将图像拖动到他们想要的位置,然后可以设置文本环绕它的方式。这与浮动元素没有什么不同,并且会比那些尚未经历翻译过程的内容更准确地呈现最终结果,而翻译过程可能会或可能不会100%起作用。

示例:

将元素拖到页面上,它占用100%的宽度。将另一个元素拖到页面上,它位于第一个元素下面并占用相同的元素。然后,您可以更改两个元素的“换行”样式,使它们向左浮动,页面更新以准确显示用户最终会得到什么。您在超灵活定位中牺牲了什么,为您提供更好的用户体验。

<强>结论

听起来您通过决定绝对定位是唯一足够灵活的解决方案来预测您的用户需求 - 我的建议是:不构建您的用户没有要求的功能。给他们一个你可以构建的拖放UI,然后如果他们要求更多的功能,那就搞清楚吧。他们可能永远不会问,你会让自己头疼。

答案 5 :(得分:3)

  1. 看一下网格(不是数据网格)框架,有很多好主意,也许你可以使用其中一些没有任何定制。
  2. 再次考虑绝对定位用户的输入,但我认为它不适合CMS。

答案 6 :(得分:3)

我认为你应该小心:听起来你正试图建立一个所见即所得的界面,使用绝对定位和大小,最终变成一种不是所见即所得的东西;可变宽度和定位取决于屏幕尺寸。

您遇到了现代响应式设计的一个基本问题;网站不再是所见即所得了。几乎不可能传达设计精良的移动网站在单个图像中看到的所有不同方式。

您的用户必须遵守设计师对移动设计的相同限制,因为元素必须在屏幕尺寸之间优雅地流动。这通常意味着将内容约束到网格或单个平面(即列或行),或设计两次;一次用于移动,一次用于桌面。

话虽这么说,我见过的少数网格系统中有一个与绝对定位和大小的元素一起工作的是Masonry Grid。它需要任何大小的元素,并尽可能地将它们组合在一起,而不会破坏页面的流动。它经常出现在杂志或投资组合网站中,其中长篇形式的书面内容很少见。

通过一个体面的规则系统和创建负空间的特殊元素(即全宽分隔线,空白块,全高边栏),您可以为用户提供创建重新排列自身网站的工具很好地使用Masonry Grid来做所有事情。