How can I override "display:inline-block" with "display: block" in IE7? - html

Here's some code to illustrate the problem I'm running into. jsFiddle Demo
<div class="normal">
Test
Test longer
</div>
<div class="ib blockbyclass">
Test
Test longer
</div>
<div class="ib">
Test
Test longer
</div>
body{background-color: gray;}
div{float:left; margin: 5px;}
a {background-color: black; color: white;}
div.ib a {display: inline-block;}
div.normal > a {display: block;}
div.blockbyclass> a {display: block; }
I have a certain type of link that under most circumstances needs to be rendered as inline-block, but in a certain case needs to be rendered as block elements. Specifically, I want them to each appear on their own line and take up the entire area of the containing div. In this particular case, the div containing the links is set to float, so it will resize itself based on the largest of the links inside it. IE8, IE9, Firefox and Chrome render these links correctly, but no matter what I do IE7 refuses to forget the display: inline-block rule.
How can I make IE7 show these elements in "block" mode?

Acording with this article display:inline-block has a similar behavior that display:inline in IE7, so you can make a litte change only to support IE7 (with a simple hack for IE):
div.ib a {
display: inline-block;
*display: inline; /* IE7 and below */
}
I hope this works as you expected.
EDIT:
Ok. The problem are with the property hasLayout explaining here. Both zoom:1 and height:any_value activates the hasLayout, so meanwhile display:inline-block; *display:inline works to overwrite the next display:block declarations, putting a height:30px (for example) returns the property hasLayout. So the thing to do is remove the hasLayout as it says in this article.
I have this demo to show how works. Because height is practically untouchable I using padding-bottom and font-size to simulate the height in other browsers. Note that the width of the widest element is maintained.
EDIT2:
Have you are considerate jQuery solutions? (Only giving the elements different widths in IE7)

Update: moved from comments here:
The problem is on div floating. When you float an element, that will be outside of pages normal stream, so, IE will take for it width:0; height:0; and when you put some elements in it, they will create their own height and width and the floated-element will be rendered how can push them (my English is really bad, so sorry). First step, A is inline-block so its height is for example x. when you make it block it should fill its parent, but, in IE mind, its parent has width:0. so you should remove the first inline-block attribute from div.ib a OR you can create a fixed-width attribute for floated div element.
div { float: left; margin: 5px; width: 80px; }
also, insofar as I know, W3C recommends that floated elements should have a fixed-width. - IE 6 needs a fixed height too to work correctly!!!
The another way -if you can and your solution allows you- is that change the first inline-block to inline just for IE:
display: inline-block;
*display: inline;
But the width solution (for div) is more standard and flexible.
END UPDATE
However, for overriding a css-attribute just in IE, you have 3 optional way to do:
The first way is using conditional comment that makes it's content visible to IE only. A full example is something like this:
<!-- visible to IE less that 7 (6, 5, etc) -->
<!--[if lt IE 7]> <link href="/Content/ie6.css" rel="stylesheet" type="text/css" /> <![endif]-->
<!-- visible to IE 7 only -->
<!--[if IE 7]> <link href="/Content/ie7.css" rel="stylesheet" type="text/css" /> <![endif]-->
<!-- visible to IE 8 only -->
<!--[if IE 8]> <link href="/Content/ie8.css" rel="stylesheet" type="text/css" /> <![endif]-->
<!-- visible to IE 9 and above and also visible to other browsers -->
<!--[if gt IE 8]><!--> <link href="/Content/normal.css" rel="stylesheet" type="text/css" /> <!--<![endif]-->
As you can see, you have many options to use conditional comment.
The other way is using CSS specially selectors that make some selectors visible to IE and hide them from other browsers. A full example is:
/* normal */
your-selector{
}
/* visible to IE 6 only */
* html your-selector{
}
/* visible to IE 7 only */
*:first-child + html your-selector{
}
/* visible to IE 7 and above */
html > body your-selector{
}
/* visible to IE 8 and above */
html > /**/ body your-selector{
}
The third way that I know is using IE specialized css-properties:
/* normal selector */
your-selector{
/* normal property, visible to all browsers */
color: #FF0;
padding: 20px auto 35px;
/* use special properties in name/value for IE */
/* visible to ie 6 only */
_color: #FF0;
_padding: 15px auto 30px;
/* visible to ie 7 and below (7, 6, 5, ...) */
*color:#FF0;
*padding: 15px auto 30px;
}
Let me know if you have any questions or need clarifications on any part.

