diff --git a/core/modules/block/block.api.php b/core/modules/block/block.api.php
index d33f594..72c950d 100644
--- a/core/modules/block/block.api.php
+++ b/core/modules/block/block.api.php
@@ -197,6 +197,8 @@ function hook_block_save($delta = '', $edit = array()) {
  *     have a default title, this should be set to NULL.
  *   - content: The content of the block's body. This may be a renderable array
  *     (preferable) or a string containing rendered HTML content.
+ *   - attributes: (optional) Additional attributes array to apply to the block
+ *     when rendered.
  *
  * For a detailed usage example, see block_example.module.
  *
@@ -211,6 +213,7 @@ function hook_block_view($delta = '') {
   switch ($delta) {
     case 'syndicate':
       $block['subject'] = t('Syndicate');
+      $block['attributes']['class'][] = 'syndicate';
       $block['content'] = array(
         '#theme' => 'feed_icon',
         '#url' => 'rss.xml',
@@ -221,6 +224,7 @@ function hook_block_view($delta = '') {
     case 'recent':
       if (user_access('access content')) {
         $block['subject'] = t('Recent content');
+        $block['attributes']['class'][] = 'recentcontent';
         if ($nodes = node_get_recent(variable_get('node_recent_block_count', 10))) {
           $block['content'] = array(
             '#theme' => 'node_recent_block',
@@ -251,6 +255,7 @@ function hook_block_view($delta = '') {
  *   - content: Either a string or a renderable array representing the content
  *     of the block. You should check that the content is an array before trying
  *     to modify parts of the renderable structure.
+ *   - attributes: An array of attributes to apply to the block.
  * @param $block
  *   The block object, as loaded from the database, having the main properties:
  *   - module: The name of the module that defined the block.
diff --git a/core/modules/block/block.module b/core/modules/block/block.module
index 920090f..b23a7cd 100644
--- a/core/modules/block/block.module
+++ b/core/modules/block/block.module
@@ -930,8 +930,6 @@ function template_preprocess_block(&$variables) {
   // Create the $content variable that templates expect.
   $variables['content'] = $variables['elements']['#children'];
 
-  $variables['classes_array'][] = drupal_html_class('block-' . $variables['block']->module);
-
   // Add default class for block content.
   $variables['content_attributes_array']['class'][] = 'content';
 
@@ -947,8 +945,25 @@ function template_preprocess_block(&$variables) {
   // hyphens to underscores in block deltas for the theme suggestions.
   $variables['theme_hook_suggestions'][] = 'block__' . $variables['block']->module . '__' . strtr($variables['block']->delta, '-', '_');
 
-  // Create a valid HTML ID and make sure it is unique.
-  $variables['block_html_id'] = drupal_html_id('block-' . $variables['block']->module . '-' . $variables['block']->delta);
+  // Construct the attributes array for the rendered block.
+  $attributes = isset($variables['block']->attributes) ? $variables['block']->attributes : array();
+
+  // Retrieve the ID for the block.
+  if (!isset($attributes['id'])) {
+    // Create a valid HTML ID and make sure it is unique.
+    $variables['block_html_id'] = drupal_html_id('block-' . $variables['block']->module . '-' . $variables['block']->delta);
+    $attributes['id'] = $variables['block_html_id'];
+  }
+  else {
+    // We are providing an explicit ID for the block, so use that.
+    $variables['block_html_id'] = $attributes['id'];
+  }
+
+  // Inject the classes into the attributes array and the template system.
+  $attributes['class'][] = 'block';
+  $attributes['class'][] = drupal_html_class('block-' . $variables['block']->module);
+  $variables['classes_array'] = $attributes['class'];
+  $variables['attributes_array'] = $attributes;
 }
 
 /**
diff --git a/core/modules/block/block.tpl.php b/core/modules/block/block.tpl.php
index c1025c3..c2ff12c 100644
--- a/core/modules/block/block.tpl.php
+++ b/core/modules/block/block.tpl.php
@@ -10,13 +10,12 @@
  * - $block->module: Module that generated the block.
  * - $block->delta: An ID for the block, unique within each module.
  * - $block->region: The block region embedding the current block.
- * - $classes: String of classes that can be used to style contextually through
- *   CSS. It can be manipulated through the variable $classes_array from
- *   preprocess functions. The default values can be one or more of the following:
- *   - block: The current template type, i.e., "theming hook".
- *   - block-[module]: The module generating the block. For example, the user module
- *     is responsible for handling the default user navigation block. In that case
- *     the class would be "block-user".
+ * - $block->attributes: An array of attributes to apply to the block itself.
+ *   This generally holds a number of values:
+ *   - id: The ID name for the block (block-[module]-[delta]).
+ *   - class: An array of classes to apply to the block (block-[module]).
+ * - $attributes: String of attributes that should be applied to the block. This
+ *   is generated from the $block->attributes variable.
  * - $title_prefix (array): An array containing additional output populated by
  *   modules, intended to be displayed in front of the main title tag that
  *   appears in the template.
@@ -25,8 +24,9 @@
  *   the template.
  *
  * Helper variables:
- * - $classes_array: Array of html class attribute values. It is flattened
- *   into a string within the variable $classes.
+ * - $attributes_array: An array of attributes to associate with the block.
+ * - $classes_array: An array of class to style the block.
+ * - $classes: A string representing all the classes to apply to the block.
  * - $block_zebra: Outputs 'odd' and 'even' dependent on each block region.
  * - $zebra: Same output as $block_zebra but independent of any block region.
  * - $block_id: Counter dependent on each block region.
@@ -41,8 +41,7 @@
  * @see template_process()
  */
 ?>
-<div id="<?php print $block_html_id; ?>" class="<?php print $classes; ?>"<?php print $attributes; ?>>
-
+<div<?php print $attributes; ?>>
   <?php print render($title_prefix); ?>
 <?php if ($block->subject): ?>
   <h2<?php print $title_attributes; ?>><?php print $block->subject ?></h2>
diff --git a/core/modules/system/system.module b/core/modules/system/system.module
index e2e16ae..da6a112 100644
--- a/core/modules/system/system.module
+++ b/core/modules/system/system.module
@@ -2064,6 +2064,8 @@ function system_block_view($delta = '') {
       if (isset($system_menus[$delta])) {
         $block['subject'] = t($system_menus[$delta]);
         $block['content'] = menu_tree($delta);
+        // System menu blocks should get the same class as menu module blocks.
+        $block['attributes']['class'][] = 'block-menu';
         return $block;
       }
       break;
@@ -2071,16 +2073,6 @@ function system_block_view($delta = '') {
 }
 
 /**
- * Implements hook_preprocess_block().
- */
-function system_preprocess_block(&$variables) {
-  // System menu blocks should get the same class as menu module blocks.
-  if ($variables['block']->module == 'system' && in_array($variables['block']->delta, array_keys(menu_list_system_menus()))) {
-    $variables['classes_array'][] = 'block-menu';
-  }
-}
-
-/**
  * Provide a single block on the administration overview page.
  *
  * @param $item
