chosen
chosen copied to clipboard
Chosen gets "cut" when placed in area with "overflow:hidden".
I have a div with a form. The div has "overflow:hidden" option in the css. When Chosen gets created, and it goes below the bottom line of the div, it gets cut.
Here is a screenshot:
This is the same as issue #59
Isn't this unavoidable since the container element, is well, "overflow :hidden" that's just how CSS works. The only way around this is to render the drop down outside of the container and then use absolute positioning.
Yeah, I agree with dfischer. Doesn't seem like a Chosen issue. By definition, the overflow property specifies what happens if content overflows an element's boundaries. If you don't want it the overflow to be hidden, then change that property.
While true, I think this is a common use case with dialog boxes. (Especially jquery dialog)
It is a common use case, however based on this ticket, like I previously mentioned... the entire structure and implementation has to change if you want to accomplish this.
You are required to render outside of the container for this to happen and then use jQuery/JS magic to figure out the positioning relative to the trigger.
jQuery Dialog's case doesn't depend upon a container element so it just uses positioning based on center dimensions and width of the dialog.
This is more of a CSS issue, not a Chosen issue. Don't put overflow: hidden on the container. You're going to have to use another technique to clear the floats below it if that's what you're doing.
I just wrote some code which I think does what you're looking for:
$.fn.extend({ chosen: function (data, options) { if ($(this).parent().css("overflow") == "hidden") { //get the offsets between parent and child to calculate the diff //when we push to absolute var y = $(this).offset().top - $(this).parent().offset().top, x = $(this).offset().left - $(this).parent().offset().left, $t1 = $("<div/>", { css: { "position": "relative", "height": $(this).parent().height, "width": $(this).parent().width } }), $t2 = $("<div/>", { css: { "position": "absolute", "top": y, "left": x } }); $t1.insertBefore($(this).parent()); $(this).parent().appendTo($t1); $t2.appendTo($t1); $(this).appendTo($t2); } return $(this).each(function (input_field) { if (!($(this)).hasClass("chzn-done")) { return new Chosen(this, data, options); } }); } });
(btw I'm new to github as of today so if there is a different place where I should be posting code let me know)
That code effectively does the following:
- calculate the offset between the select box and the parent.
- create a parent div with the same dimensions as your overflow hidden and set to relative.
- create a parent for the select box creating the element as absolute using the x and y offsets from step 1.
- insert new parent before the select's parent, append the overflow div inside of the new parent, append that new select parent inside of the master parent, append the select to the new child parent.
Interesting idea Matthew, but I think that's not going to work in a jQuery-UI dialog is it?
It's more likely that the dropdown element (.chzn-drop) needs to be pulled out of the .chzn-container and up to the document body...
Just add a style to the page and your answer is yes:
.ui-dialog{ overflow:visible; }
Doesn't work for me, since I create my pages using div's as columns (as opposed to td's and tables). I use "overflow:hidden" to stop runaway content from ruining neighbour divs.
I suppose many of you use the same structure.
That won't work, as the dialogs are set to overflow:auto so they can have scrollbars if necessary.
On Fri, Jul 29, 2011 at 11:47 PM, ethaniel [email protected] wrote:
Doesn't work for me, since I create my pages using div's as columns (as opposed to td's and tables). I use "overflow:hidden" to stop runaway content from ruining neighbour divs.
I suppose many of you use the same structure.
Reply to this email directly or view it on GitHub: https://github.com/harvesthq/chosen/issues/86#issuecomment-1681303
Before we get any further into this conversation, what I've done is a theoretical fix. It can't be applied to all scenarios because all it takes is one element having a counter-attribute to screw it up. The above solution with the overflow visible will only work with dialog option resizable:false. Why would you need to have a select overflow outside of a dialog?
Ok, here are a bunch of screenshots which hopefully clarify the issue.
http://i.imgur.com/9ZY9O.png http://i.imgur.com/c2PLo.png http://i.imgur.com/1oqZ7.png http://i.imgur.com/ZBrQj.png
Screenshots 1 & 2 show how it behaves, there isn't enough space for the dropdown "inside" the dialog, so it scrolls and is hidden as a result. This is very clunky to use and ugly and not how the built in select controls work (they show over the top of the content, no matter how deep inside it they are or what it's overflow style is.)
Screenshots 3 & 4 show my current work-around, which is to put a whole heap of space below the dropdown. This is also ugly and makes the form harder to use.
So, to summarise, the real point is that native select controls aren't restricted to their parent container and if it's possible, the chosen enhanced select control shouldn't be either, since it's designed to be a drop-in replacement for the native control.
This theoretically can be done but it would require a completely different construction/positioning system by the chosen plugin. This change would be extensive and require about a 30% rewrite of the current plugin. I consider this a feature request and not a bug. All browsers have a default render for select elements.Chosen replicates it using divs but is not treated like a select element.
Like I said, the only way to do this is absolute positioning OUTSIDE of the triggered element. There's no other way. Correct on @medelbrock
While it would be very nice to have chosen behave like a browser widget, I agree this should be considered a feature not a bug. Can we currently set a max height?
@veloper: I gave that a go (as best I could) and it didn't seem to help. I can't see how it would work either, as the div.chzn-drop
is still contained in the dialog, so will be clipped regardless of whether it is absolutely positioned or not.
The only way to stop that is going to be to pull the div.chzn-drop
out of the dialog and make it a child of <body>
, but as everyone is pointing out, that is a bigger change than anyone is willing to get their hands dirty trying.
Unfortunately using overflow:visible
isn't an option, the dialog needs to be scrollable if necessary.
I think I've solved the issue by setting the drop down position to absolute and whenever showing the drop down setting it's position. e.g. Changing (editing the javascript)
this.dropdown.css({
"top": dd_top + "px",
"left": 0
});
to
var parent = this.dropdown.parent();
var offset = parent.offset();
dd_top = offset.top + parent.outerHeight();
dd_width = parent.width();
this.dropdown.css({
"top": dd_top + "px",
"left": offset.left,
"width": dd_width + "px"
});
I'm running into this problem myself while trying to make Chosen work inside a Wijmo / jQuery UI Dialog. I may be way out of my league here, but isn't there a fairly simple fix of making the "dropdown" portion have "display: none" while hidden, and then "display: block" when shown? You'd still incur the scroll bars when the dropdown is open, but that's probably better than having the scroll bars always present.
The fix (tested in Chrome 13, Firefox 7 and IE 9) :
In chosen.css:
.chzn-container .chzn-drop { position: fixed; }
and in Chosen.prototype.results_show
var offset = this.container.offset(); this.dropdown.css({ "top": (offset.top+dd_top) + "px", "left": offset.left + "px", "display": "block" });
http://img30.imageshack.us/img30/4094/chosen3.png
That's the stuff, good thinking @levushka. Resolved now in my branch: https://github.com/tompaton/chosen/commit/fda07051161f3fffe6049362b6c9b66ffbe857d1
Ok, it's a little more complicated than that. The above fix didn't work if the page was scrolled.
I've updated my repo with a changeset that sort of fixes it, the dropdown is positioned correctly now, but if the page is scrolled while the dropdown is visible it doesn't move as expected. That's annoying, but not a show stopper.
iOS 5 might solve this, but iOS currently doesn't support position: fixed in the same way that desktop browsers do. Chosen works terrifically on the desktop, but this might limit its uses on poorly designed mobile browsers...
I'm not just picking on Apple here, older version of Android also lack support for position: fixed.
As of jQuery 1.7 (not yet released, but in release candidate) they have a built-in test for CSS Position Fixed support: http://bugs.jquery.com/ticket/6809
Might be worth detecting jQuery 1.7 and using their result, or copying their code and getting a separate result otherwise.
+1 for position at the end of body element.
check the jquery widget "autocomplete". pretty good solution for that problem:
http://jqueryui.com/demos/autocomplete/
great plugin by the way.
I had this issue mostly in webkit browsers. IE just goes mental with chosen, so i disabled it if ie. Using jquery, i check if the browser is a webkit one, and adjust the overflow of the div containing my chosens like so:
if($.browser.webkit) $(this).css("overflow",($(this).is(":visible"))?"visible":"hidden");
where this is the div containing the chosens.
+1 @levushka and @tompaton Not perfect, but good enough-ish. Barely :)
@levushka solution is great, but it is global ... so at window.top when you scroll down and click to chosen, it roll down in wrong position. So here is solutuion for normal pages and popup windows
in Chosen.prototype.results_show
replace:
this.dropdown.css({
"top": dd_top + "px",
"left": 0
});
with:
if($('.popup').length!=0) {
var offset = this.container.offset();
this.dropdown.css({
"top": (offset.top+dd_top) + "px",
"left": offset.left + "px",
"display": "block"
});
} else {
this.dropdown.css({
"top": dd_top + "px",
"left": 0
});
}
CSS:
.popup .chzn-container .chzn-drop { position:fixed; }
If you are using jQuery UI or something else, you can have problems with z-index, so set chosen z-index to higher values (jQuery UI is it 1010+)
Now it is wokring in FF and for Chrome you need:
.popup { overflow-x:visible; overflow-y:visible; }
lover elements can have overlow:hidden with no problems.
Why not render the dropdown in the body and use Jquery UI's position function to position the box? http://jqueryui.com/demos/position/. This is the standard method used for many jquery ui widgets.
$( ".czn-drop" ).position({ of: $( "#container" ), my: "left top", at: "left bottom", });