Sass: Create mixin for input fields

compass-sasssass

I'm new to Sass so I need help with the creation of a mixing for my input fields.

However, if anyone knows of an already made mixin for this or if Compass has one that accomplishes this, please let me (us) know.

I currently have the following CSS rules in my .scss file:

input[type="text"],
input[type="password"],
input[type="email"],
input[type="search"],
input[type="url"],
textarea, 
select { ... }

input[type="text"]:hover,
input[type="text"]:focus,
input[type="password"]:hover,
input[type="password"]:focus,
input[type="email"]:hover,
input[type="email"]:focus,
input[type="search"]:hover,
input[type="search"]:focus,
input[type="url"]:hover,
input[type="url"]:focus,
textarea:hover,
textarea:focus,
select:hover,
select:focus  { ... }

Now, as we know HTML5 provides a nice new set of input types, but right now I don't need to add input types like date, month or week, that's why I don't have them listed "yet".

So in the case I need to add them in the future, I'll update that list you see above.

However, my problem is that I feel I'm repeating myself all over here, plus, the work of selecting items, copying, pasting and editing every time for every new input type I add to the list is just plain dumb and I almost sure Sass' mixins can be of help with this. The problem is that creating a mixin for this is honestly very confusing to me.

I've looked around here and the web for something similar but haven't been able to find anything.

Any help with this is greatly appreciated.

Best Answer

Ok, I eventually found the Sass mixing library Bourbon.

They have an 'add-on' for HTML5 input types (here's a link to the .scss file they created), but it doesn't have the :hover or :focus pseudo elements. So I added them.

I honestly don't know if what I did is the best way to write this mixin, but the thing works marvelously:

//************************************************************************//
// Generate a variable ($all-text-inputs) with a list of all html5
// input types that have a text-based input, excluding textarea.
// http://diveintohtml5.org/forms.html
//************************************************************************//
$inputs-list: 'input[type="email"]',
              'input[type="number"]',
              'input[type="password"]',
              'input[type="search"]',
              'input[type="tel"]',
              'input[type="text"]',
              'input[type="url"]',

              // Webkit & Gecko may change the display of these in the future
              'input[type="color"]',
              'input[type="date"]',
              'input[type="datetime"]',
              'input[type="datetime-local"]',
              'input[type="month"]',
              'input[type="time"]',
              'input[type="week"]';

$unquoted-inputs-list: ();

@each $input-type in $inputs-list {
  $unquoted-inputs-list: append($unquoted-inputs-list, unquote($input-type), comma);
}

$all-text-inputs: $unquoted-inputs-list;

// You must use interpolation on the variable:
// #{$all-text-inputs}
//************************************************************************//
//   #{$all-text-inputs}, textarea {
//     border: 1px solid red;
//   }

// :hover and :focus pseudo elements
// Added by Ricardo Zea
// http://ricardozea.net
// @ricardozea
// Tracking: http://stackoverflow.com/questions/13180807/sass-create-mixin-for-input-fields

$inputs-list-hf:'input[type="email"]:hover',
                'input[type="number"]:hover',
                'input[type="password"]:hover',
                'input[type="search"]:hover',
                'input[type="tel"]:hover',
                'input[type="text"]:hover',
                'input[type="url"]:hover',
                'input[type="color"]:hover',
                'input[type="date"]:hover',
                'input[type="datetime"]:hover',
                'input[type="datetime-local"]:hover',
                'input[type="month"]:hover',
                'input[type="time"]:hover',
                'input[type="week"]:hover',

                'input[type="email"]:focus',
                'input[type="number"]:focus',
                'input[type="password"]:focus',
                'input[type="search"]:focus',
                'input[type="tel"]:focus',
                'input[type="text"]:focus',
                'input[type="url"]:focus',
                'input[type="color"]:focus',
                'input[type="date"]:focus',
                'input[type="datetime"]:focus',
                'input[type="datetime-local"]:focus',
                'input[type="month"]:focus',
                'input[type="time"]:focus',
                'input[type="week"]:focus';

$unquoted-inputs-list-hf: ();

@each $input-type-hf in $inputs-list-hf {
  $unquoted-inputs-list-hf: append($unquoted-inputs-list-hf, unquote($input-type-hf), comma);
}

$all-text-inputs-hf: $unquoted-inputs-list-hf;

// You must use interpolation on the variable:
// #{$all-text-inputs-hf}
//************************************************************************//
//   #{$all-text-inputs-hf}, textarea {
//     border: 1px solid red;
//   }

As you can see I copied and pasted the original mixing and added the prefix -hf and of course the :hover and :focus to the new rules.

And in my .scss file I added this @import:

@import "html5-input-types"; (no need for the underline _ or file extension .scss)

And in the 'Forms' section of my .scss file I added these rules:

/*Normal state*/
#{$all-text-inputs}, 
textarea,
select { ... }

/*:hover and :focus states*/
#{$all-text-inputs-hf}, 
textarea:hover, 
textarea:focus,
select:hover,
select:focus { ... }

I know I have textarea and select outside the mixin file (html5-input-types.scss), not sure yet if I'm including them in it or not, gotta think about it.

Anyway, this worked for me pretty well and although I will still need to update the html5-input-types.scss if anything changes in the future, at least I'm handling these input fields way more efficiently than before.

Hopefully what I did here helps someone else.

And if any of you has a suggestion to improve the mixin, by all means let me (us) know.

Thanks.