GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS

Written by thoughtbot

Common Markup and Style Mistakes In Rails

Here are three common mistakes we've made in the past. Nothing earth-shattering but they've now become rules of thumb to avoid when developing markup & style for our Rails apps.

  • Paragraph tags around form fields
  • Forgetting blank option in selects
  • Styling elements globally

Paragraph tags around form fields

You're marking up a form. Don't do this:

<p>
  <%= form.label :title %>
  <%= form.text_field :title %>
</p>

Why? If the attribute is required, when validation fails, the markup will look like this:

<p>
  <div class="fieldWithErrors">
    <label for="deal_title">Title</label>
  </div>
  <div class="fieldWithErrors">
    <input id="deal_title" name="deal[title]" size="30" type="text" value="" />
  </div>
</p>

Do you see the problem? There are divs inside the paragraph tags, which is invalid markup.

Invalid markup is A Bad Thing for general correctness, but it also has at least one practical implication: depending on your styles, you may not give the user nice visual feedback you could otherwise provide around a form field:

Do this instead:

<div>
  <%= form.label :title %>
  <%= form.text_field :title %>
</div>

We follow our own advice in the generated users/_form and sessions/new in Clearance.

Forgetting blank option in selects

Any dropdown without a default value should include a blank option as the default.

Don't do this:

<div>
  <%= form.label :location %>
  <%= form.select :location, Location::ALL %>
</div>

Instead do this:

<div>
  <%= form.label :location %>
  <%= form.select :location, Location::ALL, :include_blank => true %>
</div>

Why?

Required attribute

If the option is required, prefer that the user gets a validation message saying they need a location instead of accidentally assigning location to Boston when it should be New York.

Optional attribute

A blank default has no downside for an optional attribute.

Styling elements globally

It can be tempting to apply specific styles directly to elements to achieve results quickly. The risk of style collisions increases as soon as style is applied directly to an element.

If a style should only apply to one or a handful of elements, that style should be within an appropriate selector.

Don't do this:

input {
  float: left;
  clear: both;
}

Instead do this:

form#new_user #first_name.text_field input {
  float: left;
  clear: both;
}

This becomes a particularly troublesome issue with styles that affect the box model (margin, padding, border) and layout (floating, display, position).

Writing style to remain specific to page elements will save you from having to troubleshoot many strange layout bugs, and also saves you from having to reset these styles for any subsequent elements.