Jump to content

Float with no breaks?


shadowayex

Recommended Posts

I have some divisions I want to have floating next to one another, but I want them to all stay in one line, even if the width of the container is reached.The idea is to have a horizontal set of divisions that can be scrolled through when the user wants to look at the rest of them.One solution was to use spans with the display set to inline-block (to allow height and width), but due to other things I'm doing, I cannot change the display property of whatever element I decide on.

Link to comment
Share on other sites

You could wrap the floated elements with a div that has a width equal to that of all elements combined... and an overflow:auto if you want a stand-along scrollbar.

Link to comment
Share on other sites

You could wrap the floated elements with a div that has a width equal to that of all elements combined... and an overflow:auto if you want a stand-along scrollbar.
A good idea, but implementing it will be tricky. The number of items can vary greatly, as users are allowed to add and remove items as desired.The more complex portion of it is that the scroll feature is not a simple one. It's put together using custom images as buttons and some JQuery. Groups of a certain (variable) number are shown at a time, and clicking the scroll buttons animates a scroll to the next group.I have a mix of this scrolling feature and JQuery UI Sortables for a widget-style experience. The aim is that there is a grid of widgets that the user can customize, and a bar above it of widgets the user can either get new ones from, or remove ones they have by placing them in the bar. This bar is the part in question, as I want the widgets to just continuous go side by side and allow the user to navigate through them via the scrolling system. I got the scrolling system to work via spans, but I need block elements for my specific goal.Edit: If you're wondering how I pulled it off with spans, I used the CSS white-space: nowrap feature, which doesn't seem to work with divs.
Link to comment
Share on other sites

I'd use spans and turn them into inline-blocks, then use the white-space property. There's no need for floating then.
That would have been fine, but the inline-block breaks the Sortable, as I discovered when I tried it =/Good suggestion nonetheless, though.
Link to comment
Share on other sites

That would have been fine, but the inline-block breaks the Sortable, as I discovered when I tried it =/Good suggestion nonetheless, though.
What is "Sortable?" Maybe there's some other way around this.
Link to comment
Share on other sites

What is "Sortable?" Maybe there's some other way around this.
Sortable is a JQuery UI feature that makes life a million times easier if you're looking for a nice drag and drop sorting feature.JQuery Sortable APIThe above link is a demo of it in action, along with some API documentation.Here is a fully functioning page that can demonstrate what happens when you change an element's display to inline-block. It uses some public minimalized JQuery and JQuery UI files from Google APIs, so you don't need to download anything.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html lang="en-US" xml:lang="en-US" xmlns="http://www.w3.org/1999/xhtml">	<head>		<title>Sortable Test</title>		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />		<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.0/jquery.min.js"></script>		<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.9/jquery-ui.min.js"></script>		<style type="text/css">			#sortable			{				list-style-type: none;				margin: 0;				padding: 0;				width: 60%;			}			#sortable li			{				margin: 0 3px 3px 3px;				padding: 0.4em;				padding-left: 1.5em;				font-size: 1.4em;				height: 18px;				/*display: inline-block;*/			}			#sortable li span			{				position: absolute;				margin-left: -1.3em;			}		</style>		<script type="text/javascript">			$(function() {				$( "#sortable" ).sortable();				$( "#sortable" ).disableSelection();			});		</script>	</head>	<body>		<div class="demo">			<ul id="sortable">				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 1</li>				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 2</li>				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 3</li>				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 4</li>				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 5</li>				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 6</li>				<li class="ui-state-default"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span>Item 7</li>			</ul>		</div>	</body></html>

This bug happens with any element, whether natively inline or block. This code was taken from the page above and formatted, with the only changes being that 1) I made it into a valid XHTML 1.0 page, and 2) I added a currently commented out display: inline-block. If you try it both commented and uncommented, you'll notice that changing the display cause the others to jump down a little while you're dragging them. With these list items, it's relatively small. But with my 230x230 divs, it's a larger, layout-breaking jump.I hope that is enough to figure out a solution, if one exists.

Link to comment
Share on other sites

I just added

			float:left;

to #sortable liand it seems to work as you wanted.I also uncommented the display inline-block with no apparent problem.the position absolute in "#sortable li span" scares me though. Other than apparently adding some left margin it does not seem to affect the placement of the sorted elements.as for making sure they all stay in one line, I would just define an arbitrary maximum value to the outer container

<div class="demo">

if 1000 is the max width of all elements then use that. A scroll bar will always be visible in the browser even if there is no "stuff" outside the margins but that is a minor drawback.I am using Google Chrome. Similar results in Opera and Safari . . . Perhaps your browser behaves differently. Or perhaps I do not understand the problem.Curious: why is sortable limited to 60%?

