Reputation: 156524
Here's some code to illustrate the problem I'm running into. jsFiddle Demo
<div class="normal">
<a href="#">Test</a>
<a href="#">Test longer</a>
</div>
<div class="ib blockbyclass">
<a href="#">Test</a>
<a href="#">Test longer</a>
</div>
<div class="ib">
<a href="#" style="display: block;">Test</a>
<a href="#" style="display: block;">Test longer</a>
</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?
Upvotes: 9
Views: 19008
Reputation: 27585
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.
Upvotes: 4
Reputation: 3248
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.
Upvotes: 0
Reputation: 3122
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.
Upvotes: 0
Reputation: 3028
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">
<a href="#">Test</a>
<a href="#">Test longer</a>
</div>
<div class="ib blockbyclass">
<a href="#">Test</a>
<a href="#">Test longer</a>
</div>
<div class="ib">
<a href="#" style="display: block;">Test</a>
<a href="#" style="display: block;">Test longer</a>
</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">
<a href="#" style="display: block;">Test</a>
<a href="#" style="display: block;">Test longer</a>
</div>
This, in this case, becomes redundant, and therefore unnecessary. You're already making those elements block.
<div class="ib">
<a href="#">Test</a>
<a href="#">Test longer</a>
</div>
You're simply overcomplicating something really very simple.
Here's a fiddle: http://jsfiddle.net/dhYjZ/1/
Upvotes: 0
Reputation: 4206
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 width
s in IE7)
Upvotes: 4
Reputation: 72261
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.
Upvotes: 1
Reputation: 3921
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; }
Upvotes: -1
Reputation: 3059
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/
Upvotes: -1
Reputation: 7653
display: inline-block
for IE7 looks like:
*display: inline;
zoom: 1
Upvotes: 1
Reputation: 1772
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.
Upvotes: 0
Reputation: 116110
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.
Upvotes: 1