First, this issue is not about block elements collapsing when their children are floated. In fact the issue has nothing to do with clearing at all.
The issue is this. Suppose I have a series of floated divs like:
<div class="column">Column 1</div>
<div class="column"></div>
<div class="column">Column 3</div>
With css:
div.column { float: left; width: 200px; }
The middle column will collapse in recent versions of Firefox and Safari, although apparently not IE7. What I want is the IE7 behavior.
I realize I can add an and it will hold the div open, but that doesn't work for me in this case because I also have have a declaration like this:
div.column input { width: 100% }
I have a series of columns layed in a table-like format, with certain conditions causing the input fields to disappear. The problem is when the input disappears the field collapses. If I add an it causes the div to wrap. Just to head off the initial questions:
Why don't I use a table instead? Because I'm using Scriptaculous Sortable to drag and drop rows, which doesn't work with tables
Why don't I use a shorter pixel width to leave room for an ? Because width: 100% is more accurate across browsers.
Why don't I add a when I hide the input I may end up resorting to this, but it would be kind of ugly in the JS, so I'm hoping for a better way.
Does anyone have any clever hacks here? Since both Safari and Firefox behave this way I assume this is officially sanctioned behavior. Where is this discussed in the W3C specs?
Eh? Shouldn't you just give it a random height? Can you show a demo?
Related
This question already has answers here:
How to remove the space between inline/inline-block elements?
(41 answers)
Closed 7 years ago.
I'm attempting to use a css grid with widths set in % (so I can use it responsively) and without using floats (personal dislike!).
In this instance, I'm using csswizardry-grids with the appropriate variables added in. You can view the demo linked on the github page.
There is no mention of a "container" class to assign a width to the grid, so I added .container (which is also what the csswizardry-grids demo has) with a max-width (in prep for other breakpoints later). The container has left and right padding to allow for the padding:left on the .grid__item within.
.container {
margin: 0 auto;
padding: 0 $gutter;
max-width: 960px;
}
The scss:
.grid__item {
display: inline-block;
padding-left: 32px;
vertical-align: top;
width: 100%;
-webkit-box-sizing: border-box;
box-sizing: border-box;
}
.desk--one-third { width: 33.333%; }
Also note that the box-sizing:border-box is not on any other element except that which is spec'd by the csswizardry-grids.scss.
My markup:
<div class="container">
<div class="grid">
<div class="grid__item desk--one-third">
<h1>Column 1</h1>
</div>
<div class="grid__item desk--one-third">
<h1>Column 2</h1>
</div>
<div class="grid__item desk--one-third">
<h1>Column 3</h1>
</div>
</div>
</div>
The problem: in firefox, safari & chrome, the last .grid__item falls away.
What I see: a mysterious gap between '.grid__item's of at least a few pixels. See attached screenshot:
!(http://dl.getdropbox.com/u/7408773/Screen%20Shot%202013-05-10%20at%2012.51.06%20AM.png)
Can anyone shed some light on this for me please?
Whitespace between inline-block elements
It sounds like you're using display: inline-block for the columns, rather than floating them.
The problem with using inline-block for layout is that if there's any whitespace in the HTML source code between the HTML tags (in this case, the grid__item divs), there will be 3-4 pixels of horizontal spacing added between the displayed elements.
inline-block was intended for adding block content to the flow of a paragraph. The reason this spacing occurs is the same reason that 3-4 px are added between 2 words in a paragraph: It gives a series of inline elements in a paragraph the amount of spacing they're usually expected to have.
There's no CSS solution for this that's truly cross-browser and safe (though negative left margins come the closest). There are ways to edit the HTML code to prevent this (removing the whitespace between the tags in the source code), but they present maintainability issues (with a high risk of difficult-to-identify issues turning up later on when someone else works on the code), and it significantly compromises the separation of content and presentation (given that changes to the formatting of the source code can affect the formatting of the displayed pages).
Comparison of inline-block and floats
Both floats and inline-block have the disadvantage of not having been intended for general layout (e.g., creating variable-height columns in the flow of a page). It could be argued that CSS positioning and HTML tables were not intended for general layout either (or at least are not well suited for it).
The natural uses for each:
Floats: Allowing a paragraph of text to flow around an element (usually an image)
inline-block: Adding block content inside a paragraph (like an image), as part of the paragraph
CSS positioning: Overlaying one element on top of another (usually a pop-up or dropdown)
HTML tables: Data grids
Historically, each of these has been forced into use for layout, due to the lack of other options. As Eric Meyer pointed out here and here, the reason floats wound up being used for layout was because of the ability to clear a float (which allows it to be used in a wider variety of ways).
Choosing the right tool
So if neither one was intended for general layout, how do you choose the best one to use?
The strongest argument against inline-block, on the whole, is that if it were truly suitable for general layout, there wouldn't be such a fundamental issue as the 3-4 px of horizontal spacing added between elements (which is almost never desired when laying out the main regions of a page -- columns shouldn't behave the same as words in a paragraph of text).
In specific situations, a simple rule can be applied: For cases where that 3-4 px creates a problem, that indicates that the use of inline-block is inappropriate. Likewise, for cases where the 3-4 px does not create a problem, that suggests that it may be a reasonable option.
In practice, I've found floats to be far more reliable and predictable than inline-block, especially on earlier versions of IE. The main hassle with floats is having to manually clear them. Adding a reliable clearfix to the CSS file makes doing so relatively manageable though. Even on modern CSS grid systems, the preferred layout mechanism for establishing columns is typically floats (based on what I've seen so far).
This was the first link when I searched "space between inline": http://css-tricks.com/fighting-the-space-between-inline-block-elements/
tl;dr remove any spaces between your columns.
This issue is caused by inline-block elements being considered as words - so it can be simulated by giving a negative word-spacing to the wrapping element. About word-spacing: -4px; worked for me Chrome/IE9/FF :) - However - remember - this is a workaround.
HTML:
<div class="wrapper">
<div class="inliner">01</div>
<div class="inliner">01</div>
<div class="inliner">01</div>
</div>
CSS:
.inliner{ display: inline-block; }
.wrapper{ word-spacing: -4px; }
I have a two-column layout, composed of fixed-width floated divs. Inside the first column is an extra wide element. So the html layout looks something like this:
<div id="container">
<div id="column1">
...short content...
<div id="extra-wide">
...wide content...
</div>
</div>
<div id="column2">
...long content...
</div>
</div>
As annotated, the first column contains a short amount of content and the second column contains a long amount of content. The CSS looks something like this:
#column1 { width: 200px; }
#column2 { width: 100px; }
#extra-wide { width: 250px; }
So the extra-wide element is actually wider than its parent, column1. And I don't know the heights of any of the elements ahead of time -- they are all variable.
The issue here is that column2 appears overlapped over the extra-wide element in column1. Here's a jsfiddle to help visualize this: http://jsfiddle.net/e3KNg/ (This fiddle has some content inserted and colors added to make what's happening more clear). Here's a screenshot:
Without altering the basic HTML structure or the widths of the three elements, is it possible (without the aid of Javascript) to force the extra-wide element in column1 to appear below column2? Here is the effect I'm trying to achieve:
I know this can be done by rearranging html elements or by using Javascript, but I'm looking for a solution within the above constraints. I tried using clearing divs in various places, removing or adjusting floats, and trying some overflow settings, but could not achieve the effect I was looking for.
looking at it, without set heights on the content elements or using javascript to work their heights out or set positioning on the extra-wide element, what you are looking for can't be achieved.
Heres a fiddle which works using an absolute positioning of the extra wide element and a top value, as well as using some clever css to make the columns the same height.
http://jsfiddle.net/yKRu4/1/
As i siad this works, but i honestly feel what you are looking for can't be achieved with the restrictions you have put in place.
I'm trying to make a HTML "showcase". I am thinking of using elements like this:
<div id="index-showcase-tabs">
<div id="index-showcase-tabslide">
<div class="index-showcase-tab" id="showcase-tab-1">Item1</div>
<div class="index-showcase-tab" id="showcase-tab-2">Item2</div>
...
<div class="index-showcase-tab" id="showcase-tab-N">ItemN</div>
</div>
</div>
The showcase items are floated left, and I don't know their precise width, nor the number of them.
Problem is: if the combined width of the items is bigger than the container (index-showcase-tabs), I don't want them to break line (which they do by default). I want them in one line, and I want to hide the overflow and then let the user scroll them with javascript (not by scrollbar...).
How would I do that?
PS: There's not much css for the items yet. I only gave the slider a specific heigth:
#index-showcase-tabslide
{
height: 34px;
}
Edit: Here you can see my problem.
Edit2: explaining more with a fiddle: http://jsfiddle.net/TbSfj/19/
For this, you cannot use float: left. Instead use display: inline - this will have the same effect for what you want to accomplish, and it will not be constrained to the parent div in the DOM model.
check out this sexy control:
http://jsfiddle.net/SoonDead/U6QdQ/20/
this way made for my project, but I think it does what you want.
The tricks are:
Because you use a lot of characters that can "linebreak" and even forcefully disable linebreaks have different results in 1-2 browsers, I would recommend against it.
Instead make the overflowing width wide enough to hold all the elements easily, so if javascript is disabled it will not look ugly.
(I know that you are fine with jquery, so I use it within the example, also the outerWidth property in simple js has bugs in webkit (tends to be 0 in some cases).)
So you need to sum up the elements' outerWidth() and set the content holder's width, so you can use scrollLeft, and not overscroll.
There is no other trick, just a scrollTo function because calculating positions are not that trivial if you are new to jquery and you might want to use that.
When I have three divs that all have float left I want the sections to expand or contract based on how long the data inside them is.
For instance, if the 1st address is very long I want the 1st box to expand and push the 2nd one over. In Firefox it is doing this but in Internet Explorer it requires a width to look right. In IE7 it doesn't display right at all - each div has a table with two columns and in IE7 it shows the 2nd column way over to the far side of the page instead of snug with the 1st column despite setting align=left on the 2nd column and setting a small width on the 1st column. I have the doc type specified in the master page and I've tried adding clear:both with no luck.
Why does the width totally change how the float section is displayed in IE and how can I fix this? The page must look nice in IE7.
.FloatingSection
{
float:left;
padding-bottom:10px;
padding-right:10px;
}
<div id="FirstPerson" class="FloatingSection">
</div>
<div id="SecondPerson" class="FloatingSection">
</div>
<div id="ThirdPerson" class="FloatingSection">
</div>
I noticed that in IE8 this looks just fine.
You should almost always include an explicit width when you're floating elements.
If you don't, browsers have to guess what you mean. In this case, Firefox is guessing better than IE, but you shouldn't make them guess. Be explicit where you can.
edit: If you want all three boxes to expand with the content, I'd suggest setting percentage-based widths. In general, you're going to want to look up techniques for fluid column layouts.
Just discovered that if you have a float and a clear applied to a DIV IE7 chokes.
Instead, specify the float, in the DIV's CSS, but remove the clear and place an empty div, after the DIV in question, like this:
BEFORE:
<div style="float:left; clear:right;">Content goes here</div>
AFTER
<div style="float:left;">Content goes here</div>
<div style="clear:right;"></div>
Have you considered display:inline-block instead of floating? I don't think you can do what you want with floats AND support IE without using some JS to explicitly define width on each floated element.
Another note, you have to declare a second separate rule for block level elements in IE:
HTML:
<div class="foo">test</div><div class="foo">bar</div>
CSS:
.foo { display:inline-block; }
.foo { display:inline; } /* Feed this to IE below 9 only with a CC. Don't feed it to modern browsers */
Compare these 3 URLs (look at the top navigation bar in each case):
http://fast.kirkdesigns.co.uk/blog
as above but with the url fragment #navigation
as above but with the url fragment #node-2655
Note, that the only difference is the URL fragment on the end.
The first two pages display absolutely fine (in Firefox at least). It's the third one where the problem lies. The fragment #node-2655 pushes the top navbar off the top of the screen. When you then scroll back up to the top of the page, the navbar has been cut in half. This happens when using any URL fragment that causes the navbar to be out of the initial viewport when the page is first loaded.
So, how can using a url fragment affect the css layout like this?!
THE SOLUTION:
as suggested below, removing the overflow: hidden on the container element that held the navbar fixed the problem. I'd love to understand why though!
Remove the overflow:hidden on #main in css_75afd7072eaf4096aaebf60674218e31.css
I'd say it's a rendering bug in FireFox as it's fine in Opera. There shouldn't be anyway an anchor would change the CSS like you say (unless you are using jQuery or something).
I am having this problem too, and think I can see what is happening.
The "column" block with the massive (5678 pixel) margin and padding makes that block very tall. In browsers other than Firefox, the positive and negative values cancel each other out, but FF really does make it that tall - kind of.
FF also knows the two cancel each other out, but seems to look at the 5678px padding and decides the column block is poking out the bottom of the #wrapper block. This is overflow - and with overflow set to auto on #wrapper, you see the true size of #wrapper with a scroll-bar down the side.
With overflow set to hidden, FF takes away the scrollbar, but still seems to scroll the contents of #wrapper so that the item the fragment points to is at the top of the page. This is normal behaviour for fragment links in scrollable blocks, but since there is no scrollbar, you cannot scroll the content back down again, hence it looks like the layout has been effected by the fragment.
So in short, I suspect that FF is operating an invisible scrollbar in this example. That could be considered a bug, but it is probably correct behaviour. Being able to scroll the content up and down inside a non-overflowed fixed-sized block using URL fragments, is a technique that can be used effectively to implement image "sliders" that work even in the absence of JavaScript.
Hope that helps. This has been puzzling me for years, and this explanation suddenly struck me out the blue. My current workaround for this is to use jQuery "scroll to" plugin to scroll the whole page down to the fragment, as this seems to prevent the contents of #wrapper from scrolling internally.
You can also take "display: hidden" off #wrapper, but your page then ends up half a mile long.
I'll just point out that there may be some weird inheritance from the 30+ stylesheets linked to in the head. There may not, either, and it's probably a rendering bug (possibly related to :target styling) that Dan suggested. I just felt it worth pointing out that if you've got more than thirty stylesheets, you likely to start seeing some weirdness, whatever else might happens.
The reason is the column with the large padding has expanded it's container, but the expansion is then hidden but overflow:hidden; but with the use of the fragment it is being scrolled into the position of the fragment, effectively chopping off anything above that. You can use javascript and set scrollTop to 0 and it scroll it back to the normal position.
Basically a wierd edge case which browsers do not seem to handle very well.
Sorry this isn't an "answer," tho it is a response to the other comments here. This problem is just flabbergasting. It is very easy to isolate (i.e., has nothing to do with number of stylesheets), and doesn't have a proper "solution," as there is no way to achieve the desired rendering.
<!DOCTYPE html>
<html>
<head>
<style>
#container {
margin: 1em auto;
width: 40em;
}
#wrapper {
overflow: hidden;
position: relative;
}
#c1 {background-color: #aaf;}
#c2 {background-color: #ccf;}
.column {
float: left;
margin-bottom: -5678px;
padding-bottom: 5678px;
width: 50%;
}
#footer {
background-color: #eee;
padding: 1px;
text-align: center;
}
p {margin: 1em;}
</style>
</head>
<body>
<div id="container">
<div id="wrapper">
<div id="c1" class="column">
<p>This is some content in a short column. We would need some Javascript to change its height if we wanted a different background color for each column to stretch the full height of the respective columns...or we can use large padding together with an equal negative margin.</p>
<ul>
<li>Jump to P1</li>
<li>Jump to P2</li>
<li>Jump to P3</li>
</ul>
</div>
<div id="c2" class="column">
<p id="p1">The desired effect is to have the height of the two columns appear the same. We use 'overflow:hidden' on the containing div (#wrapper) to wrap it around the floated columns.</p>
<p id="p2">These paragraphs have fragment identifiers. Problem comes in when clicking one of the links on the left. Instead of scrolling just the page, the browser scrolls the div with 'overflow:hidden' so the target is at the top. It does this even if the target is already visible.</p>
<p id="p3">Opera does not exhibit this behavior. This occurs in Chrome/Safari, Firefox, and IE. (Interestingly, IE also works as expected if we completely remove the DOCTYPE declaration.)</p>
</div>
</div>
<div id="footer">
<p>Footer stuff.</p>
<p>To see why 'overflow: hidden' (or any other piece of the CSS) is needed, just try disabling it.</p>
</div>
</div>
</body>
</html>
Just as a side-note, the above technique is generally used to provide flexible-width mulit-column layouts. This is probably becoming less important these days as fixed-width layouts are becoming a lot more comment - browsers are able to magnify the web page to see small text, and fixed-width makes it a lot easier to control the typography of a page, e.g. set the width (in ems) to display the ideal nine words per line regardless of what font size and magnification the user chooses.
Sorry if that does not sound like an answer, but it is basically suggesting to discard this old model and consider moving to fixed-width columns (which is a whole new subject).
I was able to solve this with some javascript to scroll the body to the position the overflow hidden element was scrolled to.
setTimeout(() => {
let intendedScroll = document.getElementById("fragmentfix").scrollTop;
document.getElementById("fragmentfix").scrollTop = 0;
window.scrollTo(0, intendedScroll);
}, 0)