diff --git a/css/webform.css b/css/webform.css
index ce3d42f..daacb05 100644
--- a/css/webform.css
+++ b/css/webform.css
@@ -10,6 +10,20 @@ input.webform-calendar {
 html.js input.webform-calendar {
   display: inline;
 }
+fieldset.webform-container {
+  background: transparent;
+  border: none;
+  padding: 0;
+  margin: 0;
+  position: static;
+  height: auto;
+  width: auto;
+  left: auto;
+  top: auto;
+}
+fieldset.webform-container legend.webform-container-legend {
+  display: none;
+}
 .webform-container-inline label {
   display: inline;
   margin-right: 1em;
diff --git a/webform.module b/webform.module
index b8171c4..6b05c6d 100644
--- a/webform.module
+++ b/webform.module
@@ -2721,7 +2721,7 @@ function _webform_client_form_add_component($node, $component, $component_value,
  */
 function webform_client_form_prevalidate($form, &$form_state) {
   global $user;
-  
+
   $node = $form['#node'];
   $finished = $form_state['values']['details']['finished'];
 
@@ -3326,7 +3326,13 @@ function theme_webform_element($variables) {
     $wrapper_classes[] = 'webform-container-inline';
   }
   $wrapper_attributes['class'] = isset($wrapper_attributes['class']) ? array_merge($wrapper_classes, $wrapper_attributes['class']) : $wrapper_classes;
-  $output = '<div ' . drupal_attributes($wrapper_attributes) . '>' . "\n";
+
+  // If there are multiple elements, a label cannot point to all of them.
+  // Removing the ID on the element will remove the label "for" attribute.
+  $multiple_elements = count(element_children($element)) > 1;
+  if ($multiple_elements) {
+    $variables['element']['#id'] = NULL;
+  }
 
   // If #title_display is none, set it to invisible instead - none only used if
   // we have no title at all to use.
@@ -3343,6 +3349,7 @@ function theme_webform_element($variables) {
   }
   $prefix = isset($element['#field_prefix']) ? '<span class="field-prefix">' . webform_filter_xss($element['#field_prefix']) . '</span> ' : '';
   $suffix = isset($element['#field_suffix']) ? ' <span class="field-suffix">' . webform_filter_xss($element['#field_suffix']) . '</span>' : '';
+  $output = '';
 
   switch ($element['#title_display']) {
     case 'inline':
@@ -3368,9 +3375,27 @@ function theme_webform_element($variables) {
     $output .= ' <div class="description">' . $element['#description'] . "</div>\n";
   }
 
-  $output .= "</div>\n";
+  // If this is a group of elements, display as a fieldset for accessibility.
+  // This legend is *always* hidden by CSS, and it's intentional that is be
+  // hidden because fieldset legends cannot be styled adequately (i.e. cannot
+  // be "display: inline"). The "label" tag is rendered above, inline, or hidden
+  // like normal, while the "legend" tag provides screenreader accessibility,
+  // allowing each element name to be repeated.
+  if ($multiple_elements) {
+    $grouped_output = $output;
+    $output = '';
+    $output .= '<fieldset class="webform-container">';
+    $output .= '<legend class="webform-container-legend">' . $element['#title'] . '</legend>';
+    $output .= $grouped_output;
+    $output .= '</fieldset>';
+  }
 
-  return $output;
+  // Then wrap the whole thing in our main wrapper.
+  $wrapped_output = '<div ' . drupal_attributes($wrapper_attributes) . '>' . "\n";
+  $wrapped_output .= $output;
+  $wrapped_output .= "</div>\n";
+
+  return $wrapped_output;
 }
 
 /**
