CSS properties that take the element out of layout flow.

HTML, CSS and anything else that deals with client side capabilities.

Moderator: General Moderators

Post Reply
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

CSS properties that take the element out of layout flow.

Post by JellyFish »

What other CSS properties break an element out of the document layout flow, like position:absolute;? This way I can take advantage of the position:relative; rule while at the same time taking the element out of the layout flow. Are there any css rules that have this effect? Or is position:absolute; the only solution?
User avatar
kaszu
Forum Regular
Posts: 749
Joined: Wed Jul 19, 2006 7:29 am

Re: CSS properties that take the element out of layout flow.

Post by kaszu »

position: fixed; and display: none; I can't think of any other.
What's wrong with position absolute? What effect are you trying to achieve?
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Re: CSS properties that take the element out of layout flow.

Post by JellyFish »

Absolute positioning takes the element out of the layout's flow, which is what I want. But position relative positions the element only relative from where it starts in the layout's flow. What I'm trying to achieve would be quite contradictory I guess. I'm trying to combine both relative and absolute positioning. I want the element to be taken out of the flow, but at the same time want the element to be position relative to were it started from. This way whenever the layout changes (elements are resized/add, or the window is resized) the element gets re-positioned with the document.

Here's a good example of what I'm trying to accomplish.

Code: Select all

 
<label class="placeholder" for="keywords">Enter your search</label>
<input type="text" class="text" id="keywords" />
 
In this markup, I have a label for a input element for keywords for a search form. What I want to be able to do with all labels with the class "placeholder" is have that label appear over the top of the input element they are for. This way the effect is a placeholder for text and password input elements. I will use JavaScript to add this effect. What I could do is absolutely position the label element over the input element, but then when the document changes around the input element the label element doesn't follow with it. This leads me to trying relative positioning. The only issue with relative positioning that I'm having is that there's this space left where the element would have been. I want to get rid of this space, and the only way I can think of to do this is to take the element out of the layout's flow.

Currently what I'm doing is setting the position to absolute but leaving the left and top properties set to auto. However there is another effect I'm going for with the placeholders. When the input element is focused, the label doesn't just disappear, rather it pops out above or below the input element in a tooltip kind of way. When this happens I set the left and top properties to the calculation of the input elements offset. Sense I'm still using position absolute, the label element doesn't follow the input element whenever the layout changes around the input element (causing the input element to change it's position) when the the input element is focused.

Here's a link to the testing area for what these labels.
User avatar
JellyFish
DevNet Resident
Posts: 1361
Joined: Tue Feb 14, 2006 7:18 pm
Location: San Diego, CA

Re: CSS properties that take the element out of layout flow.

Post by JellyFish »

Okay, so what I figured I'd do was use relative positioning and just set a negative right margin to the label. I was so excited after I "relativized" my placeholder labels, but then remembered I had to test everything in IE. Crossing my fingers in hope that IE wouldn't choke, I tested IE6, 7, and 8. Against all hope, it failed, miserably. :cry:

Here's the link to the test area.

Here's the JavaScript code:

Code: Select all

        function inputFocus(eventObject)
        {
            var inputElement = $(eventObject.target);
            var inputOffset = inputElement.offset();
            var inputTotalHeight = inputElement.height()+
                parseInt(inputElement.css("paddingTop"))+
                parseInt(inputElement.css("paddingBottom"))+
                parseInt(inputElement.css("borderTopWidth"))+
                parseInt(inputElement.css("borderBottomWidth"));
            var labelElement = $("label.placeholder[for="+inputElement.attr("id")+"]");
            var labelOffset = labelElement.offset();
            var labelTotalHeight = labelElement.height()+
                parseInt(labelElement.css("paddingTop"))+
                parseInt(labelElement.css("paddingBottom"))+
                parseInt(labelElement.css("borderTopWidth"))+
                parseInt(labelElement.css("borderBottomWidth"))
            var labelCurrentTop = parseInt(labelElement.css("top"));
            
            var labelClass = "tip-above";
            var labelNewTop = labelCurrentTop - labelTotalHeight;
            
            if (labelOffset.top + labelNewTop < 0)
            {
                var labelClass = "tip-below";
                var labelNewTop = labelCurrentTop + inputTotalHeight;
            }
            
            labelElement.addClass(labelClass).css(
                {
                    zIndex: 1,
                    //This formula must parse after the labelClass was added
                    marginRight: parseInt(labelElement.css("marginRight"))+(labelElement.offset().left - inputElement.offset().left)
                }
            ).animate(
                {
                    top: labelNewTop+"px",
                    opacity: 1
                }, 
                100
            );
        }
        function inputBlur(eventObject)
        {
            var inputElement = $(eventObject.target);
            var labelElement = $("label.placeholder[for=" + inputElement.attr("id") + "]");
            var inputOffset = inputElement.offset();
            var labelNewTop = parseInt(labelElement.css("top")) + inputElement.offset().top - labelElement.offset().top;
            
            if (this.value)
                var opacity = 0;
            else
                var opacity = 1;
            
            labelElement.removeClass("tip-above tip-below").css(
                {
                    zIndex: 0,
                    marginRight: parseInt(labelElement.css("marginRight")) + (labelElement.offset().left - inputElement.offset().left)
                }
            ).animate(
                {
                    top: labelNewTop+"px",
                    opacity: opacity
                }, 
                100
            );
        }
        
        $("label.placeholder").each(function(i) {
            var labelElement = $(this);
            var inputElement = $("#"+labelElement.attr("for"));
            
            labelElement.css(
                {
                    position: "relative",
                    zoom: 1,
                    marginRight: labelElement.offset().left - inputElement.offset().left,
                    top: inputElement.offset().top - labelElement.offset().top
                }
            );
            inputElement.focus(inputFocus).blur(inputBlur);
        });
Here's the CSS:

Code: Select all

/* LABELS */
label.placeholder {
    padding: 4px 5px;
    border-width: 0px;
    color: #888;
    cursor: text;
}
    label.placeholder.tip-above{
        background: #9edaff;
        -webkit-border-radius: 3px 3px 0px 0px;
        -moz-border-radius: 3px 3px 0px 0px;
        color: #333;
        font-weight: bold;
    }
    label.placeholder.tip-below {
        background: #bde6ff;
        -webkit-border-radius: 0px 0px 3px 3px;
        -moz-border-radius: 0px 0px 3px 3px;
        color: #424242;
        font-weight: bold;
    }
Not only does this break as far as layout goes, but IE also throws these useless errors which explains the problem as clearly as mud used in a telescope.

I don't see where the problem lies, I don't even know where to start. Not only does IE have the most problems out of any browser, but it sucks noodles when it comes to debugging. Why Microsoft, why?! I know why! It's a conspiracy! Microsoft knows that the Web as a platform is going to take over the desktop industry, so rather then moving forward with innovation, they are just trying to suck up as much money left in the current market...

How do you guys ever handle IE? Or do you not dabble in the client-side much? How could one ever solve such an issue? How do I even expect anyone on this forum to know how to solve this problem?

I just can't wait till Google Chrome Frame is out of beta.
Post Reply