HtmlProperties XHTML and HTML5

HtmlProperties, XHTML and HTML5

Lift unifies many aspects of parsing and displaying the HTML page in a single trait,HtmlProperties.HtmlProperties defines, on a session-by-session basis, the way that templates are parsed and the way that Scala’sNodeSeq is converted into valid HTML output. The properties on HtmlProperties are:

XHTML viaOldHtmlProperties

The default properties that keep compability with the disparate LiftRules used to calculate DocType and Encoding. Uses thePCDataXmlParserparser which requires well-formed XML files. Output is generally XHTML viaAltXML.toXML, but cerain tags are written in IE6/IE7 friendly ways.

HTML5 viaHtml5Properties

Prior to Lift 2.2, Lift always emitted XHTML and by default set the Content-Type header toapplication/xhtml+xml; charset=utf-8. This continues to be Lift’s default behavior. It turns out that most browsers, even modern ones had issues with XHTML. Further, XHTML limited the behavior of certain JavaScript libraries. By invoking LiftRules.htmlProperties.default.set((r: Req) =>new Html5Properties(r.userAgent)) in Boot.scala, you can set Lift to full HTML5 support.

Lift uses the nu.validator HTML parser. This parser tries to fix broken HTML and will do so rather than throwing an exception. This sometimes causes confusion, especially when converting from XHTML or using older example code. If you’re using Html5, read this page completely before posting to the Lift mailing list about stuff that’s not working… especially the part about snippet invocation syntax. Also, please note that we are using this library, but have no control over it, so we can’t change its behavior.

Lift emits the correct DocType and response headers such that all tested browsers render tags correctly . Because the HTML5 parser is different from the standard XML parser, you will need to adjust your existing templates in the following ways:

head merge in HTML5

Since the parser strips any head tag not directly following an html tag, you need to use the head_merge tag if your templates contain head elements that should be merged into the final pages’s head element.


    <div id="main" class="lift:surround?with=default&at=content">

        <head_merge>
            <title>My page title</title>
            <script>
                $(function(){
                   $('#dummy').click(function(){ alert('foo'); });
                });
            </script>
        </head_merge>
    
        <button id="dummy">ok</button>

    </div>

Changing behavior mid-session or mid-request

for {
  ses <- S.session
  req <- S.request
} ses.requestHtmlProperties.set(new Html5Properties(req.userAgent))