Search code examples
htmljsfjsf-2conditional-commentsomnifaces

JSF 2 how to set html style depending on browser version


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


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