Removing module stylesheets in a Drupal 7 theme

When building sites in Drupal with custom themes (which is pretty much always what I do), you often find a desire to remove stylesheets added by the Drupal core or additional modules. There are a few reasons why you might want to do this, not least to have clean tidy HTML, and avoiding having to override certain style choices made by the Drupal core team that don't fit the theme you are working on. Drupal 7 seems to have changed the way you do this, along with a whole heap of other theming changes.

In Drupal 6, there were a couple of established ways of removing module stylesheets when using a particular theme. These included setting overrides to blank files in the theme's .info file, or using a page preprocess function in your template.php. I prefer the latter method, as it gives me more control over the matching algorithm for which CSS files to remove. For example, I might remove all CSS related to a particular module (e.g. Panels), or only remove module CSS for non-logged in users. Here's what I would generally use in my template.php for D6:


function theme_preprocess_page(&$variables) {
    theme_remove_stylesheets($variables);
}

function theme_remove_stylesheets(&$variables) {
    //this bit is used to remove unwanted css files from the end user template to improve download
    //speed and keep the html/css cleaner
    $original_css = drupal_add_css();
    $css_to_remove = array(); //array holding css files to remove

    //put some logic here to choose which CSS files to remove
    $css_to_remove[] = drupal_get_path('module','system').'/system.css';
    $css_to_remove[] = drupal_get_path('module','system').'/system-menus.css';

    // now we can remove these stylesheets from the array
    foreach ($css_to_remove as $index => $css_file) {
      unset($original_css['all']['module'][$css_file]);
    }

    //re-save new css file list to template variables
    $variables['css'] = $original_css;
    $variables['styles'] = drupal_get_css($original_css);
}

Thanks to Andrew in the comments below for pointing out my omission that with all the example theme hook functions on this page, you would need to replace the "theme" text at the start of each function name with the name of your theme. e.g. if your theme was named zen, the hook function name would be zen_preprocess_page

In Drupal 7, not only are the template preprocess function many and varied, but we don't seem to be able to access the CSS index of the $variables array an more. I'd love to hear comments on whether it's still possible to modify this? It seems the new way to do this is via a new hook which can be implemented by module or themes - hook_css_alter. You can implement this hook in your template.php and have access to the $css file array as a function parameter reference and simply unset the values you don't want. It's a lot simpler than before, but I am as yet unclear where this falls in the page execution cycle, and whether it is before or after drupal_add_css() calls made in preprocess functions. In the most basic form, here's an example of what you need to include in your template.php:


function theme_css_alter(&$css) {
    unset($css[drupal_get_path('module','system').'/system.base.css']);
    unset($css[drupal_get_path('module','system').'/system.menus.css']);
}

For debugging and to make the code easier to read, I prefer to put these all in an array before removing:


function theme_css_alter(&$css) {
    //make a list of module css to remove
    $css_to_remove = array();
    $css_to_remove[] = drupal_get_path('module','system').'/system.base.css';
    $css_to_remove[] = drupal_get_path('module','system').'/system.menus.css';
	
    // now we can remove the contribs from the array
    foreach ($css_to_remove as $index => $css_file) {
      unset($css[$css_file]);
    }
}

Drupal 7 also splits some of the system CSS up, which is great, as it gives you more flexibility on what system styling you want to include. I'd have liked to have seen a bit more of this though (maybe a system.forms.css?), especially as it seems to be aggregated on most sites anyway.