Link to comment
Share on other sites

Your problem with float seems to me to be the same as mine, even if the application is very different. The fundamental behaviour of float.I started a thread just a few hours before you about it here. As far as I've been able to determine there's no way to prevent float from breaking into rows. It's like that by design.But as I played with my floats I also considered your problem and had an idea for you. I'm a newbie to web stuff and haven't gotten as far as jQuery, so I hope I understand your situation enough that this isn't completely unapplicable. Since you're already using scripting it shouldn't be a problem to implement.Instead of using float:left, which never spawns a horiz scroll, you could "fake" the float by dynamically positioning your objects (position:absolute) according to their order in the container (display:block; position:relative; overflow:auto) . This will only work with objects of the same width.Before you append the object to the container, set object[x].style.left = object_width_unit * container.childNodes.lengthTo see what I mean, this is my sandbox code I posted in my thread, trimmed down and modified to show this solution. The CreateNew function, the #container1 style, and .newdiv style are changed from the original.

<html><head><script type="text/javascript">function randcol(){	var color="";	for (i=0;i<6;i++){	color=color+Math.floor(Math.random()*16).toString(16);}	return color;	}function createNew(parent_name, new_type, new_typeText) {        var x = document.getElementById(parent_name);	var y = document.createElement(new_type);	y.appendChild(document.createElement('p'));	y.firstChild.className = 'spawntext';	y.firstChild.innerHTML = 'YAY! I has a '+new_typeText;	y.className = 'new'+new_type;	y.id = y.className + x.childNodes.length;	y.style.left = 100 * x.childNodes.length;	y.style.backgroundColor = randcol();	x.appendChild(y);	}	function clearNew(parent_name, new_type) {	var x=document.getElementById(parent_name);        var y=x.getElementsByTagName(new_type);	var lastdiv=y.length-1;	if (lastdiv >= 0){		var z=x.getElementsByTagName(new_type)[lastdiv];		x.removeChild(z);		};	}function clearAll(parent_name) {	var x=document.getElementById(parent_name);        x.innerHTML="";	}</script><!--============================--><style type="text/css">body {	width:100%;	margin:0;	padding:0;	font-family:"Arial Verdana", Arial, sans-serif;	font-size:100%;}div {	box-sizing:border-box;	-moz-box-sizing:border-box;	-webkit-box-sizing:border-box;}#settings {	float:left;	background:#f88;	border:3px solid red;	padding: 0.5em 0.5em 0em 0.5em;	max-width:20%;	min-height:100%;	margin-bottom:0;}#settings select {	width:100px;}#controls {	display:inline-block;	background:#8f8;	border:3px solid green;	padding: 0em;	width:440px;}#controls button {	width:30%;	margin:1%;	height:3em;	vertical-align:middle;}#container1 {	position:relative;	display:block;	overflow:auto;	max-width:425;	height:117;	background:#ddd;}.newdiv {position:absolute;	width:96px;	height:96px;	background:#86f;	border:2px solid blue;	margin:3px;}	.spawntext {	padding:0em 0.8em;	vertical-align:middle;	font-weight:700;	text-align:center;	color:white;}</style></head><!--===========================--><body><div id="settings"><form id="myform" name="settingsPanel">Display:<br/><select name="input_styleDisplay" onChange="document.getElementById('container1').style.display =	document.settingsPanel.input_styleDisplay.options[document.settingsPanel.input_styleDisplay.selectedIndex].value"> 	<option value="inline">inline</option>	<option value="block" selected="selected">block</option>	<option value="inline-block">inline-block</option>	<option value="inline-table">inline-table</option>	<option value="list-item">list-item</option>	<option value="run-in">run-in</option>	<option value="table">table</option></select> <br/>Overflow:<br/><select name="input_styleOverflow" onChange="document.getElementById('container1').style.overflow =	document.settingsPanel.input_styleOverflow.options[document.settingsPanel.input_styleOverflow.selectedIndex].value"> 	<option value="visible">visible</option>	<option value="hidden">hidden</option>	<option value="scroll">scroll</option>	<option value="auto" selected="selected">auto</option></select> <br/>White-space:<br/><select name="styleWhitespace" onChange="setProperty('container1', 'settingsPanel', 'styleWhitespace', 'whiteSpace')">	<option value="normal" selected="selected">normal</option>	<option value="nowrap">nowrap</option>	<option value="pre">pre</option></select> <br/>Float:<br/><select id="myfloat" name="style_Float" onChange="document.getElementById('container1').style.float =	document.settingsPanel.input_styleFloat.options[document.settingsPanel.input_styleFloat.selectedIndex].value">	<option value="none" selected="selected">none</option>	<option value="left">left</option>	<option value="right">right</option></select> </form></div><div id="controls"><button type="button" onclick="createNew('container1','div','box'); return false">I want more boxes!</button><button type="button" onclick="clearNew('container1','div'); return false">I don't like that one</button><button type="button" onclick="clearAll('container1'); return false">Too many. Take them away!</button></div><br/><div style="height:117;background:#def"><div id="container1"></div></div><br/></body></html>

