CSS styling in Django forms CSS styling in Django forms django django

CSS styling in Django forms


Taken from my answer to:How to markup form fields with <div class='field_type'> in Django

class MyForm(forms.Form):    myfield = forms.CharField(widget=forms.TextInput(attrs={'class': 'myfieldclass'}))

or

class MyForm(forms.ModelForm):    class Meta:        model = MyModel    def __init__(self, *args, **kwargs):        super(MyForm, self).__init__(*args, **kwargs)        self.fields['myfield'].widget.attrs.update({'class': 'myfieldclass'})

or

class MyForm(forms.ModelForm):    class Meta:        model = MyModel        widgets = {            'myfield': forms.TextInput(attrs={'class': 'myfieldclass'}),        }

--- EDIT ---
The above is the easiest change to make to original question's code that accomplishes what was asked. It also keeps you from repeating yourself if you reuse the form in other places; your classes or other attributes just work if you use the Django's as_table/as_ul/as_p form methods. If you need full control for a completely custom rendering, this is clearly documented

-- EDIT 2 ---
Added a newer way to specify widget and attrs for a ModelForm.


This can be done using a custom template filter. Consider rendering your form this way:

<form action="/contact/" method="post">  {{ form.non_field_errors }}  <div class="fieldWrapper">    {{ form.subject.errors }}    {{ form.subject.label_tag }}    {{ form.subject }}    <span class="helptext">{{ form.subject.help_text }}</span>  </div></form>

form.subject is an instance of BoundField which has the as_widget() method.

You can create a custom filter addclass in my_app/templatetags/myfilters.py:

from django import templateregister = template.Library()@register.filter(name='addclass')def addclass(value, arg):    return value.as_widget(attrs={'class': arg})

And then apply your filter:

{% load myfilters %}<form action="/contact/" method="post">  {{ form.non_field_errors }}  <div class="fieldWrapper">    {{ form.subject.errors }}    {{ form.subject.label_tag }}    {{ form.subject|addclass:'MyClass' }}    <span class="helptext">{{ form.subject.help_text }}</span>  </div></form>

form.subjects will then be rendered with the MyClass CSS class.


If you don't want to add any code to the form (as mentioned in the comments to @shadfc's Answer), it is certainly possible, here are two options.

First, you just reference the fields individually in the HTML, rather than the entire form at once:

<form action="" method="post">    <ul class="contactList">        <li id="subject" class="contact">{{ form.subject }}</li>        <li id="email" class="contact">{{ form.email }}</li>        <li id="message" class="contact">{{ form.message }}</li>    </ul>    <input type="submit" value="Submit"></form>

(Note that I also changed it to a unsorted list.)

Second, note in the docs on outputting forms as HTML, Django:

The Field id, is generated by prepending 'id_' to the Field name. The id attributes and tags are included in the output by default.

All of your form fields already have a unique id. So you would reference id_subject in your CSS file to style the subject field. I should note, this is how the form behaves when you take the default HTML, which requires just printing the form, not the individual fields:

<ul class="contactList">    {{ form }}  # Will auto-generate HTML with id_subject, id_email, email_message     {{ form.as_ul }} # might also work, haven't tested</ul>

See the previous link for other options when outputting forms (you can do tables, etc).

Note - I realize this isn't the same as adding a class to each element (if you added a field to the Form, you'd need to update the CSS also) - but it's easy enough to reference all of the fields by id in your CSS like this:

#id_subject, #id_email, #email_message {color: red;}