Question

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...

Was it helpful?

Solution

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>.

OTHER TIPS

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')}" />

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top