How do I add custom CSS to crispy forms?
Solution 1
As docs says, by default crispy forms using bootstrap, and also provides some template packs for bootstrap
, bootstrap3
, bootstrap4
and uni-form
. see also about Overriding project templates
If you need to custom this crispy forms, you need to create a new custom template for your project, an example crispy_forms/templates/<foobar>/
. you can checkout at this path of repository: https://github.com/django-crispy-forms/django-crispy-forms/tree/dev/crispy_forms/templates
But, previously crispy forms has templatetags to handle specific field. one of it is {{ form.field_name|as_crispy_field }}
, this example below is output of it.
<div id="div_id_email" class="control-group">
<label for="id_email" class="control-label">Email address</label>
<div class="controls">
<input class="form-control" id="id_email" maxlength="254" name="email" required="required" type="email" />
</div>
</div>
Other options, you can handle it using specific html selectors/attributes inside your forms widget, such as html class
, id
, style
, or else.
For example in your case;
class SignUpForm(forms.ModelForm):
class Meta:
model = SignUp
fields = ['full_name', 'email']
widgets = {
'email': forms.EmailInput(attrs={'class': 'form-control custom-class'}),
}
And then, if you render as {{ form.email|as_crispy_field }}
, this should render the html;
<div id="div_id_email" class="control-group">
<label for="id_email" class="control-label">Email address</label>
<div class="controls">
<input class="form-control custom-class" id="id_email" maxlength="254" name="email" required="required" type="email" />
</div>
</div>
Crispy forms also provides simply configuration inside settings.py
, Django fields generate default classes, crispy-forms handles these and adds other classes for compatibility with CSS frameworks. For example a CharField
generates an <input class="textinput"
, for more...
CRISPY_CLASS_CONVERTERS = {
'textinput': "form-control cst__radius",
'urlinput': "form-control cst__radius",
'numberinput': "form-control cst__radius",
'emailinput': "form-control cst__radius",
'dateinput': "form-control cst__radius",
'textarea': "form-control cst__radius",
'passwordinput': "form-control cst__radius",
'select': "form-control cst__radius",
}
Solution 2
You'd have to write your own CSS that would target each element of the Crispy form that you wanted to style.
Use the inspect element and find the ID/class of the element you want to work with. Write your styles in the inspect element window and once you're happy with it copy the code to a CSS file that will eventually be your "form override" file that will bring it's look more in line with the rest of your site.
Solution 3
Crispy forms provides a framework for this.
First of all, you can tell crispy_forms to use 'bootstrap4' templates:
project/settings.py
# settings
CRISPY_TEMPLATE_PACK = 'bootstrap4'
# other settings
That will render your buttons and inputs according to the Bootstrap 4 form templates
If you still want to apply styles to a specific input or button, you can use the Crispy FormHelper class and Layouts, which are, by the way, amazing.
In particular, note the .css_class='...'
parameter, which renders into HTML as class="..."
forms.py
from crispy_forms.helper import FormHelper
from crispy_forms.layout import (
Layout,
Field,
Submit,
)
class SignUpForm(forms.ModelForm):
class Meta:
model = SignUp
fields = ['full_name', 'email']
widgets = {
'email': forms.EmailInput(attrs={'class': 'form-control custom-class'}),
}
def __init__(self, *args, **kwargs):
self.helper = FormHelper(self)
self.helper.layout = Layout(
'full_name',
Field('email', css_class='custom-class') # form-control will be provided by bootstrap templates
Submit('submit', 'Sign Up', css_class='btn-primary') # define your signup button here
)
Next you can render your entire form using {% crispy form %}
. The form
tag and csrf_token
will be created by default:
signup.html
{% load crispy_forms %}
{% crispy form %}
Result
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet"/>
<form action="" method="POST">
<input type='hidden' name='csrfmiddlewaretoken' value='GLJMxnnDz1MGNFC46pjoofSlo6JMCD1IXu7X3n7LsRbQfdS38SYHJMs9IAXddcck' />
<div class="form-group">
<label for="id_full_name">Full Name</label>
<input type="text" class="form-control" id="id_full_name">
</div>
<div class="form-group">
<label for="id_email">Email <span class="required">*</span></label>
<input type="email" class="form-control custom-class" id="id_email" required>
</div>
<button type="submit" class="btn btn-primary">Sign Up</button>
</form>
uitwaa
Updated on July 02, 2022Comments
-
uitwaa almost 2 years
I'm trying to create a responsive form for my website with the help of crispy forms.I'm not using bootstrap and I want to add custom CSS to the crispy form to match my whole website.
HTML:
<form method='POST' action=''>{% csrf_token %} {{ form|crispy }} <input type='submit' value='Sign Up' /> </form>
using inspect element it shows:
<form method='POST' action=''><input type='hidden' name='csrfmiddlewaretoken' value='GLJMxnnDz1MGNFC46pjoofSlo6JMCD1IXu7X3n7LsRbQfdS38SYHJMs9IAXddcck' /> <div id="div_id_full_name" class="form-group"> <label for="id_full_name" class="control-label "> Full name </label> <div class="controls "> <input class="textinput textInput form-control" id="id_full_name" maxlength="120" name="full_name" type="text" /> </div> </div> <div id="div_id_email" class="form-group"> <label for="id_email" class="control-label requiredField"> Email<span class="asteriskField">*</span> </label> <div class="controls "> <input class="emailinput form-control" id="id_email" maxlength="254" name="email" type="email" required /> </div> </div> <!-- <input class='btn btn-primary' type='submit' value='Sign Up' />--> <input type='submit' value='Sign Up' /> </form>
forms.py:
from django import forms from .models import SignUp class ContactForm(forms.Form): full_name = forms.CharField(required=False) email = forms.EmailField() message = forms.CharField() class SignUpForm(forms.ModelForm): class Meta: model = SignUp fields = ['full_name', 'email']
models.py:
from __future__ import unicode_literals # Create your models here. from django.db import models # Create your models here. class SignUp(models.Model): email = models.EmailField() full_name = models.CharField(max_length=120, blank=True, null=True) timestamp = models.DateTimeField(auto_now_add=True, auto_now=False) updated = models.DateTimeField(auto_now_add=False, auto_now=True) def __unicode__(self): #Python 3.3 is __str__ return self.email