I’m looking for some advice on a project I am working on and would be appreciative of any assistance.
To make a drag and drop CMS which allows a user to d
I think you should be careful: from what it sounds like you are trying to build a WYSIWYG interface using absolute positioning and size that turns into something that is not WYSIWYG in the end; variable widths and positioning depending on screen size.
You have come across one of the fundamental problems of modern responsive design; websites aren't WYSIWYG anymore. Its virtually impossible to convey all the different ways a well designed mobile site will look in a single image.
Your users will have to conform to the same constraints that designers have with mobile design, in that elements have to flow gracefully between screen sizes. This usually means constraining content to a grid or a single plane (ie columns or rows), or designing twice; once for mobile, once for desktop.
That being said, one of the few grid systems i have seen that works with absolutely positioned and sized elements is the Masonry Grid. It takes elements of any size and tries to fit them together as best it can without breaking the flow of the page. It's often seen used in magazine or portfolio sites where long form written content is rare.
With a decent rules system and special elements that create negative space (ie. full width dividers, 'empty' blocks, full height sidebars) you could give your users the tools to create a site that rearranges itself pretty well using Masonry Grid for everything.
First : I don't think "converting" an absolute layout to float is the best approach. You should think floats from the beginning and hint/teach the user to build the layout accordingly.
Second : I believe the tool you want to build will need the users to learn how to use it. This said you want to make it simple enough for people not familiar with HTML/CSS concepts to be able to use it. So you need to base the use of this tool on simple and understandable concepts that users can use to build the "look" and you to generate the code behind it.
Ones I can think of are :
Now using these concepts you could enable the user to create blocks with properties : number of columns for the content width/height margin/padding. The user can then nest blocks indefinitly with these properties and drag-drop content inside them.
Here is how it could work for your example :
Header :
The user creates a block and gives it these properties :
Main :
The user creates a new block under the header with these properties :
Footer
New block with same properties as the header.
The use can then start again inside each block/column and can nest new ones with the same properties
Generating the code :
You know the number of columns of each block and their widths so you can easily create a div for each and use floats/width to position them side by side. For the heights : the user can set a fixed height and it won't be difficult for him to understand that the content can overflow. So if he doesn't want that he must select the "adaptive" height (height : auto;
in css).
Conclusion :
This is a very general idea and simple concept. The main work will be on the UI design and the way you will hint/teach the user to build layouts with your tool. Keep in mind who you are disigning for and how they would react in different situations. Use your best UI skills to hint/teach the use in the right direction.
The issue with converting from absolute positioning to floated is that you'll expend a lot of effort on something that probably won't translate well. Wouldn't it be better to have the elements use floating from the start?
I know you don't want users to have to understand floating, but think about the way images work in Microsoft Word - the user drags the image to where they want it, and can then set how text wraps around it. This is not so different from floating elements, and will more accurately present the end result than something that has yet to go through a translation process that may or may not work 100%.
Example:
Drag an element onto the page, it takes up 100% width. Drag another element onto the page, it sits under the first and takes up the same. You then change the "wrap" style of both elements so they float left, and the page updates to show exactly what the user will get at the end. What you sacrifice in super flexible positioning, you make up for in a better user experience.
Conclusion
It sounds like you're anticipating your users needs by deciding that absolute positioning is the only solution flexible enough - my advice is: don't build features your users haven't asked for. Give them a drag and drop UI that you CAN build, and then if they ask for more features, figure it out then. They might never ask, and you'll save yourself a headache.
There's a website creator tool called Weebly that has the same functionality you're looking for. It's free of charge, so you can have a look to learn more about its features.
What you're asking for is really vague, so I divided the answers into several parts:
1- For the Drag-and-Drop feature:
This is exactly what you're looking for: Gridster
You can let the user resize the boxes while keeping constraints.
2- If you're looking for a clean CSS Framework:
3- If you're looking for a fluid layout which covers the whole page (vertically and horizontally):
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 */
<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>
Keep in mind that doing so will destroy the user experience on mobile devices.
Is it possible to devise a set of rules to convert an absolute layout to a floated one?
Not impossible but extremely difficult to implement.
If so are there any existing CMS that do it?
Not that I am aware of.
Any suggestions on other ways to tackle this issue?
I find it easier to think of layouts as a bunch of rows and columns, floated appropriately. So, for this layout:
I would generate HTML markup similar to this (simplified for understanding):
<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>
You will need to provide a UI where a user can:
You can then name the rows, columns and/or content elements and use CSS to adjust their widths. Here is a proof-of-concept:
$(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();
}
});
/* 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%; }
<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>
And here is your layout, designed using this tool: