FrankHQ.io

Whatever...

Adding IE Version Specific Class Names to the <html> Tag...

…Without Using Conditional Comments.

Most of us will be familiar with Paul Irish’s Conditional stylesheets vs CSS hacks post , which makes some valid points on hackless styling for different versions of Internet Exploder.

He proposed the following solution:

1
2
3
4
5
<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="ie6"> <![endif]-->
<!--[if IE 7]>         <html class="ie7"> <![endif]-->
<!--[if IE 8]>         <html class="ie8"> <![endif]-->
<!--[if gt IE 8]><!--> <html>         <!--<![endif]-->

Great! This allows us to keep browser specific classes in the main stylesheet and keep the CSS pure and hack-free. Super Great!

1
2
div.foo { color: #000; }
.ie7 div.foo { color: #FC0; }

Doing it in Rails

Although it is entirely possible to mimic the above in Rails, there is room for much improvement as a friend pointed out. The suggestion was to determine the IE version from request.user_agent and generate the <html> tag from that. So Instead of having many conditional <html> tags, there will be a single <html> tag with the appropriate CSS classes.

The Ruby

Add the useragent gem to your Gemfile and run bundle install

Gemfile
1
gem "useragent"

Create a new initializer in the initializers folder and add the following code to it:

1
2
# Browser object used for UserAgent comparison
Browser = Struct.new(:browser, :version)

Next is the html_tag helper in application_helper.rb. Using the useragent gem we can detect the current version of IE and add the appropriate class to the <html> tag. Additionally the lang attribute is set using the default Rails locale.

app/helpers/application_helper.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
module ApplicationHelper

  def html_tag(options={}, &block)
    css     = ["no-js"]
    browser = UserAgent.parse(request.user_agent)
    ie7     = Browser.new("Internet Explorer", "7.0")
    ie8     = Browser.new("Internet Explorer", "8.0")

    if browser < ie7
      css << ["oldie", "lt-ie7"]
    elsif browser == ie7
      css << ["oldie", "ie7"]
    elsif browser == ie8
      css << ["oldie", "ie8"]
    end

    output = ActiveSupport::SafeBuffer.new
    output.safe_concat(tag(:html, {class: css, lang: I18n.default_locale}, true))
    output << capture(&block)
    output.safe_concat("</html>")
  end

end

Lastly, it’s a simple matter of using it in the application layout view. This example uses slim instead of erb.

app/views/layouts/application.html.slim
1
2
3
4
5
6
doctype 5
= html_tag do
  head
    title Cool App
  body
    p Hello!

The Generated HTML

Default (All modern browsers and IE9+)

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html class="no-js" lang="en">
  <head>
    <title>Cool App</title>
  </head>
  <body>
    <p>Hello!</p>
  </body>
</html>

IE8

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html class="no-js oldie ie8" lang="en">
  <head>
    <title>Cool App</title>
  </head>
  <body>
    <p>Hello!</p>
  </body>
</html>

IE7

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html class="no-js oldie ie7" lang="en">
  <head>
    <title>Cool App</title>
  </head>
  <body>
    <p>Hello!</p>
  </body>
</html>

IE versions less than 7

1
2
3
4
5
6
7
8
9
<!DOCTYPE html>
<html class="no-js oldie lt-ie7" lang="en">
  <head>
    <title>Cool App</title>
  </head>
  <body>
    <p>Hello!</p>
  </body>
</html>

#HappyCoding

Stick a Fork in it!

Development, Rails

« Access a Rails 3 App's Routes at Runtime Web Development »