There is one hassle. When you remove an object from the container, you must adjust the absolute left position of all the objects to the right of it, or you'll be left with a gap. The browser does this automatically for floats, but now it's up to you. Although if you can use this idea in your code then there shouldn't be a reason you can't go through the objects to adjust them.I hope that's helpful. GL.

Link to comment
Share on other sites

I ended up changing the design to avoid this problem. But I'll still try to work it out just in case.The above code I posted was not mine, but the example code. I could post my code, but it's a mess of HTML, PHP, and loops, and as such would be decently difficult to work through.The premise of the problem is that when you set a float on an object to make them go next to each other, if your row gets longer than the width of the container, it goes down to the next line. The only way I can see around this to create a wrapper between the container and the elements, set it's width to be a width that will be wide enough for all of the objects.The problem with that solution is that, because of the use of the Sortable (demoed above), the width that the wrapper would need to be is forever changing. So, here's a list of what one would need to in order to get this to work:Keep this structure in mind for my list:

<div id="container">	<div id="wrapper">		<div class="child"><p>content</p></div>	</div></div>

In the design, there could be a wide range of number of .child divs, changing by use of JavaScript/JQuery. In order to get such an effect as a row of .child's that could be scrolled through, either by the default scroll bar or (in my case) a custom scrolling control, you'll have to go through a little bit of work.#container will need a width set based on how much you want to be visible at a time, and overflow set to hidden (for custom scrolling) or auto (for default scrolling).#wrapper will need a width set based on how much content it available at load time. This could be a little trickier if you're using a system (like me) where the amount of default content varies on users and what content they have..child should be floated at the very least. In most cases, you'll probably want explicit heights and widths as well.Now, for the tricky part. Whenever something is added or removed, you'll need to resize #wrapper to compensate. For me, this was a little tougher, as I wanted things shown in groups of 3. This meant that if I had 7 spots, I still needed to leave the 8th and 9th spots. They would just need to be emptied. So, for me, I had to to a little extra detection, but I won't go into that just yet.You'll need to know (or be able to calculate) the horizontal space each .child takes. At addition of a .child, you need to add to the width of #wrapper the space that the new .child will take up. This should be done before you actually add the .child. You can do it after, but if you're using overflow: auto;, a vertical scroll bar will appear until you adjust the width, since the .child will be knocked down to the next line.On removal, you'll need to remove from #wrapper's width the space the removed.child took up. This should be done after the removal, but can technically be done before, with the same overflow: auto; disclaimer.If you're doing a custom scrolling that shows a certain amount at one time, and scrolls to the next group, you'll have to do a little detection. When adding, you need to detect if the amount you already have is a multiple of the amount you want to show at once. The mod operator (%) can help with this. If it is, you'll need to add the space that each .child takes up times the number you want shown at once. This assumes uniformity of the .child's. If they are not uniform, you'll have a really tough time getting this figured out.On removal, you'll need to do similar detection. If the new amount if a multiple of the amount you want shown, that means you'll now have an empty group. You'll just need to remove the extra width (the space each takes up times the amount shown at once).Another complication, for me, was that I wanted an empty group on the end at all times, because I was using a drag and drop API to add, remove, and sort, and I wanted to ensure at least one empty space at all times. So, for me, I had to detect if, upon addition, the amount of .child's had filled up every group, and then add width at that point. Of course, this meant there would always be enough space to add another, so I just had to move the detection code to be after addition instead of before. For removal, it was slightly more complex. If there was an empty group on the end, that meant that when one was removed, the empty group would have to go away, because a new slow was available. So, before removal, I would check if the number of .child's was a multiple of the number I showed at once. If so, I would remove the extra space along with the .child.With this post, I was really just looking for something to simplify the process. In specific, I wanted to avoid the whole #wrapper part altogether.This explanation got slightly less explicit as it went, as I assumed people would know what I meant be the end. If anyone needs any more clarity, let me know and I will go back and make edits.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...