I have a form using "#states" (in the Relation module), and it works, but it kind of jumps around. A nice slideDown would be so much better.

How can I do that instead of just making it visible?

  • I'd love to know this too. It would be nice to easily define the transition, rather than have the form abruptly change when an option is selected. Sep 23, 2011 at 15:34

3 Answers 3


Building on Mike's post, the code above only made the element side down, not back up again. To get it to slide up and down I added e.stopPropagation(); so the full code is:

jQuery(document).ready(function($) {
    $('form.slide').bind('state:visible', function(e) {
        if(e.trigger) {
            $(e.target).closest('.form-item, .form-submit, .form-wrapper')[e.value ? 'slideDown' : 'slideUp']();

I assume you're using the visible state?

The code that is responsible for doing this is in states.js:

$(document).bind('state:visible', function(e) {
    if (e.trigger) {
      $(e.target).closest('.form-item, .form-submit, .form-wrapper')[e.value ? 'show' : 'hide']();

As you can see, it calls show/hide without any configurable parameters, which means that it can't be easily changed.

However, the comment above that block is interesting:

 * Global state change handlers. These are bound to "document" to cover all
 * elements whose state changes. Events sent to elements within the page
 * bubble up to these handlers. We use this system so that themes and modules
 * can override these state change handlers for particular parts of a page.

If I understand this correctly, you can override the event handler for your specific page element, e.g. the form or even single form elements, by adding something like this:

$('form.your-form-class').bind('state:visible', function(e) {
  if (e.trigger) {
    $(e.target).closest('.form-item, .form-submit, .form-wrapper')[e.value ? 'slideDown' : 'slideUp']();

I guess you will need to return FALSE to prevent that the event bubbles up further in the DOM tree.

  • Worked beautifully! If you're doing this inline (which I wouldn't recommend) replace $'s with jQuery and wrap in drupal_add_js("[Berdir's code here]", array('type' => 'inline', 'scope' => 'footer')); Jun 29, 2012 at 0:58
  • It would be cool if someone could update this to also work with jquerys new .on() instead of .bind().
    – Letharion
    Feb 15, 2013 at 11:03
  • You should not react to the document.ready event. You should be using a drupal behavior. Jan 13, 2014 at 19:35

Building on Berdir's post, I was able to tweak it and get it working in a custom module.

So in my .module file I added this line under the hook_init() function

function er_init(){

Then in the custom.js file,

  jQuery('form#user-profile-form').bind('state:visible', function(e) {
    if (e.trigger) {
      jQuery(e.target).closest('.form-item, .form-submit, .form-wrapper')[e.value ? 'fadeIn' : 'fadeOut']();


Of course, in this case, it will only apply to the User Profile.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.