Your problem is a hasLayout trigger by the inline-block setting. To quote http://www.satzansatz.de/cssd/onhavinglayout.html (my emphasis added):
"The display-property differs: while 'inline-block' sets haslayout = true, the flag will not be reset to false later on by overriding the value with 'block' or 'inline' in another rule set."
This is unlike most hasLayout triggers that can be reset. Therefore, I think to fix your problem, you need to think in reverse. You need to have block be your default for the a tag and then add a class to get your inline-block when you need it.
Sort of like http://jsfiddle.net/mmpX3/33/ where blockbyclass I replaced with inlinebyclass (which is really inline-block).
Updated Explanation: You probably noticed that when you switched to block after going from inline-block that it "sort of worked" (the lines of text still move down). That is because it is displaying as a block, but one that hasLayout as opposed to one that does not. I don't know your particular situation, but if you can set a width on the containing div then a secondary solution to that I proposed above of "thinking in reverse" is to then set a width: 100% in conjunction with your "resetting" to block, like so: http://jsfiddle.net/mmpX3/64/.
Updated Caution: I don't know if you have other css you plan to apply to the a tags, but if any of that triggers hasLayout then you will need to watch out for that (and perhaps find a different method). See for example this fiddle http://jsfiddle.net/mmpX3/69/ in which everything is set to block but because I put a min-height on the a tag, it still has the same issues as your original problem.

You can put styles for IE7 in a separate CSS and use a conditional comment to include it only for IE7.
<!--[if IE 7]>
<link ...your IE7 specific stylesheet goes here ... >
<![endif]-->
Make sure this piece of code is below the link to the regular css file.

display: inline-block
for IE7 looks like:
*display: inline;
zoom: 1

display: inline-block is not compatible in IE7 for elements which are not inline by default so IE will ignore this rule for DIVs. If you change the DIV to a SPAN for example then this example should work.

