1

What i want to do in my JSF 2 application is to set proper html style depending on browser version, here is sample code:

<!--[if lt IE 7]> <html class="lt-ie9 lt-ie8 lt-ie7" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="lt-ie9 lt-ie8" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="lt-ie9" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <!--<![endif]-->

How to do that in JSF 2? What is the best/simplest way?

I found something interesting in Omnifaces (o:conditionalComment) but it only allows conditional loading of entire css which is useless for me...

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
michal777
  • 404
  • 4
  • 14

3 Answers3

7

It's not true that the <o:conditionalComment> is for CSS files only. That's a misconception. It's technically simply not possible to achieve your requirement with pure Facelets tags/components as it would result in malformed XML syntax and thus a Facelets compile error.

<o:conditionalComment if="lt IE 7">
    <html lang="en" class="lt-ie9 lt-ie8 lt-ie7">
</o:conditionalComment>
<o:conditionalComment if="IE 7">
    <html lang="en" class="lt-ie9 lt-ie8">
</o:conditionalComment>
<o:conditionalComment if="IE 8">
    <html lang="en" class="lt-ie9">
</o:conditionalComment>
<o:conditionalComment if="gt IE 8">
    <h:outputText value="&lt;!--&gt;" escape="false" />
    <html lang="en" class="no-js">
    <h:outputText value="&lt;!--" escape="false" />
</o:conditionalComment>
...
</html>

This is not well formed XML. You know, the XML end element should be in the very same scope as XML start element. It would be valid XML if every <html> has its own </html> in the same parent XML element. But this is in turn not valid HTML.

Just use <h:outputText escape="false"> on all <html> tags. Don't forget to do the same for the closing </html> tag.

<o:conditionalComment if="lt IE 7">
    <h:outputText value="&lt;html lang=&quot;en&quot; class=&quot;lt-ie9 lt-ie8 lt-ie7&quot;&gt;" escape="false" />
</o:conditionalComment>
<o:conditionalComment if="IE 7">
    <h:outputText value="&lt;html lang=&quot;en&quot; class=&quot;lt-ie9 lt-ie8&quot;&gt;" escape="false" />
</o:conditionalComment>
<o:conditionalComment if="IE 8">
    <h:outputText value="&lt;html lang=&quot;en&quot; class=&quot;lt-ie9&quot;&gt;" escape="false" />
</o:conditionalComment>
<o:conditionalComment if="gt IE 8">
    <h:outputText value="&lt;!--&gt;&lt;html lang=&quot;en&quot; class=&quot;no-js&quot;&gt;&lt;!--" escape="false" />
</o:conditionalComment>
...
<h:outputText value="&lt;/html&gt;" escape="false" />

Pretty awkward, but the HTML5 boilerplate (where this approach originated) is at its whole own also awkward, IMO.

Alternatively, you could consider creating a custom <my:html> component yourself which generates the desired markup so that you can just suffice with <my:html>...</my:html>.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Thanks, for now I used single h:outputText. I also wrapped everything in f:view (namespace definitions). I used o:conditionalComment for js including. Its strange but the closing – michal777 Jul 31 '12 at 08:44
  • I just wanted to throw in a [link](http://stackoverflow.com/questions/10616944/jsf-2-1-ie-conditional-comments) to another question, where BalusC spells out the f:view thing in detail. I was trying to solve the same problem, and had a hard time finding all of the pieces of the solution. – EMS Jan 08 '14 at 19:37
3

you can make 3 CSS (one per browser) with the same class. Your HTML code will be more simple.

In the header, you can use specific browser css like that:

<h:outputStylesheet library="css" name="ie_7.css" rendered="#{header['User-Agent'].contains('; MSIE 7')}" />
YoelBen
  • 113
  • 8
  • Header sniffing is technically less reliable than conditional comments. Conditional comments work for 100% sure in IE, while request headers can be spoofed/hacked by the client. – BalusC Jul 30 '12 at 14:33
  • Yes you're right, i learn something! Link about BalusC comment : http://msdn.microsoft.com/en-us/library/ms537509(v=vs.85).aspx – YoelBen Aug 01 '12 at 11:38
2

You should not conditionally declare <html> elements.

What if somebody who is using Chrome, or Firefox wants to visit your site?

The accepted practice is to create IE version specific .css file and load this files conditionally using IE macros.

e.g

<link href="global_styles.css" rel="stylesheet" type="text/css"/>
<!--[if IE 7]-->
<link href="IE7_styles.css" rel="stylesheet" type="text/css"/>
<![endif]-->
<!--[if lte IE 6]-->
<link href="IE6_styles.css" rel="stylesheet" type="text/css"/>
<![endif]-->

In IE6_styles.css, you may add some specific attributes to html class, and maybe * html hack. The beauty of this approach, is that it will function in old IE browsers, but will not break the modern ones.

BTW, this example is from "CSS: the missing manual" by David McFarland.

Alexander Pogrebnyak
  • 44,836
  • 10
  • 105
  • 121
  • OP's snippet is coming from html5boilerplate.com. – BalusC Jul 30 '12 at 12:59
  • Creating a bunch of .css files is what I do not want to do because what I got is one large css. If there is no choice then I got a lot of work preparing specific css files. – michal777 Jul 30 '12 at 13:09