The missing Html5 template of ASP.NET MVC3
In my last post, I mentioned that the default template that comes with the ASP.NET MVC would not renders properly if you use any of the new Html5 elements like article, section, header etc etc, before moving forward let me show you a brief example, lets say you are using the following markup in your view:
<section>I am inside of the section element.</section>
I am outside of section element.
Now, if you run it in a browser that does not aware of Html5, it will render like the following.
section renderingAs you can see it is rendering as inline element instead of block which section really is. The initial fix is pretty simple, just add the following css rules:
section {
display: block;
}
It will fix most of the older browsers that are not aware of Html5, except IE. Older IEs (prior IE9) requires special handling, to fix it, you have to add the following JavaScript code:
document.createElement("section")
Now, when you run it, it will render like the following, which is correct.
section renderingNow, Remy Sharp co-author of Introducing HTML5 Book came up with a script called html5shiv, it iterates all of the new Html5 elements and calls the document.createElement(), so that you do not have to do it for individual element like I shown in the above. Just add it in your head section with conditional include so that it only executes when the page is viewed in older versions of IE.
<!--[if lt IE 9]>
<script src="http://html5shiv.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
One caveat of html5shiv is, it does not handle the elements that are added by DOM manipulation, in that case you should check innerShiv.
Next, Modernizr which recently won the .Net Magazine Award (do not confuse with Microsoft .NET) in open source category takes this browser compatibility issue in next level. It not only makes older browser compatible with Html5 but also detects the Html5 and CSS3 features which you can use to develop a complete new user experience or fallback depending upon the browser support. The usage is also pretty simple, first you will add a special class in the html element and then add the script in the head section, like the following:
<html class="no-js">
<head>
<script src="js/modernizr-1.6.min.js"></script>
</head>
</html>
Now, when you run this page with the above, you will find that it adds quite a number of values in the html element class value, for example if you run this blog in FireFox 3.6.12, the firebug will show you the following:
<html class="js flexbox canvas canvastext no-webgl no-touch geolocation
postmessage no-websqldatabase no-indexeddb hashchange no-history
draganddrop no-websockets rgba hsla multiplebgs backgroundsize
borderimage borderradius boxshadow textshadow opacity no-cssanimations
csscolumns cssgradients no-cssreflections csstransforms no-csstransforms3d
no-csstransitions fontface video audio localstorage sessionstorage
webworkers applicationcache svg no-inlinesvg no-smil svgclippaths">
</html>
These are nothing but the features that the current browser supports, if a feature is not supported, the Modernizr will prefix it with no-(don’t worry about html validity, it is completely valid html). So how can we take the advantage of this? Lets see an example of NerdDinner which I recently upgraded to Html5 + Mobile for Hanselman, In NerdDinner there are several gradient images are used but we know that the Css3 has decent support for gradient, so I used the Css3 gradient by default but if the browser does not have the support for gradient, it will fallback to the image version. Here is the code of the body element:
body {
background: #f7f4e6;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#fff), color-stop(.2, #f7f4e6), to(#f7f4e6));
background: -moz-linear-gradient(top, #fff, #f7f4e6 20%, #f7f4e6);
background: linear-gradient(top, #fff, #f7f4e6 20%, #f7f4e6);
color: #000;
font: 75%/1.5 helvetica, arial, clean, sans-serif;
}
.no-cssgradients body {
background: #f7f4e6 url("../images/bkg.jpg") repeat-x top left;
}
There are also several JavaScript methods in Modernizr that you can use for feature detection. You can check the Modernizr project page for details.
Now Paul Irish, developer of the Modernizr as well as jQuery core created another cool project called Html5 Boilerplate which gives you a solid foundation for building your next Html5 application. So I decided to create an ASP.NET MVC3 template based upon it. Only razor support has been added as I know all the cool kids will be using razor instead of webforms, here is the layout page, I have also replaced the non-sematic elements with proper Html5 elements.
<!DOCTYPE html>
@{ var lang = System.Globalization.CultureInfo.CurrentCulture.TwoLetterISOLanguageName.ToLowerInvariant(); }
<!--[if lt IE 7 ]> <html lang="@lang" class="no-js ie6"> <![endif]-->
<!--[if IE 7 ]> <html lang="@lang" class="no-js ie7"> <![endif]-->
<!--[if IE 8 ]> <html lang="@lang" class="no-js ie8"> <![endif]-->
<!--[if IE 9 ]> <html lang="@lang" class="no-js ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html lang="@lang" class="no-js"> <!--<![endif]-->
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>@View.Title</title>
<link href="@Url.Content("~/Content/style.css")" rel="stylesheet"/>
<link href="@Url.Content("~/Content/Site.css")" rel="stylesheet"/>
<link href="@Url.Content("~/Content/handheld.css")" rel="stylesheet" media="handheld"/>
@if (Context.IsDebuggingEnabled) {
<script src="@Url.Content("~/Scripts/modernizr-1.6.js")"></script>
}
else {
<script src="@Url.Content("~/Scripts/modernizr-1.6.min.js")"></script>
}
</head>
<body>
<div class="page">
<header role="banner">
<h1>My MVC Application</h1>
<div id="logindisplay">
@Html.Partial("_LogOnPartial")
</div>
<nav role="navigation">
<ul id="menu">
<li>@Html.ActionLink("Home", "Index", "Home")</li>
<li>@Html.ActionLink("About", "About", "Home")</li>
</ul>
</nav>
</header>
<div role="main">
@RenderBody()
</div>
<footer></footer>
</div>
@if (Context.IsDebuggingEnabled) {
<script src="@Url.Content("~/Scripts/jquery-1.4.1.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.js")"></script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.js")"></script>
<script src="@Url.Content("~/Scripts/profiling/yahoo-profiling.min.js")"></script>
<script src="@Url.Content("~/Scripts/profiling/config.js")"></script>
} else {
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.4.1.min.js"></script>
<script>!window.jQuery && document.write(unescape("%3Cscript src='@Url.Content("~/Scripts/jquery-1.4.1.min.js")'%3E%3C/script%3E"))</script>
<script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jQuery.Validate/1.6/jQuery.Validate.min.js"></script>
<script>!jQuery.validator && document.write(unescape("%3Cscript src='@Url.Content("~/Scripts/jquery.validate.min.js")'%3E%3C/script%3E"))</script>
<script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")"></script>
}
<!--[if lt IE 7 ]>
<script src="@Url.Content("~/Scripts/dd_belatedpng.js")"></script>
<script> DD_belatedPNG.fix('img, .png_bg'); //fix any <img> or .png_bg background-images </script>
<![endif]-->
</body>
</html>
The code is almost identical to the original version of Html5 Boilerplate, except I have added the ASP.NET MVC Scripts at the bottom of the page. You will find the complete project in the bottom of this post. The next thing I tried, putting it into the new create project dialog of ASP.NET MVC3, but could not figure it out, maybe the VS tooling people can shed some light on this.
That's it for today.
Download: ASPNETMVC3HTML5Boilerplate.zip
Comments
blog comments powered by Disqus