Here's the thing: If you need the a tag anchors to render on their own lines, they are block elements, not inline... In fact, there's nothing about what you're saying that indicates a need for an inline-block. Your divs are floating, so they'll stack to the left, in a line (but not inline; they are outside the flow of the document, thus float).
Try this... let's strip it all down. Here's the HTML you gave us:
<div class="normal">
Test
Test longer
</div>
<div class="ib blockbyclass">
Test
Test longer
</div>
<div class="ib">
Test
Test longer
</div>
With the CSS you provided, in Safari and Firefox, I see three blocks with two links each, each on their own line. What you're seeing in IE7, however, isn't two inline-block elements, but just two inline elements – the reason for this is that inline-block is not supported in IE7 because of a hasLayout error (something Microsoft created to overcomplicate a simple issue). In other words, it can't forget inline-block because it simply doesn't understand inline-block (which you've misunderstood as necessary), and is treating a by its default display behavior (i.e. inline).
If they need to be on separate lines and take up the width of the container, all you have to do is this (demonstrated on .ib a, completely ignoring blockbyclass which seems to just be a red herring in this case):
.ib a {display:block;}
TADA! Width is inherited from the parent container, the a takes the default a stylings, and everything is happy. So take a look at this:
<div class="ib">
Test
Test longer
</div>
This, in this case, becomes redundant, and therefore unnecessary. You're already making those elements block.
<div class="ib">
Test
Test longer
</div>
You're simply overcomplicating something really very simple.
Here's a fiddle: http://jsfiddle.net/dhYjZ/1/

It appears that float is to blame here. It is not that IE7 does not mark the item as block, I think it is due to the div float not having a width. This can be seen here:
http://jsfiddle.net/mmpX3/129/
Typically, when working with older browsers, I have found that floated elements in <= IE7 tend to need a fixed width setting to avoid issues.
In your case, I would suggest adding a fixed width as the JS Fiddle, or remove the float if it is not needed. If I can see the use case for the floated div, I may be able to come up with an alternative.
Why a combination of float and display:inline-block stops display:block from being re-instanted, I don't know. It sounds like a typical IE7 bug that can be worked around.

I'm not quite sure what is the end-result that you are after. Are you trying to make the black background to be a whole rectangle that encapsulates both links instead of 2 rectangles (1 for each link)?
If so, why not apply the background to the DIV instead of the links?
EDIT:
It seems that there's a bug with IE7 that makes it display elements in a mixture of block and inline-block when one of the rules that applies to the element has display: inline-block even if another value for display takes precedence.
If you see http://jsfiddle.net/P2N5c/16/ , it doesn't matter if the rule that has display: block is the first one (like the one using the #blocky rule) or if it's the last one.
So far I'm not sure how to prevent this bug, but you could bypass it by avoid giving the links both ib and blockbyclass and just giving it the classes that make them blocks. I.e. don't give them ib. Instead of adding a class to toggle the states for the DIV, replace one class for the other.

Simply put, I replace all of my display:inline-block; usages with display:inline;, and I also do so conditionally, as with the answers provided above.
With your example, I find success with the following:
body{background-color: gray;}
div{float:left; margin: 5px;}
a {background-color: black; color: white;display:block;}
Jsfiddle: http://jsfiddle.net/zL3Ea/

Seems like jobs done.
I am fork your code, try it: http://jsfiddle.net/Lkwzx/1/
Secret in this line: div.ib a { display: inline-block; *display: inline; }

Related

<fieldset> resizes wrong; appears to have unremovable `min-width: min-content`

Problem
I have a <select> where one of its <option>’s text values is very long. I want the <select> to resize so it is never wider than its parent, even if it has to cut off its displayed text. max-width: 100% should do that.
Before resize:
What I want after resize:
But if you load this jsFiddle example and resize the Result panel’s width to be smaller than that of the <select>, you can see that the select inside the <fieldset> fails to scale its width down.
What I’m actually seeing after resize:
However, the equivalent page with a <div> instead of a <fieldset> does scale properly. You can see that and test your changes more easily if you have a <fieldset> and a <div> next to each other on one page. And if you delete the surrounding <fieldset> tags, the resizing works. The <fieldset> tag is somehow causing horizontal resizing to break.
The <fieldset> acts is as if there is a CSS rule fieldset { min-width: min-content; }. (min-content means, roughly, the smallest width that doesn’t cause a child to overflow.) If I replace the <fieldset> with a <div> with min-width: min-content, it looks exactly the same. Yet there is no rule with min-content in my styles, in the browser default stylesheet, or visible in Firebug’s CSS Inspector. I tried to override every style visible on the <fieldset> in Firebug’s CSS Inspector and in Firefox’s default stylesheet forms.css, but that didn’t help. Specifically overriding min-width and width didn’t do anything either.
Code
HTML of the fieldset:
<fieldset>
<div class="wrapper">
<select id="section" name="section">
<option value="-1"></option>
<option value="1501" selected="selected">Sphinx of black quartz, judge my vow. The quick brown fox jumps over the lazy dog.</option>
<option value="1480">Subcontractor</option>
<option value="3181">Valley</option>
<option value="3180">Ventura</option>
<option value="3220">Very Newest Section</option>
<option value="1481">Visitor</option>
<option value="3200">N/A</option>
</select>
</div>
</fieldset>
My CSS that should be working but isn’t:
fieldset {
/* hide fieldset-specific visual features: */
margin: 0;
padding: 0;
border: none;
}
select {
max-width: 100%;
}
Resetting the width properties to the defaults does nothing:
fieldset {
width: auto;
min-width: 0;
max-width: none;
}
Further CSS in which I try and fail to fix the problem:
/* try lots of things to fix the width, with no success: */
fieldset {
display: block;
min-width: 0;
max-width: 100%;
width: 100%;
text-overflow: clip;
}
div.wrapper {
width: 100%;
}
select {
overflow: hidden;
}
More details
The problem also occurs in this more comprehensive, more complicated jsFiddle example, which is more similar to the web page I’m actually trying to fix. You can see from that that the <select> is not the problem – an inline-block div also fails to resize. Though this example is more complicated, I assume that the fix for the simple case above will also fix this more complicated case.
[Edit: see browser support details below.]
One curious thing about this problem is that if you set div.wrapper { width: 50%; }, the <fieldset> stops resizing itself at the point then the full-size <select> would have hit the edge of the viewport. The resizing happens as if the <select> has width: 100%, even though the <select> looks like it has width: 50%.
If you give the <select> itself width: 50%, that behavior does not occur; the width is simply correctly set.
I don’t understand the reason for that difference. But it may not be relevant.
I also found the very similar question HTML fieldset allows children to expand indefinitely. The asker couldn’t find a solution and guesses that there is no solution apart from removing the <fieldset>. But I’m wondering, if it really is impossible to make the <fieldset> display right, why is that? What in <fieldset>’s spec or default CSS (as of this question) causes this behavior? This special behavior is probably be documented somewhere, since multiple browsers work like this.
Background goal and requirements
The reason I’m trying to do this is as part of writing mobile styles for an existing page with a big form. The form has multiple sections, and one part of it is wrapped in a <fieldset>. On a smartphone (or if you make your browser window small), the part of the page with the <fieldset> is much wider than the rest of the form. Most of the form constrains its width just fine, but the section with the <fieldset> does not, forcing the user to zoom out or scroll right to see all of that section.
I’m wary of simply removing the <fieldset>, as it is generated on many pages in a big app, and I’m not sure what selectors in CSS or JavaScript might depend on it.
I can use JavaScript if I need to, and a JavaScript solution is better than nothing. But if JavaScript is the only way to do this, I’d be curious to hear an explanation for why this is not possible using only CSS and HTML.
Edit: browser support
On the site, I need to support Internet Explorer 8 and later (we just dropped support for IE7), the latest Firefox, and the latest Chrome. This particular page should also work on iOS and Android smartphones. Slightly degraded but still usable behavior is acceptable for Internet Explorer 8.
I retested my broken fieldset example on different browsers. It actually already works in these browsers:
Internet Explorer 8, 9, and 10
Chrome
Chrome for Android
It breaks in these browsers:
Firefox
Firefox for Android
Internet Explorer 7
Thus, the only browser I care about that the current code breaks in is Firefox (on both desktop and mobile). If the code were fixed so it worked in Firefox without breaking it in any other browsers, that would solve my problem.
The site HTML template uses Internet Explorer conditional comments to add classes such .ie8 and .oldie to the <html> element. You can use those classes in your CSS if you need to work around styling differences in IE. The classes added are the same as in this old version of HTML5 Boilerplate.
Update (25 Sept 2017)
The Firefox bug described below is fixed as of Firefox 53 and the link to this answer has finally been removed from Bootstrap's documentation.
Also, my sincere apologies to the Mozilla contributors who had to block removing support for -moz-document partly due to this answer.
The fix
In WebKit and Firefox 53+, you just set min-width: 0; on the fieldset to override the default value of min-content.¹
Still, Firefox is a bit… odd when it comes to fieldsets. To make this work in earlier versions, you must change the display property of the fieldset to one of the following values:
table-cell (recommended)
table-column
table-column-group
table-footer-group
table-header-group
table-row
table-row-group
Of these, I recommend table-cell. Both table-row and table-row-group prevent you from changing width, while table-column and table-column-group prevent you from changing height.
This will (somewhat reasonably) break rendering in IE. Since only Gecko needs this, you can justifiably use #-moz-document—one of Mozilla's proprietary CSS extensions—to hide it from other browsers:
#-moz-document url-prefix() {
fieldset {
display: table-cell;
}
}
(Here's a jsFiddle demo.)
That fixes things, but if you're anything like me your reaction was something like…
What.
There is a reason, but it's not pretty.
The default presentation of the fieldset element is absurd and essentially impossible to specify in CSS. Think about it: the fieldset's border disappears where it's overlapped by a legend element, but the background remains visible! There's no way to reproduce this with any other combination of elements.
To top it off, implementations are full of concessions to legacy behaviour. One such is that the minimum width of a fieldset is never less than the intrinsic width of its content. WebKit gives you a way to override this behaviour by specifying it in the default stylesheet, but Gecko² goes a step further and enforces it in the rendering engine.
However, internal table elements constitute a special frame type in Gecko. Dimensional constraints for elements with these display values set are calculated in a separate code path, entirely circumventing the enforced minimum width imposed on fieldsets.
Again—the bug for this has been fixed as of Firefox 53, so you do not need this hack if you are only targeting newer versions.
Is using #-moz-document safe?
For this one issue, yes. #-moz-document works as intended in all versions of Firefox up until 53, where this bug is fixed.
This is no accident. Due in part to this answer, the bug to limit #-moz-document to user/UA stylesheets was made dependent on the underlying fieldset bug being fixed first.
Beyond this, do not use #-moz-document to target Firefox in your CSS, other resources notwithstanding.³
¹ Value may be prefixed. According to one reader, this has no effect in Android 4.1.2 Stock Browser and possibly other old versions; I have not had time to verify this.
² All links to the Gecko source in this answer refer to the 5065fdc12408 changeset, committed 29ᵗʰ July 2013; you may wish to compare notes with the most recent revision from Mozilla Central.
³ See e.g. SO #953491: Targeting only Firefox with CSS and CSS Tricks: CSS hacks targeting Firefox for widely referenced articles on high-profile sites.
Safari on iOS issue with selected answer
I found the answer from Jordan Gray to be particularly helpful.
However it didn't seem to solve this issue on Safari iOS for me.
The issue for me is simply that the fieldset cannot have an auto width if the element within has a max-width as a % width.
Fix for issue
Simply setting the fieldset to have a 100% width of it's container seems to get around this issue.
Example
fieldset {
min-width: 0;
width: 100%;
}
Please refer to the below for working examples - if you remove the % width off the fieldset or replace it with auto, it will not continue to function.
JSFiddle | Codepen
I’ve struggled for many hours with this, and basically, the browser is applying computed styling that you need to override in your CSS. I forget the exact property that is being set on fieldset elements versus divs (perhaps min-width?).
My best advice would be to change your element to a div, copy the computed styles from your inspector, then change your element back to fieldset and compare the computed styles to find the culprit.
Hope that helps.
Update: Adding display: table-cell helps in non-Chrome browsers.
.fake-select { white-space:nowrap; } caused the fieldset to interpret the .fake-select element by its original width, rather than its forced width (even when the overflow is hidden).
Remove that rule, and change .fake-select's max-width:100% to just width:100% and everything fits. The caveat is that you see all of the content of the fake-select, but I don't think this is all that bad, and it fits horizontally now.
Update: with the current rules in the following fiddle (which contains only real selects), the fieldset's children are constrained to correct widths. Other than removing rules for .fake-select and fixing comments (from // comment to /* comment */, I've noted changes in the fiddle's CSS.
I understand your problem better now, and the fiddle reflects some progress. I set default rules for all <select>s, and reserve .xxlarge for those which you know will be wider than 480px (and this only works because you know the width of #viewport, and can manually add the class to those too wide. Just requires a little bit of testing)
Proof

list items spacing issue in IE7

In my web page, there are some items listed like this, Item 1Item 2item 3 I am wondering, it is taking much space in IE7(I haven't checked it yet on other versions of IE browsers) whereas in FF and Chrome it is fine. I have given "list-style-type: none" in my CSS. Still cant guess why it is taking space. Please help.
Link Normalize CSS in your HTML page and your page should render the same in all major browsers.
Normalize.css makes browsers render all elements more consistently and in line with modern standards. It precisely targets only the styles that need normalizing.
Edit:
There can be an issue with the margin and padding, keep it to 0-
ul, li{
margin: 0;
padding: 0;
}
This one worked for me:
li { display:inline; }

IE box model error

I have a footer, below a textarea, containing a list and two buttons (all inline) within a div with the id #share-something. For some reason it is placed differently in Internet Explorer. I want it to look the same in IE as it does in Chrome. What am I doing wrong? http://jsfiddle.net/h3twR/
Oddly enough, IE7 seems to be fine for me, but 8 & 9 are off. If you have an IE-only stylesheet (using conditional comments), you can add this:
#share-something-container textarea {
margin-bottom: 5px;
}
*:first-child+html #share-something-container textarea {
margin-bottom: 0px; /* targets ie7 and undoes the margin above, as IE7 is okay */
}
This doesn't explain why 8 & 9 behave differently, but I've long since given up looking for logic and reason in IE.
There seems to be some kind of difference between IE8/9 and the other browsers and how they're rendering TEXTAREA.
It looks like you just have to set TEXTAREA to display block. It seems some browsers behave differently in this situation as they will see all elements as inline and generate extra white space. However, setting it to display:inline doesn't seem to have the reverse effect, so it's weird like that.
Here's a solution:
http://jsfiddle.net/h3twR/2/
I simply added this:
#share-something-container textarea {
...
display:block;
margin-bottom:5px;
}
And it appeared to render more consistently. IE7 seems to be off a little bit more. But hopefully this helps a little.
Cheers!

