diff --git a/django/forms/widgets.py b/django/forms/widgets.py
index ba6f9c5b9a..41263b0905 100644
--- a/django/forms/widgets.py
+++ b/django/forms/widgets.py
@@ -690,7 +690,8 @@ class CheckboxSelectMultiple(SelectMultiple):
if value is None: value = []
final_attrs = self.build_attrs(attrs, name=name)
id_ = final_attrs.get('id', None)
- output = ['
']
+ start_tag = format_html('', id_) if id_ else ''
+ output = [start_tag]
# Normalize to strings
str_values = set([force_text(v) for v in value])
for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index 7218e41082..45d9e8a4dc 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -648,6 +648,11 @@ Selector and checkbox widgets
...
+.. versionchanged:: 1.6
+
+The outer ```` container will now receive the ``id`` attribute defined on
+the widget.
+
.. _file-upload-widgets:
File upload widgets
diff --git a/tests/forms_tests/tests/test_forms.py b/tests/forms_tests/tests/test_forms.py
index cf63acb57c..49a93b2ad0 100644
--- a/tests/forms_tests/tests/test_forms.py
+++ b/tests/forms_tests/tests/test_forms.py
@@ -533,7 +533,7 @@ class FormsTestCase(TestCase):
composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple)
f = SongForm(auto_id='%s_id')
- self.assertHTMLEqual(str(f['composers']), """
+ self.assertHTMLEqual(str(f['composers']), """""")
diff --git a/tests/forms_tests/tests/test_widgets.py b/tests/forms_tests/tests/test_widgets.py
index 00e45b6b02..2ecdb1d065 100644
--- a/tests/forms_tests/tests/test_widgets.py
+++ b/tests/forms_tests/tests/test_widgets.py
@@ -804,14 +804,14 @@ beatle J R Ringo False""")
self.assertHTMLEqual(w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]), '')
# Each input gets a separate ID
- self.assertHTMLEqual(CheckboxSelectMultiple().render('letters', list('ac'), choices=zip(list('abc'), list('ABC')), attrs={'id': 'abc'}), """
+ self.assertHTMLEqual(CheckboxSelectMultiple().render('letters', list('ac'), choices=zip(list('abc'), list('ABC')), attrs={'id': 'abc'}), """""")
# Each input gets a separate ID when the ID is passed to the constructor
- self.assertHTMLEqual(CheckboxSelectMultiple(attrs={'id': 'abc'}).render('letters', list('ac'), choices=zip(list('abc'), list('ABC'))), """
+ self.assertHTMLEqual(CheckboxSelectMultiple(attrs={'id': 'abc'}).render('letters', list('ac'), choices=zip(list('abc'), list('ABC'))), """