why does the page display differently in IE than google chrome?

Certain pages display terribly in IE generally, what is the best approach to solving these issues?
You forgot to add a doctype, so your page is in Quirks Mode.
Add this (the HTML5 doctype) as the very first line:
<!DOCTYPE html>
and it should look better.
Although, changing the Document Mode manually (using Developer Tools; hit F12), it still doesn't look right. There are evidently other problems with the page.
The most pertinent problem (after escaping Quirks Mode) is this:
<body style="margin: 0; padding; 0;background-color: 4DA2CA;">
Internet Explorer is not showing any background colour because you forgot the # before the colour. (And you have padding; 0, with a ; instead of :)
This will work:
<body style="margin: 0; padding: 0; background-color: #4DA2CA">
But you shouldn't be using inline styles in the first place..
This would be better:
<body>
with CSS in your stylesheet:
body {
margin: 0;
padding: 0;
background-color: #4DA2CA
}
you mean that in IE the Div's are smaller.Thats because in IE css border,margin are included in the width declared.So, if you have given a div width of 100px and a margin of 10px both sides then in IE the actual visible width of this div will be 100-10-10=80px.To solve the problem you can use child css decleration.
Considering our example if you want to show this div 100px width in both the browsers do the following
.mydiv{ /*This deceleration will be understood by all the browsers*/
margin:10px;
width:120px;
}
html>body .mydiv{ /*This deceleration will not be understood by IE browsers so other will override the width*/
width:100px;
}
Using this you can uniform the width of your Divs across both IE and non-ie browsers
Instead of pointing out the reason for each element's different way of rendering in IE, I would strongly recommend not re-inventing the wheel each time you create a new page element.
Even in modern standards-complaint browsers, CSS can be very unpredictable, so it's better to use bullet-proof snippets of code from trusted sources such as
CSS the Missing Manual
CSS the Definitive Guide
CSS Cookbook
Start out with working blocks of HTML/CSS and modify them to your liking and test cross-browser from there. The whole process will be much less frustrating.

Getting uniform layout in both IE7 & IE8 with form elements

It would seem that IE7 puts an extra 1px of spacing above and beneath form elements.
IE8, FF3.5, Chrome 2 & Opera 9.5 correctly renders these elements without the spacing.
What I want though, is for the display to be the same in IE7, so is there some kind of workaround to get IE7 to correctly render the elements?
It doesn't appear to matter whether or not the form element (eg Input Boxes) are placed within 's or 's, nor does it seem to matter about padding, margins & spacing settings. (setting them all to zero still has a 1px space around the input boxes)
I ran into this a while back and to be honest, I'm not totally sure I remember the fix. I seem to recall it has something to do with IE adding padding on the inside and outside of the input box, thus making it impossible to fix. It was either that or borders. Try either of these, together and separately:
input {
border: 0;
font-size: .9em;
}
If either of those offer what you need, I'd go with a conditional comment like:
<!--[if lte IE 7]>
input {
border: 0;
font-size: .9em;
}
<![endif]-->
Unfortunately, browsers render form elements with inconsistent heights and widths.
Fortunately, your two problem children are IE6 and IE7, both of which are easy to target using conditional comments. Without seeing them it's hard to say what the exact fix would be, but it might look something like this:
<!--[if lte IE 7]>
<style type="text/css">
input{ padding-top: 3px; ) /* 1px less than other browsers */
</style>
<![endif]-->